Convert newsyslog to using queue(3) macros instead of a home rolled version.

Reviewed by:	gad@
Approved by:	wes@ (mentor)
MFC after:	2 months
This commit is contained in:
gordon 2010-05-29 22:52:17 +00:00
parent 8d50dfb57f
commit 5224579be4

View File

@ -113,6 +113,7 @@ __FBSDID("$FreeBSD$");
#define DEBUG_MARKER "<debug>"
struct conf_entry {
STAILQ_ENTRY(conf_entry) cf_nextp;
char *log; /* Name of the log */
char *pid_file; /* PID file */
char *r_reason; /* The reason this file is being rotated */
@ -129,7 +130,6 @@ struct conf_entry {
int flags; /* CE_COMPACT, CE_BZCOMPACT, CE_BINARY */
int sig; /* Signal to send */
int def_cfg; /* Using the <default> rule for this file */
struct conf_entry *next;/* Linked list pointer */
};
struct sigwork_entry {
@ -153,6 +153,7 @@ typedef enum {
FREE_ENT, KEEP_ENT
} fk_entry;
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);
@ -186,9 +187,9 @@ char daytime[DAYTIME_LEN]; /* The current time in human readable form,
* used for rotation-tracking messages. */
char hostname[MAXHOSTNAMELEN]; /* hostname */
static struct conf_entry *get_worklist(char **files);
static void parse_file(FILE *cf, const char *cfname, struct conf_entry **work_p,
struct conf_entry **glob_p, struct conf_entry **defconf_p);
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);
static char *sob(char *p);
static char *son(char *p);
static int isnumberstr(const char *);
@ -205,9 +206,8 @@ static struct zipwork_entry *
sigwork_entry *, int, const char *);
static void set_swpid(struct sigwork_entry *, const struct conf_entry *);
static int sizefile(const char *);
static void expand_globs(struct conf_entry **work_p,
struct conf_entry **glob_p);
static void free_clist(struct conf_entry **firstent);
static void expand_globs(struct cflist *work_p, struct cflist *glob_p);
static void free_clist(struct cflist *list);
static void free_entry(struct conf_entry *ent);
static struct conf_entry *init_entry(const char *fname,
struct conf_entry *src_entry);
@ -233,8 +233,8 @@ static void createlog(const struct conf_entry *ent);
int
main(int argc, char **argv)
{
fk_entry free_or_keep;
struct conf_entry *p, *q;
struct cflist *worklist;
struct conf_entry *p;
struct sigwork_entry *stmp;
struct zipwork_entry *ztmp;
@ -247,18 +247,17 @@ main(int argc, char **argv)
if (needroot && getuid() && geteuid())
errx(1, "must have root privs");
p = q = get_worklist(argv);
worklist = get_worklist(argv);
/*
* Rotate all the files which need to be rotated. Note that
* some users have *hundreds* of entries in newsyslog.conf!
*/
while (p) {
free_or_keep = do_entry(p);
p = p->next;
if (free_or_keep == FREE_ENT)
free_entry(q);
q = p;
while (!STAILQ_EMPTY(worklist)) {
p = STAILQ_FIRST(worklist);
STAILQ_REMOVE_HEAD(worklist, cf_nextp);
if (do_entry(p) == FREE_ENT)
free_entry(p);
}
/*
@ -365,7 +364,6 @@ init_entry(const char *fname, struct conf_entry *src_entry)
tempwork->sig = SIGHUP;
tempwork->def_cfg = 0;
}
tempwork->next = NULL;
return (tempwork);
}
@ -403,21 +401,18 @@ free_entry(struct conf_entry *ent)
}
static void
free_clist(struct conf_entry **firstent)
free_clist(struct cflist *list)
{
struct conf_entry *ent, *nextent;
struct conf_entry *ent;
if (firstent == NULL)
return; /* There is nothing to do. */
ent = *firstent;
firstent = NULL;
while (ent) {
nextent = ent->next;
while (!STAILQ_EMPTY(list)) {
ent = STAILQ_FIRST(list);
STAILQ_REMOVE_HEAD(list, cf_nextp);
free_entry(ent);
ent = nextent;
}
free(list);
list = NULL;
}
static fk_entry
@ -732,17 +727,26 @@ usage(void)
* Parse a configuration file and return a linked list of all the logs
* which should be processed.
*/
static struct conf_entry *
static struct cflist *
get_worklist(char **files)
{
FILE *f;
const char *fname;
char **given;
struct conf_entry *defconf, *dupent, *ent, *firstnew;
struct conf_entry *globlist, *lastnew, *worklist;
struct cflist *filelist, *globlist, *cmdlist;
struct conf_entry *defconf, *dupent, *ent;
int gmatch, fnres;
defconf = globlist = worklist = NULL;
defconf = NULL;
filelist = malloc(sizeof(struct cflist));
if (filelist == NULL)
err(1, "malloc of filelist");
STAILQ_INIT(filelist);
globlist = malloc(sizeof(struct cflist));
if (globlist == NULL)
err(1, "malloc of globlist");
STAILQ_INIT(globlist);
fname = conf;
if (fname == NULL)
@ -757,22 +761,22 @@ get_worklist(char **files)
if (!f)
err(1, "%s", fname);
parse_file(f, fname, &worklist, &globlist, &defconf);
parse_file(f, filelist, globlist, defconf);
(void) fclose(f);
/*
* All config-file information has been read in and turned into
* a worklist and a globlist. If there were no specific files
* a filelist and a globlist. If there were no specific files
* given on the run command, then the only thing left to do is to
* call a routine which finds all files matched by the globlist
* and adds them to the worklist. Then return the worklist.
* and adds them to the filelist. Then return the worklist.
*/
if (*files == NULL) {
expand_globs(&worklist, &globlist);
free_clist(&globlist);
expand_globs(filelist, globlist);
free_clist(globlist);
if (defconf != NULL)
free_entry(defconf);
return (worklist);
return (filelist);
/* NOTREACHED */
}
@ -794,7 +798,7 @@ get_worklist(char **files)
* If newsyslog was run with a list of specific filenames,
* then create a new worklist which has only those files in
* it, picking up the rotation-rules for those files from
* the original worklist.
* the original filelist.
*
* XXX - Note that this will copy multiple rules for a single
* logfile, if multiple entries are an exact match for
@ -802,21 +806,21 @@ get_worklist(char **files)
* we want to continue to allow it? If so, it should
* probably be handled more intelligently.
*/
firstnew = lastnew = NULL;
cmdlist = malloc(sizeof(struct cflist));
if (cmdlist == NULL)
err(1, "malloc of cmdlist");
STAILQ_INIT(cmdlist);
for (given = files; *given; ++given) {
/*
* First try to find exact-matches for this given file.
*/
gmatch = 0;
for (ent = worklist; ent; ent = ent->next) {
STAILQ_FOREACH(ent, filelist, cf_nextp) {
if (strcmp(ent->log, *given) == 0) {
gmatch++;
dupent = init_entry(*given, ent);
if (!firstnew)
firstnew = dupent;
else
lastnew->next = dupent;
lastnew = dupent;
STAILQ_INSERT_TAIL(cmdlist, dupent, cf_nextp);
}
}
if (gmatch) {
@ -832,7 +836,7 @@ get_worklist(char **files)
gmatch = 0;
if (verbose > 2 && globlist != NULL)
printf("\t+ Checking globs for %s\n", *given);
for (ent = globlist; ent; ent = ent->next) {
STAILQ_FOREACH(ent, globlist, cf_nextp) {
fnres = fnmatch(ent->log, *given, FNM_PATHNAME);
if (verbose > 2)
printf("\t+ = %d for pattern %s\n", fnres,
@ -840,13 +844,9 @@ get_worklist(char **files)
if (fnres == 0) {
gmatch++;
dupent = init_entry(*given, ent);
if (!firstnew)
firstnew = dupent;
else
lastnew->next = dupent;
lastnew = dupent;
/* This new entry is not a glob! */
dupent->flags &= ~CE_GLOB;
STAILQ_INSERT_TAIL(cmdlist, dupent, cf_nextp);
/* Only allow a match to one glob-entry */
break;
}
@ -866,25 +866,21 @@ get_worklist(char **files)
printf("\t+ No entry matched %s (will use %s)\n",
*given, DEFAULT_MARKER);
dupent = init_entry(*given, defconf);
if (!firstnew)
firstnew = dupent;
else
lastnew->next = dupent;
/* Mark that it was *not* found in a config file */
dupent->def_cfg = 1;
lastnew = dupent;
STAILQ_INSERT_TAIL(cmdlist, dupent, cf_nextp);
}
/*
* Free all the entries in the original work list, the list of
* glob entries, and the default entry.
*/
free_clist(&worklist);
free_clist(&globlist);
free_clist(filelist);
free_clist(globlist);
free_entry(defconf);
/* And finally, return a worklist which matches the given files. */
return (firstnew);
return (cmdlist);
}
/*
@ -892,19 +888,15 @@ get_worklist(char **files)
* which match those glob-entries onto the worklist.
*/
static void
expand_globs(struct conf_entry **work_p, struct conf_entry **glob_p)
expand_globs(struct cflist *work_p, struct cflist *glob_p)
{
int gmatch, gres;
size_t i;
char *mfname;
struct conf_entry *dupent, *ent, *firstmatch, *globent;
struct conf_entry *lastmatch;
struct conf_entry *dupent, *ent, *globent;
glob_t pglob;
struct stat st_fm;
if ((glob_p == NULL) || (*glob_p == NULL))
return; /* There is nothing to do. */
/*
* The worklist contains all fully-specified (non-GLOB) names.
*
@ -913,9 +905,7 @@ expand_globs(struct conf_entry **work_p, struct conf_entry **glob_p)
* that already exist. Do not add a glob-related entry for any
* file which already exists in the fully-specified list.
*/
firstmatch = lastmatch = NULL;
for (globent = *glob_p; globent; globent = globent->next) {
STAILQ_FOREACH(globent, glob_p, cf_nextp) {
gres = glob(globent->log, GLOB_NOCHECK, NULL, &pglob);
if (gres != 0) {
warn("cannot expand pattern (%d): %s", gres,
@ -930,7 +920,7 @@ expand_globs(struct conf_entry **work_p, struct conf_entry **glob_p)
/* See if this file already has a specific entry. */
gmatch = 0;
for (ent = *work_p; ent; ent = ent->next) {
STAILQ_FOREACH(ent, work_p, cf_nextp) {
if (strcmp(mfname, ent->log) == 0) {
gmatch++;
break;
@ -957,29 +947,16 @@ expand_globs(struct conf_entry **work_p, struct conf_entry **glob_p)
if (verbose > 2)
printf("\t+ . add file %s\n", mfname);
dupent = init_entry(mfname, globent);
if (!firstmatch)
firstmatch = dupent;
else
lastmatch->next = dupent;
lastmatch = dupent;
/* This new entry is not a glob! */
dupent->flags &= ~CE_GLOB;
/* Add to the worklist. */
STAILQ_INSERT_TAIL(work_p, dupent, cf_nextp);
}
globfree(&pglob);
if (verbose > 2)
printf("\t+ Done with pattern %s\n", globent->log);
}
/* Add the list of matched files to the end of the worklist. */
if (!*work_p)
*work_p = firstmatch;
else {
ent = *work_p;
while (ent->next)
ent = ent->next;
ent->next = firstmatch;
}
}
/*
@ -987,22 +964,16 @@ expand_globs(struct conf_entry **work_p, struct conf_entry **glob_p)
* process.
*/
static void
parse_file(FILE *cf, const char *cfname, struct conf_entry **work_p,
struct conf_entry **glob_p, struct conf_entry **defconf_p)
parse_file(FILE *cf, struct cflist *work_p, struct cflist *glob_p,
struct conf_entry *defconf_p)
{
char line[BUFSIZ], *parse, *q;
char *cp, *errline, *group;
struct conf_entry *lastglob, *lastwork, *working;
struct conf_entry *working;
struct passwd *pwd;
struct group *grp;
int eol, ptm_opts, res, special;
/*
* XXX - for now, assume that only one config file will be read,
* ie, this routine is only called one time.
*/
lastglob = lastwork = NULL;
errline = NULL;
while (fgets(line, BUFSIZ, cf)) {
if ((line[0] == '\n') || (line[0] == '#') ||
@ -1032,7 +1003,7 @@ parse_file(FILE *cf, const char *cfname, struct conf_entry **work_p,
/*
* Allow people to set debug options via the config file.
* (NOTE: debug optons are undocumented, and may disappear
* (NOTE: debug options are undocumented, and may disappear
* at any time, etc).
*/
if (strcasecmp(DEBUG_MARKER, q) == 0) {
@ -1052,17 +1023,12 @@ parse_file(FILE *cf, const char *cfname, struct conf_entry **work_p,
working = init_entry(q, NULL);
if (strcasecmp(DEFAULT_MARKER, q) == 0) {
special = 1;
if (defconf_p == NULL) {
warnx("Ignoring entry for %s in %s!", q,
cfname);
free_entry(working);
continue;
} else if (*defconf_p != NULL) {
if (defconf_p != NULL) {
warnx("Ignoring duplicate entry for %s!", q);
free_entry(working);
continue;
}
*defconf_p = working;
defconf_p = working;
}
q = parse = missing_field(sob(++parse), errline);
@ -1328,17 +1294,9 @@ no_trimat:
if (special) {
; /* Do not add to any list */
} else if (working->flags & CE_GLOB) {
if (!*glob_p)
*glob_p = working;
else
lastglob->next = working;
lastglob = working;
STAILQ_INSERT_TAIL(glob_p, working, cf_nextp);
} else {
if (!*work_p)
*work_p = working;
else
lastwork->next = working;
lastwork = working;
STAILQ_INSERT_TAIL(work_p, working, cf_nextp);
}
}
if (errline != NULL)