From 06f0413c15c9b30e7951763c79d1d49358f870f6 Mon Sep 17 00:00:00 2001 From: gad Date: Mon, 24 Feb 2003 00:51:41 +0000 Subject: Add the idea of a "default rotate action", which will be used if a file is specified at runtime, but that filename is not listed in the newsyslog.conf file. This default-action can be changed by having a line in newsyslog.conf with the filename of "". Before this change, the program would quietly ignore the given file. An update to the man page will be written after I finish some other updates to newsyslog.c. Reviewed by: no objections from freebsd-arch MFC after: 3 weeks --- usr.sbin/newsyslog/newsyslog.c | 227 +++++++++++++++++++++++++++++++++++------ 1 file changed, 194 insertions(+), 33 deletions(-) (limited to 'usr.sbin/newsyslog') diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c index 041a948..1d9c82e 100644 --- a/usr.sbin/newsyslog/newsyslog.c +++ b/usr.sbin/newsyslog/newsyslog.c @@ -87,9 +87,12 @@ struct conf_entry { int permissions; /* File permissions on the log */ int flags; /* CE_COMPACT, CE_BZCOMPACT, CE_BINARY */ int sig; /* Signal to send */ + int def_cfg; /* Using the rule for this file */ struct conf_entry *next;/* Linked list pointer */ }; +#define DEFAULT_MARKER "" + int archtodir = 0; /* Archive old logfiles to other directory */ int verbose = 0; /* Print out what's going on */ int needroot = 1; /* Root privs are necessary */ @@ -109,11 +112,14 @@ static char *sob(char *p); static char *son(char *p); static char *missing_field(char *p, char *errline); static void do_entry(struct conf_entry * ent); +static void free_entry(struct conf_entry *ent); +static struct conf_entry *init_entry(const char *fname, + struct conf_entry *src_entry); static void PRS(int argc, char **argv); static void usage(void); static void dotrim(char *log, const char *pid_file, int numdays, int falgs, - int perm, int owner_uid, int group_gid, int sig); -static int log_trim(char *log); + int perm, int owner_uid, int group_gid, int sig, int def_cfg); +static int log_trim(char *log, int def_cfg); static void compress_log(char *log, int dowait); static void bzcompress_log(char *log, int dowait); static int sizefile(char *file); @@ -152,7 +158,7 @@ main(int argc, char **argv) } } p = p->next; - free((char *) q); + free_entry(q); q = p; } while (wait(NULL) > 0 || errno == EINTR) @@ -160,6 +166,77 @@ main(int argc, char **argv) return (0); } +static struct conf_entry * +init_entry(const char *fname, struct conf_entry *src_entry) +{ + struct conf_entry *tempwork; + + if (verbose > 4) + printf("\t--> [creating entry for %s]\n", fname); + + tempwork = malloc(sizeof(struct conf_entry)); + if (tempwork == NULL) + err(1, "malloc of conf_entry for %s", fname); + + tempwork->log = strdup(fname); + if (tempwork->log == NULL) + err(1, "strdup for %s", fname); + + if (src_entry != NULL) { + tempwork->pid_file = NULL; + if (src_entry->pid_file) + tempwork->pid_file = strdup(src_entry->pid_file); + tempwork->uid = src_entry->uid; + tempwork->gid = src_entry->gid; + tempwork->numlogs = src_entry->numlogs; + tempwork->size = src_entry->size; + tempwork->hours = src_entry->hours; + tempwork->trim_at = src_entry->trim_at; + tempwork->permissions = src_entry->permissions; + tempwork->flags = src_entry->flags; + tempwork->sig = src_entry->sig; + tempwork->def_cfg = src_entry->def_cfg; + } else { + /* Initialize as a "do-nothing" entry */ + tempwork->pid_file = NULL; + tempwork->uid = NONE; + tempwork->gid = NONE; + tempwork->numlogs = 1; + tempwork->size = -1; + tempwork->hours = -1; + tempwork->trim_at = (time_t)0; + tempwork->permissions = 0; + tempwork->flags = 0; + tempwork->sig = SIGHUP; + tempwork->def_cfg = 0; + } + tempwork->next = NULL; + + return (tempwork); +} + +static void +free_entry(struct conf_entry *ent) +{ + + if (ent == NULL) + return; + + if (ent->log != NULL) { + if (verbose > 4) + printf("\t--> [freeing entry for %s]\n", ent->log); + free(ent->log); + ent->log = NULL; + } + + if (ent->pid_file != NULL) { + free(ent->pid_file); + ent->pid_file = NULL; + } + + free(ent); +} + static void do_entry(struct conf_entry * ent) { @@ -223,7 +300,7 @@ do_entry(struct conf_entry * ent) } dotrim(ent->log, pid_file, ent->numlogs, ent->flags, ent->permissions, ent->uid, ent->gid, - ent->sig); + ent->sig, ent->def_cfg); } else { if (verbose) printf("--> skipping\n"); @@ -279,7 +356,7 @@ usage(void) { fprintf(stderr, - "usage: newsyslog [-Fnrv] [-f config-file] [-a directory]\n"); + "usage: newsyslog [-Fnrv] [-f config-file] [-a directory] [ filename ... ]\n"); exit(1); } @@ -293,13 +370,13 @@ parse_file(char **files) FILE *f; char line[BUFSIZ], *parse, *q; char *cp, *errline, *group; - char **p; - struct conf_entry *first, *working; + char **given; + struct conf_entry *defconf, *first, *working, *worklist; struct passwd *pass; struct group *grp; int eol; - first = working = NULL; + defconf = first = working = worklist = NULL; if (strcmp(conf, "-")) f = fopen(conf, "r"); @@ -331,27 +408,55 @@ parse_file(char **files) errline); *parse = '\0'; + /* + * If newsyslog was run with a list of specific filenames, + * then this line of the config file should be skipped if + * it is NOT one of those given files (except that we do + * want any line that defines the action). + * + * XXX - note that CE_GLOB processing is *NOT* done when + * trying to match a filename given on the command! + */ if (*files) { - for (p = files; *p; ++p) - if (strcmp(*p, q) == 0) - break; - if (!*p) + if (strcasecmp(DEFAULT_MARKER, q) != 0) { + for (given = files; *given; ++given) { + if (strcmp(*given, q) == 0) + break; + } + if (!*given) + continue; + } + if (verbose > 2) + printf("\t+ Matched entry %s\n", q); + } else { + /* + * If no files were specified on the command line, + * then we can skip any line which defines the + * default action. + */ + if (strcasecmp(DEFAULT_MARKER, q) == 0) { + if (verbose > 2) + printf("\t+ Ignoring entry for %s\n", + q); continue; + } } - if (!first) { - if ((working = malloc(sizeof(struct conf_entry))) == - NULL) - err(1, "malloc"); - first = working; + working = init_entry(q, NULL); + if (strcasecmp(DEFAULT_MARKER, q) == 0) { + if (defconf != NULL) { + warnx("Ignoring duplicate entry for %s!", q); + free_entry(working); + continue; + } + defconf = working; } else { - if ((working->next = malloc(sizeof(struct conf_entry))) - == NULL) - err(1, "malloc"); - working = working->next; + if (!first) + first = working; + else + worklist->next = working; + worklist = working; } - if ((working->log = strdup(q)) == NULL) - err(1, "strdup"); q = parse = missing_field(sob(++parse), errline); parse = son(parse); @@ -527,9 +632,57 @@ parse_file(char **files) } free(errline); } - if (working) - working->next = (struct conf_entry *) NULL; (void) fclose(f); + + /* + * The entire config file has been processed. If there were + * no specific files given on the run command, then the work + * of this routine is done. + */ + if (*files == NULL) + return (first); + + /* + * If the program was given a specific list of files to process, + * it may be that some of those files were not listed in the + * config file. Those unlisted files should get the default + * rotation action. First, create the default-rotation action + * if none was found in the config file. + */ + if (defconf == NULL) { + working = init_entry(DEFAULT_MARKER, NULL); + working->numlogs = 3; + working->size = 50; + working->permissions = S_IRUSR|S_IWUSR; + defconf = working; + } + + for (given = files; *given; ++given) { + for (working = first; working; working = working->next) { + if (strcmp(*given, working->log) == 0) + break; + } + if (working != NULL) + continue; + if (verbose > 2) + printf("\t+ No entry for %s (will use %s)\n", + *given, DEFAULT_MARKER); + /* + * This given file was not found in the config file. + * Add another item on to our work list, based on the + * default entry. + */ + working = init_entry(*given, defconf); + if (!first) + first = working; + else + worklist->next = working; + /* This is a file that was *not* found in config file */ + working->def_cfg = 1; + worklist = working; + } + + free_entry(defconf); return (first); } @@ -544,7 +697,7 @@ missing_field(char *p, char *errline) static void dotrim(char *log, const char *pid_file, int numdays, int flags, int perm, - int owner_uid, int group_gid, int sig) + int owner_uid, int group_gid, int sig, int def_cfg) { char dirpart[MAXPATHLEN], namepart[MAXPATHLEN]; char file1[MAXPATHLEN], file2[MAXPATHLEN]; @@ -659,8 +812,10 @@ dotrim(char *log, const char *pid_file, int numdays, int flags, int perm, (void) chown(zfile2, owner_uid, group_gid); } } - if (!noaction && !(flags & CE_BINARY)) - (void) log_trim(log); /* Report the trimming to the old log */ + if (!noaction && !(flags & CE_BINARY)) { + /* Report the trimming to the old log */ + (void) log_trim(log, def_cfg); + } if (!_numdays) { if (noaction) @@ -691,9 +846,11 @@ dotrim(char *log, const char *pid_file, int numdays, int flags, int perm, if (fchown(fd, owner_uid, group_gid)) err(1, "can't chmod new log file"); (void) close(fd); - if (!(flags & CE_BINARY)) - if (log_trim(tfile)) /* Add status message */ + if (!(flags & CE_BINARY)) { + /* Add status message to new log file */ + if (log_trim(tfile, def_cfg)) err(1, "can't add status message to log"); + } } if (noaction) printf("chmod %o %s...\n", perm, log); @@ -759,14 +916,18 @@ dotrim(char *log, const char *pid_file, int numdays, int flags, int perm, /* Log the fact that the logs were turned over */ static int -log_trim(char *log) +log_trim(char *log, int def_cfg) { FILE *f; + const char *xtra; if ((f = fopen(log, "a")) == NULL) return (-1); - fprintf(f, "%s %s newsyslog[%d]: logfile turned over\n", - daytime, hostname, (int) getpid()); + xtra = ""; + if (def_cfg) + xtra = " using rule"; + fprintf(f, "%s %s newsyslog[%d]: logfile turned over%s\n", + daytime, hostname, (int) getpid(), xtra); if (fclose(f) == EOF) err(1, "log_trim: fclose:"); return (0); -- cgit v1.1