[PATCH] Allow syslogd to accept multiple configuration files
Ryan Stone
rysto32 at gmail.com
Wed Nov 9 15:27:46 UTC 2011
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)
@@ -114,7 +114,6 @@
#define SYSLOG_NAMES
#include <sys/syslog.h>
-const char *ConfFile = _PATH_LOGCONF;
const char *PidFile = _PATH_LOGPID;
const char ctty[] = _PATH_CONSOLE;
@@ -141,6 +140,13 @@
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().
*/
@@ -159,7 +165,7 @@
*/
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 */
@@ -266,7 +272,7 @@
"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 */
@@ -351,6 +357,7 @@
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;
@@ -393,7 +400,11 @@
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;
@@ -497,6 +508,14 @@
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();
@@ -989,7 +1008,7 @@
(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))
@@ -1066,7 +1085,7 @@
{
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;
@@ -1403,7 +1422,7 @@
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);
@@ -1505,7 +1524,7 @@
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);
@@ -1528,90 +1547,37 @@
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);
}
/*
@@ -1687,19 +1653,91 @@
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 ");
@@ -2054,7 +2092,7 @@
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,
More information about the freebsd-current
mailing list