Author: sobomax
Date: Sat May 14 03:00:55 2011
New Revision: 221873
URL: http://svn.freebsd.org/changeset/base/221873

Log:
  Add new modifier - "R", when it is specified the path to pid file
  will be considered as a path to a binary or a shell script to be executed
  after rotation has been completed instead of sending signal to the process
  id in that file.
  
  Sponsored by: Sippy Software, Inc.
  From the:     FreeBSD hacking lounge at BSDCan

Modified:
  head/usr.sbin/newsyslog/newsyslog.c
  head/usr.sbin/newsyslog/newsyslog.conf.5

Modified: head/usr.sbin/newsyslog/newsyslog.c
==============================================================================
--- head/usr.sbin/newsyslog/newsyslog.c Sat May 14 02:28:26 2011        
(r221872)
+++ head/usr.sbin/newsyslog/newsyslog.c Sat May 14 03:00:55 2011        
(r221873)
@@ -125,6 +125,7 @@ __FBSDID("$FreeBSD$");
                                /*    process when trimming this file. */
 #define        CE_CREATE       0x0100  /* Create the log file if it does not 
exist. */
 #define        CE_NODUMP       0x0200  /* Set 'nodump' on newly created log 
file. */
+#define        CE_PID2CMD      0x0400  /* Replace PID file with a shell 
command.*/
 
 #define        MIN_PID         5       /* Don't touch pids lower than this */
 #define        MAX_PID         99999   /* was lower, see 
/usr/include/sys/proc.h */
@@ -154,7 +155,7 @@ const struct compress_types compress_typ
 struct conf_entry {
        STAILQ_ENTRY(conf_entry) cf_nextp;
        char *log;              /* Name of the log */
-       char *pid_file;         /* PID file */
+       char *pid_cmd_file;             /* PID or command file */
        char *r_reason;         /* The reason this file is being rotated */
        int firstcreate;        /* Creating log for the first time (-C). */
        int rotate;             /* Non-zero if this file should be rotated */
@@ -178,7 +179,8 @@ struct sigwork_entry {
        int      sw_pidok;              /* true if pid value is valid */
        pid_t    sw_pid;                /* the process id from the PID file */
        const char *sw_pidtype;         /* "daemon" or "process group" */
-       char     sw_fname[1];           /* file the PID was read from */
+       int      run_cmd;               /* run command or send PID to signal */
+       char     sw_fname[1];           /* file the PID was read from or shell 
cmd */
 };
 
 struct zipwork_entry {
@@ -384,9 +386,9 @@ init_entry(const char *fname, struct con
                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->pid_cmd_file = NULL;
+               if (src_entry->pid_cmd_file)
+                       tempwork->pid_cmd_file = 
strdup(src_entry->pid_cmd_file);
                tempwork->r_reason = NULL;
                tempwork->firstcreate = 0;
                tempwork->rotate = 0;
@@ -406,7 +408,7 @@ init_entry(const char *fname, struct con
                tempwork->def_cfg = src_entry->def_cfg;
        } else {
                /* Initialize as a "do-nothing" entry */
-               tempwork->pid_file = NULL;
+               tempwork->pid_cmd_file = NULL;
                tempwork->r_reason = NULL;
                tempwork->firstcreate = 0;
                tempwork->rotate = 0;
@@ -441,9 +443,9 @@ free_entry(struct conf_entry *ent)
                ent->log = NULL;
        }
 
-       if (ent->pid_file != NULL) {
-               free(ent->pid_file);
-               ent->pid_file = NULL;
+       if (ent->pid_cmd_file != NULL) {
+               free(ent->pid_cmd_file);
+               ent->pid_cmd_file = NULL;
        }
 
        if (ent->r_reason != NULL) {
@@ -1291,6 +1293,9 @@ no_trimat:
                        case 'n':
                                working->flags |= CE_NOSIGNAL;
                                break;
+                       case 'r':
+                               working->flags |= CE_PID2CMD;
+                               break;
                        case 'u':
                                working->flags |= CE_SIGNALGROUP;
                                break;
@@ -1324,10 +1329,10 @@ no_trimat:
                        *parse = '\0';
                }
 
-               working->pid_file = NULL;
+               working->pid_cmd_file = NULL;
                if (q && *q) {
                        if (*q == '/')
-                               working->pid_file = strdup(q);
+                               working->pid_cmd_file = strdup(q);
                        else if (isdigit(*q))
                                goto got_sig;
                        else
@@ -1364,16 +1369,16 @@ no_trimat:
                if ((working->flags & CE_NOSIGNAL) == CE_NOSIGNAL) {
                        /*
                         * This config-entry specified 'n' for nosignal,
-                        * see if it also specified an explicit pid_file.
+                        * see if it also specified an explicit pid_cmd_file.
                         * This would be a pretty pointless combination.
                         */
-                       if (working->pid_file != NULL) {
+                       if (working->pid_cmd_file != NULL) {
                                warnx("Ignoring '%s' because flag 'n' was 
specified in line:\n%s",
-                                   working->pid_file, errline);
-                               free(working->pid_file);
-                               working->pid_file = NULL;
+                                   working->pid_cmd_file, errline);
+                               free(working->pid_cmd_file);
+                               working->pid_cmd_file = NULL;
                        }
-               } else if (working->pid_file == NULL) {
+               } else if (working->pid_cmd_file == NULL) {
                        /*
                         * This entry did not specify the 'n' flag, which
                         * means it should signal syslogd unless it had
@@ -1388,7 +1393,7 @@ no_trimat:
                                working->flags &= ~CE_SIGNALGROUP;
                        }
                        if (needroot)
-                               working->pid_file = strdup(path_syslogpid);
+                               working->pid_cmd_file = strdup(path_syslogpid);
                }
 
                /*
@@ -1826,7 +1831,7 @@ do_rotate(const struct conf_entry *ent)
         * multiple log files had to be rotated.
         */
        swork = NULL;
-       if (ent->pid_file != NULL)
+       if (ent->pid_cmd_file != NULL)
                swork = save_sigwork(ent);
        if (ent->numlogs > 0 && ent->compress > COMPRESS_NONE) {
                /*
@@ -1845,6 +1850,7 @@ do_sigwork(struct sigwork_entry *swork)
 {
        struct sigwork_entry *nextsig;
        int kres, secs;
+       char *tmp;
 
        if (!(swork->sw_pidok) || swork->sw_pid == 0)
                return;                 /* no work to do... */
@@ -1887,6 +1893,24 @@ do_sigwork(struct sigwork_entry *swork)
                return;
        }
 
+       if (swork->run_cmd) {
+               asprintf(&tmp, "%s %d", swork->sw_fname, swork->sw_signum);
+               if (tmp == NULL) {
+                       warn("can't allocate memory to run %s",
+                           swork->sw_fname);
+                       return;
+               }
+               if (verbose)
+                       printf("Run command: %s\n", tmp);
+               kres = system(tmp);
+               if (kres) {
+                       warnx("%s: returned non-zero exit code: %d",
+                           tmp, kres);
+               }
+               free(tmp);
+               return;
+       }
+
        kres = kill(swork->sw_pid, swork->sw_signum);
        if (kres != 0) {
                /*
@@ -2016,7 +2040,7 @@ save_sigwork(const struct conf_entry *en
        sprev = NULL;
        ndiff = 1;
        SLIST_FOREACH(stmp, &swhead, sw_nextp) {
-               ndiff = strcmp(ent->pid_file, stmp->sw_fname);
+               ndiff = strcmp(ent->pid_cmd_file, stmp->sw_fname);
                if (ndiff > 0)
                        break;
                if (ndiff == 0) {
@@ -2032,11 +2056,18 @@ save_sigwork(const struct conf_entry *en
        if (stmp != NULL && ndiff == 0)
                return (stmp);
 
-       tmpsiz = sizeof(struct sigwork_entry) + strlen(ent->pid_file) + 1;
+       tmpsiz = sizeof(struct sigwork_entry) + strlen(ent->pid_cmd_file) + 1;
        stmp = malloc(tmpsiz);
-       set_swpid(stmp, ent);
+       
+       stmp->run_cmd = 0;
+       /* If this is a command to run we just set the flag and run command */
+       if (ent->flags & CE_PID2CMD) {
+               stmp->run_cmd = 1;
+       } else {
+               set_swpid(stmp, ent);
+       }
        stmp->sw_signum = ent->sig;
-       strcpy(stmp->sw_fname, ent->pid_file);
+       strcpy(stmp->sw_fname, ent->pid_cmd_file);
        if (sprev == NULL)
                SLIST_INSERT_HEAD(&swhead, stmp, sw_nextp);
        else
@@ -2113,7 +2144,7 @@ set_swpid(struct sigwork_entry *swork, c
                swork->sw_pidtype = "process-group";
        }
 
-       f = fopen(ent->pid_file, "r");
+       f = fopen(ent->pid_cmd_file, "r");
        if (f == NULL) {
                if (errno == ENOENT && enforcepid == 0) {
                        /*
@@ -2124,9 +2155,9 @@ set_swpid(struct sigwork_entry *swork, c
                         * files that the process would have been using.
                         */
                        swork->sw_pidok = 1;
-                       warnx("pid file doesn't exist: %s", ent->pid_file);
+                       warnx("pid file doesn't exist: %s", ent->pid_cmd_file);
                } else
-                       warn("can't open pid file: %s", ent->pid_file);
+                       warn("can't open pid file: %s", ent->pid_cmd_file);
                return;
        }
 
@@ -2139,9 +2170,9 @@ set_swpid(struct sigwork_entry *swork, c
                 */
                if (feof(f) && enforcepid == 0) {
                        swork->sw_pidok = 1;
-                       warnx("pid file is empty: %s", ent->pid_file);
+                       warnx("pid/cmd file is empty: %s", ent->pid_cmd_file);
                } else
-                       warn("can't read from pid file: %s", ent->pid_file);
+                       warn("can't read from pid file: %s", ent->pid_cmd_file);
                (void)fclose(f);
                return;
        }
@@ -2154,10 +2185,10 @@ set_swpid(struct sigwork_entry *swork, c
        rval = strtol(linep, &endp, 10);
        if (*endp != '\0' && !isspacech(*endp)) {
                warnx("pid file does not start with a valid number: %s",
-                   ent->pid_file);
+                   ent->pid_cmd_file);
        } else if (rval < minok || rval > maxok) {
                warnx("bad value '%ld' for process number in %s",
-                   rval, ent->pid_file);
+                   rval, ent->pid_cmd_file);
                if (verbose)
                        warnx("\t(expecting value between %ld and %ld)",
                            minok, maxok);

Modified: head/usr.sbin/newsyslog/newsyslog.conf.5
==============================================================================
--- head/usr.sbin/newsyslog/newsyslog.conf.5    Sat May 14 02:28:26 2011        
(r221872)
+++ head/usr.sbin/newsyslog/newsyslog.conf.5    Sat May 14 03:00:55 2011        
(r221873)
@@ -301,9 +301,16 @@ log file using
 .It Cm N
 indicates that there is no process which needs to be signaled
 when this log file is rotated.
+.It Cm R
+if this flag is set the
+.Xr newsyslog 8
+will run shell command defined in 
+.Ar path_to_pid_cmd_file
+after rotation instead of trying to send signal to a process id
+stored in the file.
 .It Cm U
 indicates that the file specified by
-.Ar path_to_pid_file
+.Ar path_to_pid_cmd_file
 will contain the ID for a process group instead of a process.
 This option also requires that the first line in that file
 be a negative value to distinguish it from a process ID.
@@ -319,7 +326,7 @@ can be used as a placeholder to create a
 .Ar flags
 field when you need to specify any of the following fields.
 .El
-.It Ar path_to_pid_file
+.It Ar path_to_pid_cmd_file
 This optional field specifies the file name containing a daemon's
 process ID or to find a group process ID if the
 .Cm U
@@ -340,6 +347,12 @@ switch.
 This field must start with
 .Ql /
 in order to be recognized properly.
+When used with the
+.Cm R
+flag, the file is treated as a path to a binary to be executed
+by the
+.Xr newsyslog 8
+after rotation instead of sending the signal out.
 .It Ar signal_number
 This optional field specifies the signal number that will be sent
 to the daemon process (or to all processes in a process group, if the
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to