From owner-freebsd-hackers Mon Oct 8 9:10:10 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from air.linkclub.or.jp (air.linkclub.or.jp [210.250.19.40]) by hub.freebsd.org (Postfix) with ESMTP id 781BD37B401 for ; Mon, 8 Oct 2001 09:09:55 -0700 (PDT) Received: from localhost.jp.FreeBSD.org (1Cust217.tnt1.hanno.jp.da.uu.net [63.12.195.217]) by air.linkclub.or.jp (8.11.4/8.11.4) with ESMTP id f98G3xW38706 for ; Tue, 9 Oct 2001 01:04:03 +0900 (JST) (envelope-from toshi@jp.FreeBSD.org) Date: Tue, 9 Oct 2001 00:27:05 +0900 (JST) Message-Id: <200110081527.f98FR5A56224.toshi@jp.FreeBSD.org> From: Toshihiko ARAI To: freebsd-hackers@FreeBSD.org Subject: [patch] extension of newsyslog X-Mailer: VM 5.96 (beta) / Mule 2.3 (SUETSUMUHANA) based on 19.34.1 Mime-Version: 1.0 (generated by tm-edit 7.106) Content-Type: text/plain; charset=US-ASCII Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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 #include +#include #include #include #include @@ -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