2 * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
3 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 675
17 * Mass Ave, Cambridge, MA 02139, USA.
24 /***************************************************************
25 Signal function to tell us we timed out.
26 ****************************************************************/
28 static void gotalarm_sig(void)
33 /***************************************************************
34 Lock or unlock a fd for a known lock type. Abandon after waitsecs
36 ****************************************************************/
38 BOOL do_file_lock(int fd, int waitsecs, int type)
40 SMB_STRUCT_FLOCK lock;
44 CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
47 lock.l_whence = SEEK_SET;
53 ret = fcntl(fd, SMB_F_SETLKW, &lock);
55 CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL);
58 DEBUG(0, ("do_file_lock: failed to %s file.\n",
59 type == F_UNLCK ? "unlock" : "lock"));
67 /***************************************************************
68 Lock an fd. Abandon after waitsecs seconds.
69 ****************************************************************/
71 BOOL file_lock(int fd, int type, int secs, int *plock_depth)
78 if ((*plock_depth) == 0)
80 if (!do_file_lock(fd, secs, type)) {
81 DEBUG(10,("file_lock: locking file failed, error = %s.\n",
90 /***************************************************************
91 Unlock an fd. Abandon after waitsecs seconds.
92 ****************************************************************/
94 BOOL file_unlock(int fd, int *plock_depth)
99 ret = do_file_lock(fd, 5, F_UNLCK);
104 DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n",
109 /***************************************************************
110 locks a file for enumeration / modification.
111 update to be set = True if modification is required.
112 ****************************************************************/
114 void *startfilepwent(char *pfile, char *s_readbuf, int bufsize,
115 int *file_lock_depth, BOOL update)
121 DEBUG(0, ("startfilepwent: No file set\n"));
124 DEBUG(10, ("startfilepwent: opening file %s\n", pfile));
126 fp = sys_fopen(pfile, update ? "r+b" : "rb");
129 DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile));
133 /* Set a buffer to do more efficient reads */
134 setvbuf(fp, s_readbuf, _IOFBF, bufsize);
136 if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth))
138 DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile));
143 /* Make sure it is only rw by the owner */
146 /* We have a lock on the file. */
150 /***************************************************************
151 End enumeration of the file.
152 ****************************************************************/
153 void endfilepwent(void *vp, int *file_lock_depth)
155 FILE *fp = (FILE *)vp;
157 file_unlock(fileno(fp), file_lock_depth);
159 DEBUG(7, ("endfilepwent: closed file.\n"));
162 /*************************************************************************
163 Return the current position in the file list as an SMB_BIG_UINT.
164 This must be treated as an opaque token.
165 *************************************************************************/
166 SMB_BIG_UINT getfilepwpos(void *vp)
168 return (SMB_BIG_UINT)sys_ftell((FILE *)vp);
171 /*************************************************************************
172 Set the current position in the file list from an SMB_BIG_UINT.
173 This must be treated as an opaque token.
174 *************************************************************************/
175 BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok)
177 return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET);
180 /*************************************************************************
181 gets a line out of a file.
182 line is of format "xxxx:xxxxxx:xxxxx:".
183 lines with "#" at the front are ignored.
184 *************************************************************************/
185 int getfileline(void *vp, char *linebuf, int linebuf_size)
187 /* Static buffers we will return. */
188 FILE *fp = (FILE *)vp;
195 DEBUG(0,("getfileline: Bad file pointer.\n"));
200 * Scan the file, a line at a time.
206 fgets(linebuf, linebuf_size, fp);
213 * Check if the string is terminated with a newline - if not
214 * then we must keep reading and discard until we get one.
217 linebuf_len = strlen(linebuf);
218 if (linebuf_len == 0)
224 if (linebuf[linebuf_len - 1] != '\n')
227 while (!ferror(fp) && !feof(fp))
238 linebuf[linebuf_len - 1] = '\0';
241 #ifdef DEBUG_PASSWORD
242 DEBUG(100, ("getfileline: got line |%s|\n", linebuf));
244 if ((linebuf[0] == 0) && feof(fp))
246 DEBUG(4, ("getfileline: end of file reached\n"));
250 if (linebuf[0] == '#' || linebuf[0] == '\0')
252 DEBUG(6, ("getfileline: skipping comment or blank line\n"));
256 p = (unsigned char *) strchr_m(linebuf, ':');
259 DEBUG(0, ("getfileline: malformed line entry (no :)\n"));
268 /****************************************************************************
269 read a line from a file with possible \ continuation chars.
270 Blanks at the start or end of a line are stripped.
271 The string will be allocated if s2 is NULL
272 ****************************************************************************/
273 char *fgets_slash(char *s2,int maxlen,XFILE *f)
278 BOOL start_of_line = True;
283 if (maxlen <2) return(NULL);
287 maxlen = MIN(maxlen,8);
288 s = (char *)malloc(maxlen);
291 if (!s) return(NULL);
295 while (len < maxlen-1)
303 while (len > 0 && s[len-1] == ' ')
307 if (len > 0 && s[len-1] == '\\')
310 start_of_line = True;
317 return(len>0?s:NULL);
322 start_of_line = False;
326 if (!s2 && len > maxlen-3)
331 t = (char *)Realloc(s,maxlen);
333 DEBUG(0,("fgets_slash: failed to expand buffer!\n"));
343 /****************************************************************************
344 load from a pipe into memory
345 ****************************************************************************/
346 char *file_pload(char *syscmd, size_t *size)
353 fd = sys_popen(syscmd);
354 if (fd == -1) return NULL;
359 while ((n = read(fd, buf, sizeof(buf))) > 0) {
360 tp = Realloc(p, total + n + 1);
362 DEBUG(0,("file_pload: failed to exand buffer!\n"));
367 memcpy(p+total, buf, n);
374 if (size) *size = total;
379 /****************************************************************************
380 load a file into memory from a fd.
381 ****************************************************************************/
383 char *fd_load(int fd, size_t *size)
385 SMB_STRUCT_STAT sbuf;
388 if (sys_fstat(fd, &sbuf) != 0) return NULL;
390 p = (char *)malloc(sbuf.st_size+1);
393 if (read(fd, p, sbuf.st_size) != sbuf.st_size) {
399 if (size) *size = sbuf.st_size;
404 /****************************************************************************
405 load a file into memory
406 ****************************************************************************/
407 char *file_load(const char *fname, size_t *size)
412 if (!fname || !*fname) return NULL;
414 fd = open(fname,O_RDONLY);
415 if (fd == -1) return NULL;
417 p = fd_load(fd, size);
425 /****************************************************************************
426 parse a buffer into lines
427 ****************************************************************************/
428 static char **file_lines_parse(char *p, size_t size, int *numlines)
435 for (s = p, i=0; s < p+size; s++) {
436 if (s[0] == '\n') i++;
439 ret = (char **)malloc(sizeof(ret[0])*(i+2));
444 memset(ret, 0, sizeof(ret[0])*(i+2));
445 if (numlines) *numlines = i;
448 for (s = p, i=0; s < p+size; s++) {
454 if (s[0] == '\r') s[0] = 0;
461 /****************************************************************************
462 load a file into memory and return an array of pointers to lines in the file
463 must be freed with file_lines_free().
464 ****************************************************************************/
465 char **file_lines_load(const char *fname, int *numlines)
470 p = file_load(fname, &size);
473 return file_lines_parse(p, size, numlines);
476 /****************************************************************************
477 load a fd into memory and return an array of pointers to lines in the file
478 must be freed with file_lines_free(). If convert is true calls unix_to_dos on
480 ****************************************************************************/
481 char **fd_lines_load(int fd, int *numlines)
486 p = fd_load(fd, &size);
489 return file_lines_parse(p, size, numlines);
493 /****************************************************************************
494 load a pipe into memory and return an array of pointers to lines in the data
495 must be freed with file_lines_free().
496 ****************************************************************************/
497 char **file_lines_pload(char *syscmd, int *numlines)
502 p = file_pload(syscmd, &size);
505 return file_lines_parse(p, size, numlines);
508 /****************************************************************************
509 free lines loaded with file_lines_load
510 ****************************************************************************/
511 void file_lines_free(char **lines)
519 /****************************************************************************
520 take a lislist of lines and modify them to produce a list where \ continues
522 ****************************************************************************/
523 void file_lines_slashcont(char **lines)
527 for (i=0; lines[i];) {
528 int len = strlen(lines[i]);
529 if (lines[i][len-1] == '\\') {
530 lines[i][len-1] = ' ';
532 char *p = &lines[i][len];
533 while (p < lines[i+1]) *p++ = ' ';
534 for (j = i+1; lines[j]; j++) lines[j] = lines[j+1];