Author: gordon
Date: Sat May 29 22:55:59 2010
New Revision: 208649
URL: http://svn.freebsd.org/changeset/base/208649

Log:
  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

Modified:
  head/usr.sbin/newsyslog/newsyslog.c
  head/usr.sbin/newsyslog/newsyslog.conf.5

Modified: head/usr.sbin/newsyslog/newsyslog.c
==============================================================================
--- head/usr.sbin/newsyslog/newsyslog.c Sat May 29 22:52:17 2010        
(r208648)
+++ head/usr.sbin/newsyslog/newsyslog.c Sat May 29 22:55:59 2010        
(r208649)
@@ -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];    /* hostna
 
 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, stru
  */
 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
                                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

Modified: head/usr.sbin/newsyslog/newsyslog.conf.5
==============================================================================
--- head/usr.sbin/newsyslog/newsyslog.conf.5    Sat May 29 22:52:17 2010        
(r208648)
+++ head/usr.sbin/newsyslog/newsyslog.conf.5    Sat May 29 22:55:59 2010        
(r208649)
@@ -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
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to