Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Oct 2001 00:27:05 +0900 (JST)
From:      Toshihiko ARAI <toshi@jp.FreeBSD.org>
To:        freebsd-hackers@FreeBSD.org
Subject:   [patch] extension of newsyslog
Message-ID:  <200110081527.f98FR5A56224.toshi@jp.FreeBSD.org>

next in thread | raw e-mail | index | archive | help
Hello,

I add script call features to newsyslog.  This adds a one field to
newsyslog.conf.  When newsyslog processed log file, this can execute
arbitrary program.

Situation to assume:
 * For the log file which cannot use signal.
 * Cases to do statistical application for log file.

A sample entry of newsylog.conf:
# logfilename  [owner:group] mode count size when [ZB] [/pid_file] [sig_num] [/program]
/var/log/foo.log  bar:baz    640  1     100  *     Z   -  -  /etc/foo.sh

'-' is usable as a filler of null field.

I used similar enhanced function from the past.  I think that you can
apply this patch for 5-current.  In addition, I can prepare a patch
for 4-stable if it is necessary.

I ask for testing and a review of the following patches.

Thanks.
--
Toshihiko ARAI


Index: newsyslog.8
===================================================================
RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.8,v
retrieving revision 1.32
diff -u -r1.32 newsyslog.8
--- newsyslog.8	2001/07/30 15:17:17	1.32
+++ newsyslog.8	2001/09/30 08:54:07
@@ -76,7 +76,7 @@
 Each line of the file contains information about a particular log file
 that should be handled by
 .Nm .
-Each line has five mandatory fields and four optional fields, with
+Each line has five mandatory fields and five optional fields, with
 whitespace separating each field.  Blank lines or lines beginning with
 ``#'' are ignored.  The fields of the configuration file are as
 follows:
@@ -294,12 +294,28 @@
 .Ar signal_number
 is sent the process id contained in this
 file.  This field must start with "/" in order to be recognized
-properly.
+properly.  Same as
+.Ar flags
+field, you can use "-" for null field.
 .It Ar signal_number
 This optional field specifies
-the signal number will be sent to the daemon process.
+the signal number or signal name will be sent to the daemon process.
 By default
-a SIGHUP will be sent.
+a SIGHUP will be sent.  Same as
+.Ar flags
+field, you can use "-" for null field.
+.It Ar path_to_program
+This optional field specifies
+the path name of a script for postprocessing of log file. 
+This field must be specified with full path.
+And a file must be execute permission by specified
+.Ar owner
+and
+.Ar group .
+When
+.Ar path_to_program
+is called, new log file is given to the first argument, and old
+log file is given to the second argument.
 .El
 .Sh OPTIONS
 The following options can be used with
Index: newsyslog.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.c,v
retrieving revision 1.37
diff -u -r1.37 newsyslog.c
--- newsyslog.c	2001/07/31 16:25:55	1.37
+++ newsyslog.c	2001/10/08 14:09:19
@@ -38,6 +38,7 @@
 
 #include <ctype.h>
 #include <err.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <grp.h>
 #include <paths.h>
@@ -73,6 +74,7 @@
 struct conf_entry {
 	char *log;		/* Name of the log */
 	char *pid_file;		/* PID file */
+	char *prog;		/* Program for postprocessing */
 	int uid;		/* Owner of log */
 	int gid;		/* Group of log */
 	int numlogs;		/* Number of logs to keep */
@@ -106,11 +108,13 @@
 static void do_entry(struct conf_entry * ent);
 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 void dotrim(char *log, const char *pid_file, const char *prog,
+		int numdays, int falgs, int perm, int owner_uid,
+		int group_gid, int sig);
 static int log_trim(char *log);
 static void compress_log(char *log);
 static void bzcompress_log(char *log);
+static int post_prog(const char *prog, char *log, int owner_uid, int group_gid);
 static int sizefile(char *file);
 static int age_old_log(char *file);
 static pid_t get_pid(const char *pid_file);
@@ -119,6 +123,7 @@
 		int group_gid);
 static void createdir(char *dirpart);
 static time_t parseDWM(char *s);
+static int signame_to_signum(char *sig);
 
 int
 main(int argc, char **argv)
@@ -200,7 +205,7 @@
 				else
 					pid_file = NULL;
 			}
-			dotrim(ent->log, pid_file, ent->numlogs,
+			dotrim(ent->log, pid_file, ent->prog, ent->numlogs,
 			    ent->flags, ent->permissions, ent->uid, ent->gid,
 			    ent->sig);
 		} else {
@@ -460,34 +465,52 @@
 		if (q && *q) {
 			if (*q == '/')
 				working->pid_file = strdup(q);
-			else if (isdigit(*q))
+			else if (isalnum(*q))
 				goto got_sig;
-			else
-				errx(1,
-			"illegal pid file or signal number in config file:\n%s",
+			else if (*q != '-')
+				errx(1, "illegal pid file in config file:\n%s",
 				    errline);
 		}
+
 		if (eol)
 			q = NULL;
 		else {
 			q = parse = sob(++parse);	/* Optional field */
-			*(parse = son(parse)) = '\0';
+			parse = son(parse);
+			if (!*parse)
+				eol = 1;
+			*parse = '\0';
 		}
 
+	got_sig:
 		working->sig = SIGHUP;
 		if (q && *q) {
-			if (isdigit(*q)) {
-		got_sig:
+			if (isdigit(*q))
 				working->sig = atoi(q);
-			} else {
-		err_sig:
+			else if (*q != '-')
+				working->sig = signame_to_signum(q);
+			if (working->sig < 1 || working->sig >= NSIG)
 				errx(1,
 				    "illegal signal number in config file:\n%s",
 				    errline);
-			}
-			if (working->sig < 1 || working->sig >= NSIG)
-				goto err_sig;
 		}
+
+		if (eol)
+			q = NULL;
+		else {
+			q = parse = sob(++parse);	/* Optional field */
+			*(parse = son(parse)) = '\0';
+		}
+
+		working->prog = NULL;
+		if (q && *q) {
+			if (*q == '/')
+				working->prog = strdup(q);
+			else if (*q != '-')
+				errx(1,
+				    "illegal program file in config file:\n%s",
+				    errline);
+  		}
 		free(errline);
 	}
 	if (working)
@@ -506,14 +529,14 @@
 }
 
 static void
-dotrim(char *log, const char *pid_file, int numdays, int flags, int perm,
-    int owner_uid, int group_gid, int sig)
+dotrim(char *log, const char *pid_file, const char *prog, int numdays,
+    int flags, int perm, int owner_uid, int group_gid, int sig)
 {
 	char dirpart[MAXPATHLEN], namepart[MAXPATHLEN];
 	char file1[MAXPATHLEN], file2[MAXPATHLEN];
 	char zfile1[MAXPATHLEN], zfile2[MAXPATHLEN];
 	char jfile1[MAXPATHLEN];
-	int notified, need_notification, fd, _numdays;
+	int notified, need_notification, pstat, fd, _numdays;
 	struct stat st;
 	pid_t pid;
 
@@ -660,7 +683,7 @@
 		(void) chmod(log, perm);
 
 	pid = 0;
-	need_notification = notified = 0;
+	need_notification = notified = pstat = 0;
 	if (pid_file != NULL) {
 		need_notification = 1;
 		pid = get_pid(pid_file);
@@ -677,11 +700,29 @@
 				printf("daemon pid %d notified\n", (int) pid);
 		}
 	}
+	if (prog != NULL) {
+		if (need_notification && !notified)
+			warnx("don't run %s because signal is not notified",
+			      prog);
+		else if (noaction)
+			printf("Exec %s %s %s.0\n", prog, log, log);
+		else {
+			pstat = post_prog(prog, log, owner_uid, group_gid);
+			if (pstat != 0)
+				warnx("%s returned exit status %d",
+				      prog, WEXITSTATUS(pstat));
+			else if (verbose)
+				printf("exec %s done\n", prog);
+		}
+	}
 	if ((flags & CE_COMPACT) || (flags & CE_BZCOMPACT)) {
 		if (need_notification && !notified)
 			warnx(
 			    "log %s not compressed because daemon not notified",
 			    log);
+		else if (pstat != 0)
+			warnx("log %s is not compressed because %s failed",
+			      log, prog);
 		else if (noaction)
 			printf("Compress %s.0\n", log);
 		else {
@@ -756,6 +797,32 @@
 	}
 }
 
+/* Program run for postprocessing of log file */
+static int
+post_prog(const char *prog, char *log, int owner_uid, int group_gid)
+{
+	pid_t pid;
+	int pstat;
+
+	pid = vfork();
+	if (pid < 0)
+		err(1, "can't vfork");
+	else if (pid == 0) {
+		char tmp[MAXPATHLEN];
+
+		(void) snprintf(tmp, sizeof(tmp), "%s.0", log);
+		if (group_gid != NONE)
+			setgid(group_gid);
+		if (owner_uid != NONE)
+			setuid(owner_uid);
+		(void) execl(prog, prog, log, tmp, NULL);
+		warn("can't exec %s", prog);
+		_exit(1);
+	}
+	while (waitpid(pid, &pstat, 0) == -1 && errno == EINTR);
+	return pstat;
+}
+
 /* Return size in kilobytes of a file */
 static int
 sizefile(char *file)
@@ -1100,3 +1167,19 @@
 	}
 	return mktime(&tm);
 }
+
+/* Convert a signal name into signal number */
+static int
+signame_to_signum(char *sig)
+{
+	int n;
+
+	if (!strncasecmp(sig, "sig", (size_t)3))
+		sig += 3;
+	for (n = 1; n < NSIG; n++) {
+		if (!strcasecmp(sys_signame[n], sig))
+			return (n);
+	}
+	return (-1);
+}
+

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




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