Index: etc/mtree/BSD.root.dist =================================================================== --- etc/mtree/BSD.root.dist +++ etc/mtree/BSD.root.dist @@ -78,6 +78,8 @@ .. ssl .. + syslog.d + .. zfs .. .. Index: etc/syslog.conf =================================================================== --- etc/syslog.conf +++ etc/syslog.conf @@ -34,3 +34,5 @@ !ppp *.* /var/log/ppp.log !* +include /etc/syslog.d +include /usr/local/etc/syslog.d Index: usr.sbin/syslogd/syslog.conf.5 =================================================================== --- usr.sbin/syslogd/syslog.conf.5 +++ usr.sbin/syslogd/syslog.conf.5 @@ -28,7 +28,7 @@ .\" @(#)syslog.conf.5 8.1 (Berkeley) 6/9/93 .\" $FreeBSD$ .\" -.Dd September 12, 2012 +.Dd October 31, 2016 .Dt SYSLOG.CONF 5 .Os .Sh NAME @@ -62,6 +62,11 @@ .Em action field by one or more tab characters or spaces. .Pp +A special +.Em include +all files with names ending in '.conf' and not beginning with a '.' contained in +the directory following the keyword. +.Pp Note that if you use spaces as separators, your .Nm might be incompatible with other Unices or Unix-like systems. Index: usr.sbin/syslogd/syslogd.c =================================================================== --- usr.sbin/syslogd/syslogd.c +++ usr.sbin/syslogd/syslogd.c @@ -95,6 +95,7 @@ #include #include +#include #include #include #include @@ -118,6 +119,8 @@ const char *ConfFile = _PATH_LOGCONF; const char *PidFile = _PATH_LOGPID; const char ctty[] = _PATH_CONSOLE; +static const char include_str[] = "include"; +static const char include_ext[] = ".conf"; #define dprintf if (Debug) printf @@ -1601,6 +1604,157 @@ exit(1); } +static int +configfiles(const struct dirent *dp) +{ + const char *p; + size_t ext_len; + + if (dp->d_name[0] == '.') + return (0); + + ext_len = sizeof(include_ext) -1; + + if (dp->d_namlen <= ext_len) + return (0); + + p = &dp->d_name[dp->d_namlen - ext_len]; + if (strcmp(p, include_ext) != 0) + return (0); + + return (1); +} + +static void +readconfigfile(FILE *cf, struct filed **nextp, int allow_includes) +{ + FILE *cf2; + struct filed *f; + struct dirent **ent; + char cline[LINE_MAX]; + char host[MAXHOSTNAMELEN]; + char prog[LINE_MAX]; + char file[MAXPATHLEN]; + char *p, *tmp; + int i, nents; + size_t include_len; + + /* + * Foreach line in the conf table, open that file. + */ + f = NULL; + include_len = sizeof(include_str) -1; + (void)strlcpy(host, "*", sizeof(host)); + (void)strlcpy(prog, "*", sizeof(prog)); + while (fgets(cline, sizeof(cline), cf) != NULL) { + /* + * check for end-of-section, comments, strip off trailing + * spaces and newline character. #!prog is treated specially: + * following lines apply only to that program. + */ + for (p = cline; isspace(*p); ++p) + continue; + if (*p == 0) + continue; + if (allow_includes && + strncmp(p, include_str, include_len) == 0 && + isspace(p[include_len])) { + p += include_len; + while (isspace(*p)) + p++; + tmp = p; + while (*tmp != '\0' && !isspace(*tmp)) + tmp++; + *tmp = '\0'; + dprintf("Trying to include files in '%s'\n", p); + nents = scandir(p, &ent, configfiles, alphasort); + if (nents == -1) { + dprintf("Unable to open '%s': %s\n", p, + strerror(errno)); + } + for (i = 0; i < nents; i++) { + if (snprintf(file, sizeof(file), "%s/%s", p, + ent[i]->d_name) >= (int)sizeof(file)) { + dprintf("ignoring path too long: " + "'%s/%s'\n", p, ent[i]->d_name); + free(ent[i]); + continue; + } + free(ent[i]); + cf2 = fopen(file, "r"); + if (cf2 == NULL) + continue; + dprintf("reading %s\n", file); + readconfigfile(cf2, nextp, 0); + fclose(cf2); + } + if (nents >= 0) + free(ent); + continue; + } + if (*p == '#') { + p++; + if (*p != '!' && *p != '+' && *p != '-') + continue; + } + if (*p == '+' || *p == '-') { + host[0] = *p++; + while (isspace(*p)) + p++; + if ((!*p) || (*p == '*')) { + (void)strlcpy(host, "*", sizeof(host)); + continue; + } + if (*p == '@') + p = LocalHostName; + for (i = 1; i < MAXHOSTNAMELEN - 1; i++) { + if (!isalnum(*p) && *p != '.' && *p != '-' + && *p != ',' && *p != ':' && *p != '%') + break; + host[i] = *p++; + } + host[i] = '\0'; + continue; + } + if (*p == '!') { + p++; + while (isspace(*p)) p++; + if ((!*p) || (*p == '*')) { + (void)strlcpy(prog, "*", sizeof(prog)); + continue; + } + for (i = 0; i < LINE_MAX - 1; i++) { + if (!isprint(p[i]) || isspace(p[i])) + break; + prog[i] = p[i]; + } + prog[i] = 0; + continue; + } + for (p = cline + 1; *p != '\0'; p++) { + if (*p != '#') + continue; + if (*(p - 1) == '\\') { + strcpy(p - 1, p); + p--; + continue; + } + *p = '\0'; + break; + } + for (i = strlen(cline) - 1; i >= 0 && isspace(cline[i]); i--) + cline[i] = '\0'; + f = (struct filed *)calloc(1, sizeof(*f)); + if (f == NULL) { + logerror("calloc"); + exit(1); + } + *nextp = f; + nextp = &f->f_next; + cfline(cline, f, prog, host); + } +} + /* * INIT -- Initialize syslogd from configuration table */ @@ -1611,9 +1765,6 @@ FILE *cf; struct filed *f, *next, **nextp; char *p; - char cline[LINE_MAX]; - char prog[LINE_MAX]; - char host[MAXHOSTNAMELEN]; char oldLocalHostName[MAXHOSTNAMELEN]; char hostMsg[2*MAXHOSTNAMELEN+40]; char bootfileMsg[LINE_MAX]; @@ -1684,7 +1835,6 @@ free((char *)f); } Files = NULL; - nextp = &Files; /* open the configuration file */ if ((cf = fopen(ConfFile, "r")) == NULL) { @@ -1705,83 +1855,7 @@ return; } - /* - * Foreach line in the conf table, open that file. - */ - f = NULL; - (void)strlcpy(host, "*", sizeof(host)); - (void)strlcpy(prog, "*", sizeof(prog)); - while (fgets(cline, sizeof(cline), cf) != NULL) { - /* - * check for end-of-section, comments, strip off trailing - * spaces and newline character. #!prog is treated specially: - * following lines apply only to that program. - */ - for (p = cline; isspace(*p); ++p) - continue; - if (*p == 0) - continue; - if (*p == '#') { - p++; - if (*p != '!' && *p != '+' && *p != '-') - continue; - } - if (*p == '+' || *p == '-') { - host[0] = *p++; - while (isspace(*p)) - p++; - if ((!*p) || (*p == '*')) { - (void)strlcpy(host, "*", sizeof(host)); - continue; - } - if (*p == '@') - p = LocalHostName; - for (i = 1; i < MAXHOSTNAMELEN - 1; i++) { - if (!isalnum(*p) && *p != '.' && *p != '-' - && *p != ',' && *p != ':' && *p != '%') - break; - host[i] = *p++; - } - host[i] = '\0'; - continue; - } - if (*p == '!') { - p++; - while (isspace(*p)) p++; - if ((!*p) || (*p == '*')) { - (void)strlcpy(prog, "*", sizeof(prog)); - continue; - } - for (i = 0; i < LINE_MAX - 1; i++) { - if (!isprint(p[i]) || isspace(p[i])) - break; - prog[i] = p[i]; - } - prog[i] = 0; - continue; - } - for (p = cline + 1; *p != '\0'; p++) { - if (*p != '#') - continue; - if (*(p - 1) == '\\') { - strcpy(p - 1, p); - p--; - continue; - } - *p = '\0'; - break; - } - for (i = strlen(cline) - 1; i >= 0 && isspace(cline[i]); i--) - cline[i] = '\0'; - f = (struct filed *)calloc(1, sizeof(*f)); - if (f == NULL) { - logerror("calloc"); - exit(1); - } - *nextp = f; - nextp = &f->f_next; - cfline(cline, f, prog, host); - } + readconfigfile(cf, &Files, 1); /* close the configuration file */ (void)fclose(cf);