Exemplo n.º 1
0
/*
 * 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);
}
Exemplo n.º 2
0
/*
 * 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
	 */
}