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
This commit is contained in:
parent
a40596d77a
commit
82c00be8ee
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=208649
@ -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);
|
||||
|
||||
if (strcmp(fname, "-") != 0)
|
||||
f = fopen(fname, "r");
|
||||
else {
|
||||
f = stdin;
|
||||
fname = "<stdin>";
|
||||
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 (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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user