aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/newsyslog
diff options
context:
space:
mode:
authorGordon Tetlow <gordon@FreeBSD.org>2010-05-29 22:55:59 +0000
committerGordon Tetlow <gordon@FreeBSD.org>2010-05-29 22:55:59 +0000
commit82c00be8eeae73c7b4c886422efef275421aa910 (patch)
tree46442acc73777344af2183605084c57782159da6 /usr.sbin/newsyslog
parenta40596d77ab851cabf0c07fbfecc46db9e873a20 (diff)
downloadsrc-82c00be8eeae73c7b4c886422efef275421aa910.tar.gz
src-82c00be8eeae73c7b4c886422efef275421aa910.zip
Add file include processing for newsyslog.
Format for the include line in /etc/newsyslog.conf is: <include> /etc/defaults/newsyslog.conf Other notes of interest: Globbing is supported in <include> statements. Properly detect circular include loop dependencies. Reviewed by: gad@ Approved by: wes@ (mentor) MFC after: 2 months
Notes
Notes: svn path=/head/; revision=208649
Diffstat (limited to 'usr.sbin/newsyslog')
-rw-r--r--usr.sbin/newsyslog/newsyslog.c126
-rw-r--r--usr.sbin/newsyslog/newsyslog.conf.59
2 files changed, 116 insertions, 19 deletions
diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c
index fefb45869f29..594375a746b4 100644
--- a/usr.sbin/newsyslog/newsyslog.c
+++ b/usr.sbin/newsyslog/newsyslog.c
@@ -111,6 +111,7 @@ __FBSDID("$FreeBSD$");
#define DEFAULT_MARKER "<default>"
#define DEBUG_MARKER "<debug>"
+#define INCLUDE_MARKER "<include>"
struct conf_entry {
STAILQ_ENTRY(conf_entry) cf_nextp;
@@ -149,6 +150,11 @@ struct zipwork_entry {
char zw_fname[1]; /* the file to compress */
};
+struct include_entry {
+ STAILQ_ENTRY(include_entry) inc_nextp;
+ const char *file; /* Name of file to process */
+};
+
typedef enum {
FREE_ENT, KEEP_ENT
} fk_entry;
@@ -156,6 +162,7 @@ typedef enum {
STAILQ_HEAD(cflist, conf_entry);
SLIST_HEAD(swlisthead, sigwork_entry) swhead = SLIST_HEAD_INITIALIZER(swhead);
SLIST_HEAD(zwlisthead, zipwork_entry) zwhead = SLIST_HEAD_INITIALIZER(zwhead);
+STAILQ_HEAD(ilist, include_entry);
int dbg_at_times; /* -D Show details of 'trim_at' code */
@@ -189,10 +196,12 @@ char hostname[MAXHOSTNAMELEN]; /* hostname */
static struct cflist *get_worklist(char **files);
static void parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
- struct conf_entry *defconf_p);
+ struct conf_entry *defconf_p, struct ilist *inclist);
+static void add_to_queue(const char *fname, struct ilist *inclist);
static char *sob(char *p);
static char *son(char *p);
static int isnumberstr(const char *);
+static int isglobstr(const char *);
static char *missing_field(char *p, char *errline);
static void change_attrs(const char *, const struct conf_entry *);
static fk_entry do_entry(struct conf_entry *);
@@ -731,13 +740,15 @@ static struct cflist *
get_worklist(char **files)
{
FILE *f;
- const char *fname;
char **given;
- struct cflist *filelist, *globlist, *cmdlist;
+ struct cflist *cmdlist, *filelist, *globlist;
struct conf_entry *defconf, *dupent, *ent;
+ struct ilist inclist;
+ struct include_entry *inc;
int gmatch, fnres;
defconf = NULL;
+ STAILQ_INIT(&inclist);
filelist = malloc(sizeof(struct cflist));
if (filelist == NULL)
@@ -748,21 +759,29 @@ get_worklist(char **files)
err(1, "malloc of globlist");
STAILQ_INIT(globlist);
- fname = conf;
- if (fname == NULL)
- fname = _PATH_CONF;
+ inc = malloc(sizeof(struct include_entry));
+ if (inc == NULL)
+ err(1, "malloc of inc");
+ inc->file = conf;
+ if (inc->file == NULL)
+ inc->file = _PATH_CONF;
+ STAILQ_INSERT_TAIL(&inclist, inc, inc_nextp);
+
+ STAILQ_FOREACH(inc, &inclist, inc_nextp) {
+ if (strcmp(inc->file, "-") != 0)
+ f = fopen(inc->file, "r");
+ else {
+ f = stdin;
+ inc->file = "<stdin>";
+ }
+ if (!f)
+ err(1, "%s", inc->file);
- if (strcmp(fname, "-") != 0)
- f = fopen(fname, "r");
- else {
- f = stdin;
- fname = "<stdin>";
+ if (verbose)
+ printf("Processing %s\n", inc->file);
+ parse_file(f, filelist, globlist, defconf, &inclist);
+ (void) fclose(f);
}
- if (!f)
- err(1, "%s", fname);
-
- parse_file(f, filelist, globlist, defconf);
- (void) fclose(f);
/*
* All config-file information has been read in and turned into
@@ -965,14 +984,16 @@ expand_globs(struct cflist *work_p, struct cflist *glob_p)
*/
static void
parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
- struct conf_entry *defconf_p)
+ struct conf_entry *defconf_p, struct ilist *inclist)
{
char line[BUFSIZ], *parse, *q;
char *cp, *errline, *group;
struct conf_entry *working;
struct passwd *pwd;
struct group *grp;
+ glob_t pglob;
int eol, ptm_opts, res, special;
+ size_t i;
errline = NULL;
while (fgets(line, BUFSIZ, cf)) {
@@ -1017,6 +1038,37 @@ parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
parse_doption(q);
}
continue;
+ } else if (strcasecmp(INCLUDE_MARKER, q) == 0) {
+ if (verbose)
+ printf("Found: %s", errline);
+ q = parse = missing_field(sob(++parse), errline);
+ parse = son(parse);
+ if (!*parse) {
+ warnx("include line missing argument:\n%s",
+ errline);
+ continue;
+ }
+
+ *parse = '\0';
+
+ if (isglobstr(q)) {
+ res = glob(q, GLOB_NOCHECK, NULL, &pglob);
+ if (res != 0) {
+ warn("cannot expand pattern (%d): %s",
+ res, q);
+ continue;
+ }
+
+ if (verbose > 2)
+ printf("\t+ Expanding pattern %s\n", q);
+
+ for (i = 0; i < pglob.gl_matchc; i++)
+ add_to_queue(pglob.gl_pathv[i],
+ inclist);
+ globfree(&pglob);
+ } else
+ add_to_queue(q, inclist);
+ continue;
}
special = 0;
@@ -1312,6 +1364,33 @@ missing_field(char *p, char *errline)
return (p);
}
+/*
+ * Only add to the queue if the file hasn't already been added. This is
+ * done to prevent circular include loops.
+ */
+static void
+add_to_queue(const char *fname, struct ilist *inclist)
+{
+ struct include_entry *inc;
+
+ STAILQ_FOREACH(inc, inclist, inc_nextp) {
+ if (strcmp(fname, inc->file) == 0) {
+ warnx("duplicate include detected: %s", fname);
+ return;
+ }
+ }
+
+ inc = malloc(sizeof(struct include_entry));
+ if (inc == NULL)
+ err(1, "malloc of inc");
+ inc->file = strdup(fname);
+
+ if (verbose > 2)
+ printf("\t+ Adding %s to the processing queue.\n", fname);
+
+ STAILQ_INSERT_TAIL(inclist, inc, inc_nextp);
+}
+
static fk_entry
do_rotate(const struct conf_entry *ent)
{
@@ -1916,6 +1995,19 @@ isnumberstr(const char *string)
return (1);
}
+/* Check if string contains a glob */
+static int
+isglobstr(const char *string)
+{
+ char chr;
+
+ while ((chr = *string++)) {
+ if (chr == '*' || chr == '?' || chr == '[')
+ return (1);
+ }
+ return (0);
+}
+
/*
* Save the active log file under a new name. A link to the new name
* is the quick-and-easy way to do this. If that fails (which it will
diff --git a/usr.sbin/newsyslog/newsyslog.conf.5 b/usr.sbin/newsyslog/newsyslog.conf.5
index 138adc03b882..125ced076626 100644
--- a/usr.sbin/newsyslog/newsyslog.conf.5
+++ b/usr.sbin/newsyslog/newsyslog.conf.5
@@ -69,13 +69,18 @@ is treated as an ordinary character.
The fields of the configuration file are as follows:
.Bl -tag -width indent
.It Ar logfile_name
-Name of the system log file to be archived, or the literal string
-.Dq Aq Li default .
+Name of the system log file to be archived,
+or one of the literal strings
+.Dq Aq Li default ,
+or
+.Dq Aq Li include .
The special default entry will only be used if a log file
name is given as a command line argument to
.Xr newsyslog 8 ,
and if that log file name is not matched by any other
line in the configuration file.
+The include entry is used to include other configuration
+files and supports globbing.
.It Ar owner : Ns Ar group
This optional field specifies the owner and group for the archive file.
The