Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Feb 2003 23:35:56 -0500
From:      Garance A Drosihn <drosih@rpi.edu>
To:        Wes Peters <wes@softweyr.com>
Cc:        arch@FreeBSD.ORG
Subject:   Re: syslog.conf syntax change (multiple program/host specifications)
Message-ID:  <p05200f08ba7b59fffe0a@[128.113.24.47]>
In-Reply-To: <200302150905.08387.wes@softweyr.com>
References:  <20030210114930.GB90800@melusine.cuivre.fr.eu.org> <200302141733.29304.wes@softweyr.com> <p05200f1cba73875fbc8d@[128.113.24.47]> <200302150905.08387.wes@softweyr.com>

next in thread | previous in thread | raw e-mail | index | archive | help
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 <default> 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 <default> rule for this file */
  	struct conf_entry *next;/* Linked list pointer */
  };

+#define DEFAULT_MARKER "<default>"
+
  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 <default> 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 <default> 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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?p05200f08ba7b59fffe0a>