From owner-freebsd-arch Thu Feb 20 20:36:11 2003 Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id A76AC37B401 for ; Thu, 20 Feb 2003 20:36:01 -0800 (PST) Received: from smtp4.server.rpi.edu (smtp4.server.rpi.edu [128.113.2.4]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9A7F343FA3 for ; Thu, 20 Feb 2003 20:36:00 -0800 (PST) (envelope-from drosih@rpi.edu) Received: from [128.113.24.47] (gilead.netel.rpi.edu [128.113.24.47]) by smtp4.server.rpi.edu (8.12.7/8.12.7) with ESMTP id h1L4ZwqX008189; Thu, 20 Feb 2003 23:35:58 -0500 Mime-Version: 1.0 X-Sender: drosih@mail.rpi.edu Message-Id: In-Reply-To: <200302150905.08387.wes@softweyr.com> References: <20030210114930.GB90800@melusine.cuivre.fr.eu.org> <200302141733.29304.wes@softweyr.com> <200302150905.08387.wes@softweyr.com> Date: Thu, 20 Feb 2003 23:35:56 -0500 To: Wes Peters From: Garance A Drosihn Subject: Re: syslog.conf syntax change (multiple program/host specifications) Cc: arch@FreeBSD.ORG Content-Type: text/plain; charset="us-ascii" ; format="flowed" X-RPI-Spam-Score: -2.5 () IN_REP_TO,PATCH_UNIFIED_DIFF,QUOTED_EMAIL_TEXT,REFERENCES,SIGNATURE_SHORT_DENSE,SPAM_PHRASE_00_01 X-Scanned-By: MIMEDefang 2.28 Sender: owner-freebsd-arch@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Offshoot of the "syslog.conf syntax change" thread. At 9:05 AM +0000 2/15/03, Wes Peters wrote: >On Saturday 15 February 2003 06:48, Garance A Drosihn wrote: > > >> I would add some default rotate-action to newsyslog, which >> would be used if -R is specified and the file is not listed >> in the newsyslog.conf file. > >Sounds good to me. Are you going to look into that? I'll >definitely want your changes to newsyslog to go along with >my changes to syslog.conf. ;^) What follows is part #1 of what I plan to do. This adds the notion of a "default rotation action" to newsyslog. This action will *only* be significant when newsyslog is run with a specific list of filenames. The patch picks some plausible behavior for that default action, but users can set a different default-action by adding a line to newsyslog.conf which uses as the filename. This should cause no change in behavior for the standard usage of newsyslog (ie, run without listing specific filenames). I'd like to commit this on Sunday night (assuming we don't get ANOTHER snow storm this weekend...), unless there's some feedback. I'll soon have a second update, which will implement "-R requestor", which Wes could then take advantage of with his syslog changes. Updates to the man page will come later. I don't want to start writing that until I'm sure everyone's comfortable with the ideas and implementation. I expect to have more changes to newsyslog after these two, so also let me know if there's "other things" you'd like to see. Index: newsyslog.c =================================================================== RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.c,v retrieving revision 1.49 diff -u -r1.49 newsyslog.c --- newsyslog.c 21 Dec 2002 22:27:26 -0000 1.49 +++ newsyslog.c 21 Feb 2003 04:18:55 -0000 @@ -87,9 +87,12 @@ 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 *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 @@ } } p = p->next; - free((char *) q); + free_entry(q); q = p; } while (wait(NULL) > 0 || errno == EINTR) @@ -160,6 +166,77 @@ 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 @@ } 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 @@ { 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ (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 @@ 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 @@ /* 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); -- Garance Alistair Drosehn = gad@gilead.netel.rpi.edu Senior Systems Programmer or gad@freebsd.org Rensselaer Polytechnic Institute or drosih@rpi.edu To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-arch" in the body of the message