1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-30 16:51:41 +00:00

syslogd(8): add an 'include' keyword

All the '.conf' files not beginning with a '.' contained int he directory
following the keyword will be included.

This keyword can only be used in the first level configuration files.

Modify the default syslogd.conf to 'include' /etc/syslog.d and
/usr/local/etc/syslog.d

It simplify a lot handling of syslog from automation tools.

Reviewed by:	markj, kib (via irc)
Approved by:	markj
MFC after:	2 weeks
Relnotes:	yes
Differential Revision:	https://reviews.freebsd.org/D8402
This commit is contained in:
Baptiste Daroussin 2016-11-01 01:41:24 +00:00
parent 569b917590
commit fdec22c37d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=308160
4 changed files with 166 additions and 82 deletions

View File

@ -78,6 +78,8 @@
..
ssl
..
syslog.d
..
zfs
..
..

View File

@ -34,3 +34,5 @@ cron.* /var/log/cron
!ppp
*.* /var/log/ppp.log
!*
include /etc/syslog.d
include /usr/local/etc/syslog.d

View File

@ -28,7 +28,7 @@
.\" @(#)syslog.conf.5 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
.Dd September 12, 2012
.Dd November 1, 2016
.Dt SYSLOG.CONF 5
.Os
.Sh NAME
@ -62,6 +62,12 @@ field is separated from the
.Em action
field by one or more tab characters or spaces.
.Pp
A special
.Em include
keyword can be used to include all files with names ending in '.conf' and not
beginning with a '.' contained in the directory following the keyword.
This keyword can only be used in the first level configuration file.
.Pp
Note that if you use spaces as separators, your
.Nm
might be incompatible with other Unices or Unix-like systems.

View File

@ -95,6 +95,7 @@ __FBSDID("$FreeBSD$");
#include <arpa/inet.h>
#include <ctype.h>
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@ -118,6 +119,8 @@ __FBSDID("$FreeBSD$");
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 @@ die(int signo)
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));
continue;
}
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);
}
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 @@ init(int signo)
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 @@ init(int signo)
free((char *)f);
}
Files = NULL;
nextp = &Files;
/* open the configuration file */
if ((cf = fopen(ConfFile, "r")) == NULL) {
@ -1705,83 +1855,7 @@ init(int signo)
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);