/* * conf_open -- open the configuration file, lock it if we have write perms */ int conf_open(const char *cfname, const char *tfname, struct opts *cliopts) { struct stat stbuf1, stbuf2, stbuf3; struct flock flock; int ret; Confname = cfname; Timesname = tfname; Confentries = fn_list_new(NULL); Changed = CHG_NONE; Changing = CHG_TIMES; if (opts_count(cliopts, "Vn") != 0) Changing = CHG_NONE; else if (opts_count(cliopts, "rw") != 0) Changing = CHG_BOTH; Singlefile = strcmp(Confname, Timesname) == 0; if (Singlefile && Changing == CHG_TIMES) Changing = CHG_BOTH; /* special case this so we don't even try locking the file */ if (strcmp(Confname, "/dev/null") == 0) return (0); while (Conffd == -1) { Canchange = CHG_BOTH; if ((Conffd = open(Confname, O_RDWR)) < 0) { if (Changing == CHG_BOTH) err(EF_SYS, "open %s", Confname); Canchange = CHG_TIMES; if ((Conffd = open(Confname, O_RDONLY)) < 0) err(EF_SYS, "open %s", Confname); } flock.l_type = (Canchange == CHG_BOTH) ? F_WRLCK : F_RDLCK; flock.l_whence = SEEK_SET; flock.l_start = 0; flock.l_len = 1; if (fcntl(Conffd, F_SETLKW, &flock) < 0) err(EF_SYS, "flock on %s", Confname); /* wait until after file is locked to get filesize */ if (fstat(Conffd, &stbuf1) < 0) err(EF_SYS, "fstat on %s", Confname); /* verify that we've got a lock on the active file */ if (stat(Confname, &stbuf2) < 0 || !(stbuf2.st_dev == stbuf1.st_dev && stbuf2.st_ino == stbuf1.st_ino)) { /* wrong config file, try again */ (void) close(Conffd); Conffd = -1; } } while (!Singlefile && Timesfd == -1) { if ((Timesfd = open(Timesname, O_CREAT|O_RDWR, 0644)) < 0) { if (Changing != CHG_NONE) err(EF_SYS, "open %s", Timesname); Canchange = CHG_NONE; if ((Timesfd = open(Timesname, O_RDONLY)) < 0) err(EF_SYS, "open %s", Timesname); } flock.l_type = (Canchange != CHG_NONE) ? F_WRLCK : F_RDLCK; flock.l_whence = SEEK_SET; flock.l_start = 0; flock.l_len = 1; if (fcntl(Timesfd, F_SETLKW, &flock) < 0) err(EF_SYS, "flock on %s", Timesname); /* wait until after file is locked to get filesize */ if (fstat(Timesfd, &stbuf2) < 0) err(EF_SYS, "fstat on %s", Timesname); /* verify that we've got a lock on the active file */ if (stat(Timesname, &stbuf3) < 0 || !(stbuf2.st_dev == stbuf3.st_dev && stbuf2.st_ino == stbuf3.st_ino)) { /* wrong timestamp file, try again */ (void) close(Timesfd); Timesfd = -1; continue; } /* check that Timesname isn't an alias for Confname */ if (stbuf2.st_dev == stbuf1.st_dev && stbuf2.st_ino == stbuf1.st_ino) err(0, "Timestamp file %s can't refer to " "Configuration file %s", Timesname, Confname); } Conflen = stbuf1.st_size; Timeslen = stbuf2.st_size; if (Conflen == 0) return (1); /* empty file, don't bother parsing it */ if ((Confbuf = (char *)mmap(0, Conflen, PROT_READ | PROT_WRITE, MAP_PRIVATE, Conffd, 0)) == (char *)-1) err(EF_SYS, "mmap on %s", Confname); ret = conf_scan(Confname, Confbuf, Conflen, 0, cliopts); if (ret == 3 && !Singlefile && Canchange == CHG_BOTH) { /* * arrange to transfer any timestamps * from conf_file to timestamps_file */ Changing = Changed = CHG_BOTH; } if (Timesfd != -1 && Timeslen != 0) { if ((Timesbuf = (char *)mmap(0, Timeslen, PROT_READ | PROT_WRITE, MAP_PRIVATE, Timesfd, 0)) == (char *)-1) err(EF_SYS, "mmap on %s", Timesname); ret &= conf_scan(Timesname, Timesbuf, Timeslen, 1, cliopts); } /* * possible future enhancement: go through and mark any entries: * logfile -P <date> * as DELETED if the logfile doesn't exist */ return (ret); }
/* * conf_open -- open the configuration file, lock it if we have write perms */ void conf_open(const char *fname, int needwrite) { struct stat stbuf; int lineno = 0; char *line; char *eline; char *ebuf; char *comment; Confname = fname; Confentries = fn_list_new(NULL); /* special case this so we don't even try locking the file */ if (strcmp(Confname, "/dev/null") == 0) return; if ((Conffd = open(Confname, (needwrite) ? O_RDWR : O_RDONLY)) < 0) err(EF_SYS, "%s", Confname); if (fstat(Conffd, &stbuf) < 0) err(EF_SYS, "fstat on %s", Confname); if (needwrite && lockf(Conffd, F_LOCK, 0) < 0) err(EF_SYS, "lockf on %s", Confname); if (stbuf.st_size == 0) return; /* empty file, don't bother parsing it */ if ((Confbuf = (char *)mmap(0, stbuf.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, Conffd, 0)) == (char *)-1) err(EF_SYS, "mmap on %s", Confname); Conflen = stbuf.st_size; Confchanged = B_FALSE; ebuf = &Confbuf[Conflen]; if (Confbuf[Conflen - 1] != '\n') err(EF_WARN|EF_FILE, "config file doesn't end with " "newline, last line ignored."); line = Confbuf; while (line < ebuf) { lineno++; err_fileline(Confname, lineno); eline = line; comment = NULL; for (; eline < ebuf; eline++) { /* check for continued lines */ if (comment == NULL && *eline == '\\' && eline + 1 < ebuf && *(eline + 1) == '\n') { *eline = ' '; *(eline + 1) = ' '; lineno++; err_fileline(Confname, lineno); continue; } /* check for comments */ if (comment == NULL && *eline == '#') { *eline = '\0'; comment = (eline + 1); continue; } /* check for end of line */ if (*eline == '\n') break; } if (comment >= ebuf) comment = NULL; if (eline < ebuf) { char *entry; *eline++ = '\0'; /* * now we have the entry, if any, at "line" * and the comment, if any, at "comment" */ /* entry is first token */ if ((entry = nexttok(&line)) != NULL && strcmp(entry, "logadm-version") == 0) { /* * we somehow opened some future format * conffile that we likely don't understand. * if the given version is "1" then go on, * otherwise someone is mixing versions * and we can't help them other than to * print an error and exit. */ if ((entry = nexttok(&line)) != NULL && strcmp(entry, "1") != 0) err(0, "%s version not " "supported by " "this version of logadm.", Confname); } else if (entry) { char *ap; char **args; int i; ArgsI = 0; while (ap = nexttok(&line)) fillargs(ap); if (ArgsI == 0) { /* short entry allowed */ fillconflist(lineno, entry, NULL, NULL, comment, 0); } else { Args[ArgsI++] = NULL; args = MALLOC(sizeof (char *) * ArgsI); for (i = 0; i < ArgsI; i++) args[i] = Args[i]; fillconflist(lineno, entry, args, NULL, comment, 0); } } else fillconflist(lineno, entry, NULL, NULL, comment, 0); } line = eline; } /* * possible future enhancement: go through and mark any entries: * logfile -P <date> * as DELETED if the logfile doesn't exist */ }