[PATCH] Allow syslogd to accept multiple configuration files

From: Ryan Stone <rysto32_at_gmail.com>
Date: Wed, 9 Nov 2011 10:27:44 -0500
I've written the following patch to allow syslogd to accept multiple
configuration files by passing multiple -f options.  One use case for
this is to specify a common configuration file that applies across
multiple machines along with a second config file specific to the
local machine.

The patch can also be found at
http://people.freebsd.org/~rstone/patches/syslogd-multiconf.diff

(Oh, and before somebody asks, the reason that I converted struct
filed to use a TAILQ was that at one point I found myself typing
struct filed ***, then hit myself and refactored the code instead).

Index: syslogd.c
===================================================================
--- syslogd.c	(revision 227341)
+++ syslogd.c	(working copy)
_at__at_ -114,7 +114,6 _at__at_
 #define SYSLOG_NAMES
 #include <sys/syslog.h>

-const char	*ConfFile = _PATH_LOGCONF;
 const char	*PidFile = _PATH_LOGPID;
 const char	ctty[] = _PATH_CONSOLE;

_at__at_ -141,6 +140,13 _at__at_
 STAILQ_HEAD(, funix) funixes =	{ &funix_default,
 				&(funix_secure.next.stqe_next) };

+struct conf_file {
+	const char *name;
+	TAILQ_ENTRY(conf_file) next;
+};
+
+TAILQ_HEAD(, conf_file) conf_list = TAILQ_HEAD_INITIALIZER(conf_list);
+
 /*
  * Flags to logmsg().
  */
_at__at_ -159,7 +165,7 _at__at_
  */

 struct filed {
-	struct	filed *f_next;		/* next in linked list */
+	TAILQ_ENTRY(filed) f_next;	/* next in linked list */
 	short	f_type;			/* entry type, see below */
 	short	f_file;			/* file descriptor */
 	time_t	f_time;			/* time this was last written */
_at__at_ -266,7 +272,7 _at__at_
 	"FORW",		"USERS",	"WALL",		"PIPE"
 };

-static struct filed *Files;	/* Log files that we write to */
+static TAILQ_HEAD(, filed) Files = TAILQ_HEAD_INITIALIZER(Files);
 static struct filed consfile;	/* Console */

 static int	Debug;		/* debug flag */
_at__at_ -351,6 +357,7 _at__at_
 	struct timeval tv, *tvp;
 	struct sigaction sact;
 	struct funix *fx, *fx1;
+	struct conf_file *conf;
 	sigset_t mask;
 	pid_t ppid = 1, spid;
 	socklen_t len;
_at__at_ -393,7 +400,11 _at__at_
 			Debug++;
 			break;
 		case 'f':		/* configuration file */
-			ConfFile = optarg;
+			conf = malloc(sizeof(*conf));
+			if (conf == NULL)
+				errx(1, "Could not alloc memory, exiting");
+			conf->name = optarg;
+			TAILQ_INSERT_TAIL(&conf_list, conf, next);
 			break;
 		case 'k':		/* keep remote kern fac */
 			KeepKernFac = 1;
_at__at_ -497,6 +508,14 _at__at_
 		setlinebuf(stdout);
 	}

+	if (TAILQ_EMPTY(&conf_list)) {
+		conf = malloc(sizeof(*conf));
+		if (conf == NULL)
+			errx(1, "Could not alloc memory, exiting");
+		conf->name = _PATH_LOGCONF;
+		TAILQ_INSERT_TAIL(&conf_list, conf, next);
+	}
+
 	if (NumAllowed)
 		endservent();

_at__at_ -989,7 +1008,7 _at__at_
 		(void)sigsetmask(omask);
 		return;
 	}
-	for (f = Files; f; f = f->f_next) {
+	TAILQ_FOREACH(f, &Files, f_next) {
 		/* skip messages that are incorrect priority */
 		if (!(((f->f_pcmp[fac] & PRI_EQ) && (f->f_pmask[fac] == prilev))
 		     ||((f->f_pcmp[fac] & PRI_LT) && (f->f_pmask[fac] < prilev))
_at__at_ -1066,7 +1085,7 _at__at_
 {
 	struct filed *f;

-	for (f = Files; f; f = f->f_next) {
+	TAILQ_FOREACH(f, &Files, f_next) {
 		if ((f->f_type == F_FILE) &&
 		    (f->f_flags & FFLAG_NEEDSYNC)) {
 			f->f_flags &= ~FFLAG_NEEDSYNC;
_at__at_ -1403,7 +1422,7 _at__at_
 			goto oncemore;

 		/* Now, look in list of active processes. */
-		for (f = Files; f; f = f->f_next)
+		TAILQ_FOREACH(f, &Files, f_next)
 			if (f->f_type == F_PIPE &&
 			    f->f_un.f_pipe.f_pid == pid) {
 				(void)close(f->f_file);
_at__at_ -1505,7 +1524,7 _at__at_

 	was_initialized = Initialized;
 	Initialized = 0;	/* Don't log SIGCHLDs. */
-	for (f = Files; f != NULL; f = f->f_next) {
+	TAILQ_FOREACH(f, &Files, f_next) {
 		/* flush any pending output */
 		if (f->f_prevcount)
 			fprintlog(f, 0, (char *)NULL);
_at__at_ -1528,90 +1547,37 _at__at_
 	exit(1);
 }

-/*
- *  INIT -- Initialize syslogd from configuration table
- */
-static void
-init(int signo)
+static int
+parse_conf(const char *conf)
 {
 	int i;
 	FILE *cf;
-	struct filed *f, *next, **nextp;
+	struct filed *f;
 	char *p;
 	char cline[LINE_MAX];
  	char prog[NAME_MAX+1];
 	char host[MAXHOSTNAMELEN];
-	char oldLocalHostName[MAXHOSTNAMELEN];
-	char hostMsg[2*MAXHOSTNAMELEN+40];
-	char bootfileMsg[LINE_MAX];

-	dprintf("init\n");
-
-	/*
-	 * Load hostname (may have changed).
-	 */
-	if (signo != 0)
-		(void)strlcpy(oldLocalHostName, LocalHostName,
-		    sizeof(oldLocalHostName));
-	if (gethostname(LocalHostName, sizeof(LocalHostName)))
-		err(EX_OSERR, "gethostname() failed");
-	if ((p = strchr(LocalHostName, '.')) != NULL) {
-		*p++ = '\0';
-		LocalDomain = p;
-	} else {
-		LocalDomain = "";
-	}
-
-	/*
-	 *  Close all open log files.
-	 */
-	Initialized = 0;
-	for (f = Files; f != NULL; f = next) {
-		/* flush any pending output */
-		if (f->f_prevcount)
-			fprintlog(f, 0, (char *)NULL);
-
-		switch (f->f_type) {
-		case F_FILE:
-		case F_FORW:
-		case F_CONSOLE:
-		case F_TTY:
-			(void)close(f->f_file);
-			break;
-		case F_PIPE:
-			if (f->f_un.f_pipe.f_pid > 0) {
-				(void)close(f->f_file);
-				deadq_enter(f->f_un.f_pipe.f_pid,
-					    f->f_un.f_pipe.f_pname);
-			}
-			f->f_un.f_pipe.f_pid = 0;
-			break;
-		}
-		next = f->f_next;
-		if (f->f_program) free(f->f_program);
-		if (f->f_host) free(f->f_host);
-		free((char *)f);
-	}
-	Files = NULL;
-	nextp = &Files;
-
 	/* open the configuration file */
-	if ((cf = fopen(ConfFile, "r")) == NULL) {
-		dprintf("cannot open %s\n", ConfFile);
-		*nextp = (struct filed *)calloc(1, sizeof(*f));
-		if (*nextp == NULL) {
+	if ((cf = fopen(conf, "r")) == NULL) {
+		dprintf("cannot open %s\n", conf);
+		f = (struct filed *)calloc(1, sizeof(*f));
+		if (f == NULL) {
 			logerror("calloc");
 			exit(1);
 		}
-		cfline("*.ERR\t/dev/console", *nextp, "*", "*");
-		(*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f));
-		if ((*nextp)->f_next == NULL) {
+		cfline("*.ERR\t/dev/console", f, "*", "*");
+		TAILQ_INSERT_TAIL(&Files, f, f_next);
+		
+		f = (struct filed *)calloc(1, sizeof(*f));
+		if (f == NULL) {
 			logerror("calloc");
 			exit(1);
 		}
-		cfline("*.PANIC\t*", (*nextp)->f_next, "*", "*");
+		cfline("*.PANIC\t*", f, "*", "*");
+		TAILQ_INSERT_TAIL(&Files, f, f_next);
 		Initialized = 1;
-		return;
+		return (ENOENT);
 	}

 	/*
_at__at_ -1687,19 +1653,91 _at__at_
 			logerror("calloc");
 			exit(1);
 		}
-		*nextp = f;
-		nextp = &f->f_next;
 		cfline(cline, f, prog, host);
+		TAILQ_INSERT_TAIL(&Files, f, f_next);
 	}

 	/* close the configuration file */
 	(void)fclose(cf);

+	return (0);
+}
+
+/*
+ *  INIT -- Initialize syslogd from configuration table
+ */
+static void
+init(int signo)
+{
+	int i;
+	char *p;
+	struct filed *f, *next;
+	char oldLocalHostName[MAXHOSTNAMELEN];
+	char hostMsg[2*MAXHOSTNAMELEN+40];
+	char bootfileMsg[LINE_MAX];
+	struct conf_file *conf;
+	int error;
+
+	dprintf("init\n");
+
+	/*
+	 * Load hostname (may have changed).
+	 */
+	if (signo != 0)
+		(void)strlcpy(oldLocalHostName, LocalHostName,
+		    sizeof(oldLocalHostName));
+	if (gethostname(LocalHostName, sizeof(LocalHostName)))
+		err(EX_OSERR, "gethostname() failed");
+	if ((p = strchr(LocalHostName, '.')) != NULL) {
+		*p++ = '\0';
+		LocalDomain = p;
+	} else {
+		LocalDomain = "";
+	}
+
+	/*
+	 *  Close all open log files.
+	 */
+	Initialized = 0;
+	TAILQ_FOREACH_SAFE(f, &Files, f_next, next) {
+		/* flush any pending output */
+		if (f->f_prevcount)
+			fprintlog(f, 0, (char *)NULL);
+
+		switch (f->f_type) {
+		case F_FILE:
+		case F_FORW:
+		case F_CONSOLE:
+		case F_TTY:
+			(void)close(f->f_file);
+			break;
+		case F_PIPE:
+			if (f->f_un.f_pipe.f_pid > 0) {
+				(void)close(f->f_file);
+				deadq_enter(f->f_un.f_pipe.f_pid,
+					    f->f_un.f_pipe.f_pname);
+			}
+			f->f_un.f_pipe.f_pid = 0;
+			break;
+		}
+		if (f->f_program) free(f->f_program);
+		if (f->f_host) free(f->f_host);
+		TAILQ_REMOVE(&Files, f, f_next);
+		free((char *)f);
+	}
+
+	TAILQ_FOREACH(conf, &conf_list, next) {
+		error = parse_conf(conf->name);
+
+		if (error)
+			return;
+	}
+
 	Initialized = 1;

 	if (Debug) {
 		int port;
-		for (f = Files; f; f = f->f_next) {
+		TAILQ_FOREACH(f, &Files, f_next) {
 			for (i = 0; i <= LOG_NFACILITIES; i++)
 				if (f->f_pmask[i] == INTERNAL_NOPRI)
 					printf("X ");
_at__at_ -2054,7 +2092,7 _at__at_
 		MarkSeq = 0;
 	}

-	for (f = Files; f; f = f->f_next) {
+	TAILQ_FOREACH(f, &Files, f_next) {
 		if (f->f_prevcount && now >= REPEATTIME(f)) {
 			dprintf("flush %s: repeated %d times, %d sec.\n",
 			    TypeNames[f->f_type], f->f_prevcount,
Received on Wed Nov 09 2011 - 14:27:46 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:20 UTC