Home | History | Annotate | Line # | Download | only in newsyslog
newsyslog.c revision 1.21
      1  1.21        ad /*	$NetBSD: newsyslog.c,v 1.21 1999/11/30 12:03:24 ad Exp $	*/
      2  1.12   thorpej 
      3   1.1       cgd /*
      4   1.1       cgd  * This file contains changes from the Open Software Foundation.
      5   1.1       cgd  */
      6   1.1       cgd 
      7   1.1       cgd /*
      8   1.1       cgd 
      9   1.2       cgd Copyright 1988, 1989 by the Massachusetts Institute of Technology
     10   1.1       cgd 
     11   1.2       cgd Permission to use, copy, modify, and distribute this software
     12   1.2       cgd and its documentation for any purpose and without fee is
     13   1.2       cgd hereby granted, provided that the above copyright notice
     14   1.2       cgd appear in all copies and that both that copyright notice and
     15   1.2       cgd this permission notice appear in supporting documentation,
     16   1.2       cgd and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
     17   1.2       cgd used in advertising or publicity pertaining to distribution
     18   1.2       cgd of the software without specific, written prior permission.
     19   1.2       cgd M.I.T. and the M.I.T. S.I.P.B. make no representations about
     20   1.2       cgd the suitability of this software for any purpose.  It is
     21   1.2       cgd provided "as is" without express or implied warranty.
     22   1.1       cgd 
     23   1.1       cgd */
     24   1.1       cgd 
     25   1.1       cgd /*
     26   1.1       cgd  *      newsyslog - roll over selected logs at the appropriate time,
     27   1.1       cgd  *              keeping the a specified number of backup files around.
     28   1.1       cgd  */
     29   1.1       cgd 
     30  1.13     lukem #include <sys/cdefs.h>
     31   1.5   mycroft #ifndef lint
     32  1.21        ad __RCSID("$NetBSD: newsyslog.c,v 1.21 1999/11/30 12:03:24 ad Exp $");
     33   1.5   mycroft #endif /* not lint */
     34   1.1       cgd 
     35   1.1       cgd #ifndef CONF
     36   1.1       cgd #define CONF "/etc/athena/newsyslog.conf" /* Configuration file */
     37   1.1       cgd #endif
     38   1.1       cgd #ifndef PIDFILE
     39   1.1       cgd #define PIDFILE "/etc/syslog.pid"
     40   1.1       cgd #endif
     41   1.1       cgd #ifndef COMPRESS
     42   1.1       cgd #define COMPRESS "/usr/ucb/compress" /* File compression program */
     43   1.1       cgd #endif
     44   1.3       cgd #ifndef COMPRESS_POSTFIX
     45   1.3       cgd #define COMPRESS_POSTFIX ".Z"
     46   1.3       cgd #endif
     47   1.1       cgd 
     48   1.1       cgd #include <sys/types.h>
     49   1.1       cgd #include <sys/time.h>
     50   1.1       cgd #include <sys/stat.h>
     51   1.1       cgd #include <sys/param.h>
     52   1.1       cgd #include <sys/wait.h>
     53   1.1       cgd 
     54  1.13     lukem #include <ctype.h>
     55  1.13     lukem #include <fcntl.h>
     56  1.13     lukem #include <grp.h>
     57  1.13     lukem #include <pwd.h>
     58  1.13     lukem #include <signal.h>
     59  1.13     lukem #include <stdio.h>
     60  1.13     lukem #include <stdlib.h>
     61  1.13     lukem #include <string.h>
     62  1.14    kleink #include <time.h>
     63  1.13     lukem #include <unistd.h>
     64  1.13     lukem 
     65   1.1       cgd #define kbytes(size)  (((size) + 1023) >> 10)
     66   1.1       cgd #ifdef _IBMR2
     67   1.1       cgd /* Calculates (db * DEV_BSIZE) */
     68   1.1       cgd #define dbtob(db)  ((unsigned)(db) << UBSHIFT)
     69   1.1       cgd #endif
     70   1.1       cgd 
     71   1.1       cgd #define CE_COMPACT 1            /* Compact the achived log files */
     72   1.1       cgd #define CE_BINARY 2             /* Logfile is in binary, don't add */
     73   1.1       cgd                                 /* status messages */
     74  1.21        ad #define CE_NOSIGNAL 4           /* Don't send a signal when trimmed */
     75   1.1       cgd #define NONE -1
     76   1.1       cgd 
     77   1.1       cgd struct conf_entry {
     78   1.1       cgd         char    *log;           /* Name of the log */
     79   1.1       cgd         int     uid;            /* Owner of log */
     80   1.1       cgd         int     gid;            /* Group of log */
     81   1.1       cgd         int     numlogs;        /* Number of logs to keep */
     82   1.1       cgd         int     size;           /* Size cutoff to trigger trimming the log */
     83   1.1       cgd         int     hours;          /* Hours between log trimming */
     84   1.1       cgd         int     permissions;    /* File permissions on the log */
     85  1.21        ad         int     flags;          /* Flags (CE_*) */
     86  1.20        ad         char	*pidfile;	/* Name of file containing PID to signal */
     87  1.21        ad         int	signum;		/* Signal to send */
     88   1.1       cgd         struct conf_entry       *next; /* Linked list pointer */
     89   1.1       cgd };
     90   1.1       cgd 
     91   1.1       cgd char    *progname;              /* contains argv[0] */
     92   1.1       cgd int     verbose = 0;            /* Print out what's going on */
     93   1.1       cgd int     needroot = 1;           /* Root privs are necessary */
     94   1.1       cgd int     noaction = 0;           /* Don't do anything, just show it */
     95  1.21        ad int	force;			/* Force the trim no matter what */
     96   1.1       cgd char    *conf = CONF;           /* Configuration file to use */
     97   1.1       cgd time_t  timenow;
     98   1.1       cgd int     syslog_pid;             /* read in from /etc/syslog.pid */
     99   1.7        pk #define MIN_PID		3
    100   1.7        pk #define MAX_PID		65534
    101  1.15       mrg char    hostname[MAXHOSTNAMELEN + 1];           /* hostname */
    102   1.1       cgd char    *daytime;               /* timenow in human readable form */
    103   1.1       cgd 
    104   1.1       cgd 
    105  1.13     lukem void	PRS __P((int, char **));
    106  1.13     lukem int	age_old_log __P((char *));
    107  1.13     lukem void	compress_log __P((char *));
    108  1.21        ad void	dotrim __P((char *, int, int, int, int, int, char *, int));
    109  1.13     lukem void	do_entry __P((struct conf_entry *));
    110  1.13     lukem int	isnumber __P((char *));
    111  1.13     lukem int	log_trim __P((char *));
    112  1.13     lukem int	main __P((int, char **));
    113  1.13     lukem char   *missing_field __P((char *, char *));
    114  1.13     lukem struct conf_entry *parse_file __P((void));
    115  1.13     lukem int	sizefile __P((char *));
    116  1.13     lukem char   *sob __P((char *));
    117  1.13     lukem char   *son __P((char *));
    118  1.13     lukem void	usage __P((void));
    119  1.21        ad int	getsig __P((char *));
    120   1.1       cgd 
    121  1.13     lukem int
    122   1.1       cgd main(argc,argv)
    123   1.1       cgd         int argc;
    124   1.1       cgd         char **argv;
    125   1.1       cgd {
    126   1.1       cgd         struct conf_entry *p, *q;
    127   1.1       cgd 
    128   1.1       cgd         PRS(argc,argv);
    129   1.1       cgd         if (needroot && getuid() && geteuid()) {
    130   1.1       cgd                 fprintf(stderr,"%s: must have root privs\n",progname);
    131   1.1       cgd                 exit(1);
    132   1.1       cgd         }
    133   1.1       cgd         p = q = parse_file();
    134   1.1       cgd         while (p) {
    135   1.1       cgd                 do_entry(p);
    136   1.1       cgd                 p=p->next;
    137   1.1       cgd                 free((char *) q);
    138   1.1       cgd                 q=p;
    139   1.1       cgd         }
    140   1.1       cgd         exit(0);
    141   1.1       cgd }
    142   1.1       cgd 
    143  1.13     lukem void
    144   1.1       cgd do_entry(ent)
    145   1.1       cgd         struct conf_entry       *ent;
    146   1.1       cgd {
    147   1.1       cgd         int     size, modtime;
    148   1.1       cgd 
    149   1.1       cgd         if (verbose) {
    150   1.1       cgd                 if (ent->flags & CE_COMPACT)
    151   1.1       cgd                         printf("%s <%dZ>: ",ent->log,ent->numlogs);
    152   1.1       cgd                 else
    153   1.1       cgd                         printf("%s <%d>: ",ent->log,ent->numlogs);
    154   1.1       cgd         }
    155   1.1       cgd         size = sizefile(ent->log);
    156   1.1       cgd         modtime = age_old_log(ent->log);
    157   1.1       cgd         if (size < 0) {
    158   1.1       cgd                 if (verbose)
    159   1.1       cgd                         printf("does not exist.\n");
    160   1.1       cgd         } else {
    161   1.1       cgd                 if (verbose && (ent->size > 0))
    162   1.1       cgd                         printf("size (Kb): %d [%d] ", size, ent->size);
    163   1.1       cgd                 if (verbose && (ent->hours > 0))
    164   1.1       cgd                         printf(" age (hr): %d [%d] ", modtime, ent->hours);
    165  1.21        ad                 if (force || ((ent->size > 0) && (size >= ent->size)) ||
    166   1.1       cgd                     ((ent->hours > 0) && ((modtime >= ent->hours)
    167   1.1       cgd                                         || (modtime < 0)))) {
    168   1.1       cgd                         if (verbose)
    169   1.1       cgd                                 printf("--> trimming log....\n");
    170   1.1       cgd                         if (noaction && !verbose) {
    171   1.1       cgd                                 if (ent->flags & CE_COMPACT)
    172   1.1       cgd                                         printf("%s <%dZ>: trimming",
    173   1.1       cgd                                                ent->log,ent->numlogs);
    174   1.1       cgd                                 else
    175   1.1       cgd                                         printf("%s <%d>: trimming",
    176   1.1       cgd                                                ent->log,ent->numlogs);
    177   1.1       cgd                         }
    178   1.1       cgd                         dotrim(ent->log, ent->numlogs, ent->flags,
    179  1.20        ad                                ent->permissions, ent->uid, ent->gid,
    180  1.21        ad                                ent->pidfile, ent->signum);
    181   1.1       cgd                 } else {
    182   1.1       cgd                         if (verbose)
    183   1.1       cgd                                 printf("--> skipping\n");
    184   1.1       cgd                 }
    185   1.1       cgd         }
    186   1.1       cgd }
    187   1.1       cgd 
    188  1.13     lukem void
    189   1.1       cgd PRS(argc,argv)
    190   1.1       cgd         int argc;
    191   1.1       cgd         char **argv;
    192   1.1       cgd {
    193   1.1       cgd         int     c;
    194   1.1       cgd         FILE    *f;
    195   1.1       cgd         char    line[BUFSIZ];
    196   1.8       jtc 	char	*p;
    197   1.1       cgd 
    198   1.1       cgd         progname = argv[0];
    199   1.1       cgd         timenow = time((time_t *) 0);
    200   1.8       jtc         daytime = ctime(&timenow) + 4;
    201  1.10        pk         daytime[15] = '\0';
    202   1.1       cgd 
    203   1.1       cgd         /* Let's find the pid of syslogd */
    204   1.1       cgd         syslog_pid = 0;
    205   1.1       cgd         f = fopen(PIDFILE,"r");
    206   1.1       cgd         if (f && fgets(line,BUFSIZ,f))
    207   1.1       cgd                 syslog_pid = atoi(line);
    208   1.7        pk 	if (f)
    209   1.7        pk 		(void)fclose(f);
    210   1.1       cgd 
    211   1.1       cgd         /* Let's get our hostname */
    212  1.15       mrg         (void)gethostname(hostname, sizeof(hostname));
    213  1.15       mrg 	hostname[sizeof(hostname) - 1] = '\0';
    214   1.8       jtc 
    215   1.8       jtc 	/* Truncate domain */
    216  1.13     lukem 	if ((p = strchr(hostname, '.')) != NULL) {
    217   1.8       jtc 		*p = '\0';
    218   1.8       jtc 	}
    219   1.1       cgd 
    220   1.1       cgd         optind = 1;             /* Start options parsing */
    221  1.21        ad         while ((c=getopt(argc,argv,"Fnrvf:")) != -1)
    222   1.1       cgd                 switch (c) {
    223   1.1       cgd                 case 'n':
    224   1.1       cgd                         noaction++; /* This implies needroot as off */
    225   1.1       cgd                         /* fall through */
    226   1.1       cgd                 case 'r':
    227   1.1       cgd                         needroot = 0;
    228   1.1       cgd                         break;
    229   1.1       cgd                 case 'v':
    230   1.1       cgd                         verbose++;
    231   1.1       cgd                         break;
    232   1.1       cgd                 case 'f':
    233   1.1       cgd                         conf = optarg;
    234   1.1       cgd                         break;
    235  1.21        ad                 case 'F':
    236  1.21        ad                         force++;
    237  1.21        ad                         break;
    238   1.1       cgd                 default:
    239   1.1       cgd                         usage();
    240   1.1       cgd                 }
    241  1.13     lukem }
    242   1.1       cgd 
    243  1.13     lukem void
    244   1.1       cgd usage()
    245   1.1       cgd {
    246   1.1       cgd         fprintf(stderr,
    247  1.21        ad                 "Usage: %s <-Fnrv> <-f config-file>\n", progname);
    248   1.1       cgd         exit(1);
    249   1.1       cgd }
    250   1.1       cgd 
    251   1.1       cgd /* Parse a configuration file and return a linked list of all the logs
    252   1.1       cgd  * to process
    253   1.1       cgd  */
    254  1.13     lukem struct conf_entry *
    255  1.13     lukem parse_file()
    256   1.1       cgd {
    257   1.1       cgd         FILE    *f;
    258   1.1       cgd         char    line[BUFSIZ], *parse, *q;
    259  1.21        ad         char    *errline, *group, prev;
    260   1.1       cgd         struct conf_entry *first = NULL;
    261   1.1       cgd         struct conf_entry *working;
    262   1.1       cgd         struct passwd *pass;
    263   1.1       cgd         struct group *grp;
    264   1.1       cgd 
    265  1.13     lukem 	working = NULL;
    266   1.1       cgd         if (strcmp(conf,"-"))
    267   1.1       cgd                 f = fopen(conf,"r");
    268   1.1       cgd         else
    269   1.1       cgd                 f = stdin;
    270   1.1       cgd         if (!f) {
    271   1.1       cgd                 (void) fprintf(stderr,"%s: ",progname);
    272   1.1       cgd                 perror(conf);
    273   1.1       cgd                 exit(1);
    274   1.1       cgd         }
    275   1.1       cgd         while (fgets(line,BUFSIZ,f)) {
    276   1.1       cgd                 if ((line[0]== '\n') || (line[0] == '#'))
    277   1.1       cgd                         continue;
    278   1.1       cgd                 errline = strdup(line);
    279   1.1       cgd                 if (!first) {
    280   1.1       cgd                         working = (struct conf_entry *) malloc(sizeof(struct conf_entry));
    281   1.1       cgd                         first = working;
    282   1.1       cgd                 } else {
    283   1.1       cgd                         working->next = (struct conf_entry *) malloc(sizeof(struct conf_entry));
    284   1.1       cgd                         working = working->next;
    285   1.1       cgd                 }
    286   1.1       cgd 
    287   1.1       cgd                 q = parse = missing_field(sob(line),errline);
    288   1.1       cgd                 *(parse = son(line)) = '\0';
    289   1.1       cgd                 working->log = strdup(q);
    290   1.1       cgd 
    291   1.1       cgd                 q = parse = missing_field(sob(++parse),errline);
    292   1.1       cgd                 *(parse = son(parse)) = '\0';
    293  1.19        ad                 if ((group = strchr(q, ':')) != NULL || (group = strchr(q, '.')) != NULL) {
    294   1.1       cgd                     *group++ = '\0';
    295   1.1       cgd                     if (*q) {
    296   1.1       cgd                         if (!(isnumber(q))) {
    297   1.1       cgd                             if ((pass = getpwnam(q)) == NULL) {
    298   1.1       cgd                                 fprintf(stderr,
    299   1.1       cgd                                     "Error in config file; unknown user:\n");
    300   1.1       cgd                                 fputs(errline,stderr);
    301   1.1       cgd                                 exit(1);
    302   1.1       cgd                             }
    303   1.1       cgd                             working->uid = pass->pw_uid;
    304   1.1       cgd                         } else
    305   1.1       cgd                             working->uid = atoi(q);
    306   1.1       cgd                     } else
    307   1.1       cgd                         working->uid = NONE;
    308   1.1       cgd 
    309   1.1       cgd                     q = group;
    310   1.1       cgd                     if (*q) {
    311   1.1       cgd                         if (!(isnumber(q))) {
    312   1.1       cgd                             if ((grp = getgrnam(q)) == NULL) {
    313   1.1       cgd                                 fprintf(stderr,
    314   1.1       cgd                                     "Error in config file; unknown group:\n");
    315   1.1       cgd                                 fputs(errline,stderr);
    316   1.1       cgd                                 exit(1);
    317   1.1       cgd                             }
    318   1.1       cgd                             working->gid = grp->gr_gid;
    319   1.1       cgd                         } else
    320   1.1       cgd                             working->gid = atoi(q);
    321   1.1       cgd                     } else
    322   1.1       cgd                         working->gid = NONE;
    323   1.1       cgd 
    324   1.1       cgd                     q = parse = missing_field(sob(++parse),errline);
    325   1.1       cgd                     *(parse = son(parse)) = '\0';
    326   1.1       cgd                 }
    327   1.1       cgd                 else
    328   1.1       cgd                     working->uid = working->gid = NONE;
    329   1.1       cgd 
    330   1.1       cgd                 if (!sscanf(q,"%o",&working->permissions)) {
    331   1.1       cgd                         fprintf(stderr,
    332   1.1       cgd                                 "Error in config file; bad permissions:\n");
    333   1.1       cgd                         fputs(errline,stderr);
    334   1.1       cgd                         exit(1);
    335   1.1       cgd                 }
    336   1.1       cgd 
    337   1.1       cgd                 q = parse = missing_field(sob(++parse),errline);
    338   1.1       cgd                 *(parse = son(parse)) = '\0';
    339   1.1       cgd                 if (!sscanf(q,"%d",&working->numlogs)) {
    340   1.1       cgd                         fprintf(stderr,
    341   1.1       cgd                                 "Error in config file; bad number:\n");
    342   1.1       cgd                         fputs(errline,stderr);
    343   1.1       cgd                         exit(1);
    344   1.1       cgd                 }
    345   1.1       cgd 
    346   1.1       cgd                 q = parse = missing_field(sob(++parse),errline);
    347   1.1       cgd                 *(parse = son(parse)) = '\0';
    348  1.17  christos                 if (isdigit((unsigned char)*q))
    349   1.1       cgd                         working->size = atoi(q);
    350   1.1       cgd                 else
    351   1.1       cgd                         working->size = -1;
    352   1.1       cgd 
    353   1.1       cgd                 q = parse = missing_field(sob(++parse),errline);
    354   1.1       cgd                 *(parse = son(parse)) = '\0';
    355  1.17  christos                 if (isdigit((unsigned char)*q))
    356   1.1       cgd                         working->hours = atoi(q);
    357   1.1       cgd                 else
    358   1.1       cgd                         working->hours = -1;
    359   1.1       cgd 
    360   1.1       cgd                 q = parse = sob(++parse); /* Optional field */
    361  1.21        ad                 prev = *(parse = son(parse));
    362  1.21        ad                 *parse = '\0';
    363   1.1       cgd                 working->flags = 0;
    364  1.17  christos                 while (q && *q && !isspace((unsigned char)*q)) {
    365   1.1       cgd                         if ((*q == 'Z') || (*q == 'z'))
    366   1.1       cgd                                 working->flags |= CE_COMPACT;
    367   1.1       cgd                         else if ((*q == 'B') || (*q == 'b'))
    368   1.1       cgd                                 working->flags |= CE_BINARY;
    369  1.21        ad                         else if ((*q == 'N') || (*q == 'n'))
    370  1.21        ad                                 working->flags |= CE_NOSIGNAL;
    371  1.21        ad                         else if (*q != '-') {
    372   1.1       cgd                                 fprintf(stderr,
    373   1.1       cgd                                         "Illegal flag in config file -- %c\n",
    374   1.1       cgd                                         *q);
    375   1.1       cgd                                 exit(1);
    376   1.1       cgd                         }
    377   1.1       cgd                         q++;
    378   1.1       cgd                 }
    379  1.20        ad 
    380  1.21        ad                 if (prev != '\0' && (q = parse = sob(++parse)) != NULL &&
    381  1.21        ad                     q[0] == '/') {
    382  1.21        ad                 	prev = *(parse = son(parse));
    383  1.21        ad                 	*parse++ = '\0';
    384  1.21        ad                		working->pidfile = strdup(q);
    385  1.21        ad                	} else {
    386  1.21        ad                		working->pidfile = NULL;
    387  1.21        ad 			prev = *parse;
    388  1.21        ad 		}
    389  1.21        ad 
    390  1.21        ad                 if (prev != '\0' && (q = parse = sob(parse)) != NULL &&
    391  1.21        ad                     q[0] != '\0') {
    392  1.20        ad                 	*(parse = son(parse)) = '\0';
    393  1.21        ad                		if ((working->signum = getsig(q)) < 0) {
    394  1.21        ad                			fprintf(stderr,
    395  1.21        ad                                     "Illegal signal in config file -- %s\n",
    396  1.21        ad                                     q);
    397  1.21        ad                                 exit(1);
    398  1.21        ad                         }
    399  1.20        ad                	} else
    400  1.21        ad                		working->signum = SIGHUP;
    401   1.1       cgd 
    402   1.1       cgd                 free(errline);
    403   1.1       cgd         }
    404   1.1       cgd         if (working)
    405   1.1       cgd                 working->next = (struct conf_entry *) NULL;
    406   1.1       cgd         (void) fclose(f);
    407   1.1       cgd         return(first);
    408   1.1       cgd }
    409   1.1       cgd 
    410  1.13     lukem char *
    411  1.13     lukem missing_field(p,errline)
    412   1.1       cgd         char    *p,*errline;
    413   1.1       cgd {
    414   1.1       cgd         if (!p || !*p) {
    415   1.1       cgd                 fprintf(stderr,"Missing field in config file:\n");
    416   1.1       cgd                 fputs(errline,stderr);
    417   1.1       cgd                 exit(1);
    418   1.1       cgd         }
    419   1.1       cgd         return(p);
    420   1.1       cgd }
    421   1.1       cgd 
    422  1.13     lukem void
    423  1.21        ad dotrim(log,numdays,flags,perm,owner_uid,group_gid,pidfile,signum)
    424   1.1       cgd         char    *log;
    425   1.1       cgd         int     numdays;
    426   1.1       cgd         int     flags;
    427   1.1       cgd         int     perm;
    428   1.1       cgd         int     owner_uid;
    429   1.1       cgd         int     group_gid;
    430  1.20        ad         char	*pidfile;
    431  1.21        ad         int	signum;
    432   1.1       cgd {
    433   1.1       cgd         char    file1[128], file2[128];
    434   1.1       cgd         char    zfile1[128], zfile2[128];
    435  1.20        ad 	char    line[BUFSIZ];
    436   1.1       cgd         int     fd;
    437   1.1       cgd         struct  stat st;
    438  1.11   thorpej         int     ngen = numdays;
    439  1.20        ad         FILE    *f;
    440  1.20        ad         pid_t   pid;
    441   1.1       cgd 
    442   1.1       cgd #ifdef _IBMR2
    443   1.1       cgd /* AIX 3.1 has a broken fchown- if the owner_uid is -1, it will actually */
    444   1.1       cgd /* change it to be owned by uid -1, instead of leaving it as is, as it is */
    445   1.1       cgd /* supposed to. */
    446   1.1       cgd                 if (owner_uid == -1)
    447   1.1       cgd                   owner_uid = geteuid();
    448   1.1       cgd #endif
    449   1.1       cgd 
    450  1.20        ad         if (pidfile != NULL && pidfile[0] != '\0') {
    451  1.20        ad        		if ((f = fopen(pidfile,"r")) == NULL) {
    452  1.20        ad        			(void) fprintf(stderr,"%s: ",progname);
    453  1.20        ad                 	perror(conf);
    454  1.20        ad                 	return;
    455  1.20        ad                 }
    456  1.20        ad 
    457  1.20        ad        		if (fgets(line,BUFSIZ,f))
    458  1.20        ad        	        	pid = atoi(line);
    459  1.20        ad 		if (f)
    460  1.20        ad 			(void)fclose(f);
    461  1.20        ad 	} else
    462  1.20        ad 		pid = syslog_pid;
    463  1.20        ad 
    464   1.1       cgd         /* Remove oldest log */
    465   1.1       cgd         (void) sprintf(file1,"%s.%d",log,numdays);
    466   1.1       cgd         (void) strcpy(zfile1, file1);
    467   1.3       cgd         (void) strcat(zfile1, COMPRESS_POSTFIX);
    468   1.1       cgd 
    469   1.1       cgd         if (noaction) {
    470   1.1       cgd                 printf("rm -f %s\n", file1);
    471   1.1       cgd                 printf("rm -f %s\n", zfile1);
    472   1.1       cgd         } else {
    473   1.1       cgd                 (void) unlink(file1);
    474   1.1       cgd                 (void) unlink(zfile1);
    475   1.1       cgd         }
    476   1.1       cgd 
    477   1.1       cgd         /* Move down log files */
    478   1.1       cgd         while (numdays--) {
    479   1.1       cgd                 (void) strcpy(file2,file1);
    480   1.1       cgd                 (void) sprintf(file1,"%s.%d",log,numdays);
    481   1.1       cgd                 (void) strcpy(zfile1, file1);
    482   1.1       cgd                 (void) strcpy(zfile2, file2);
    483   1.1       cgd                 if (lstat(file1, &st)) {
    484   1.3       cgd                         (void) strcat(zfile1, COMPRESS_POSTFIX);
    485   1.3       cgd                         (void) strcat(zfile2, COMPRESS_POSTFIX);
    486   1.1       cgd                         if (lstat(zfile1, &st)) continue;
    487   1.1       cgd                 }
    488   1.1       cgd                 if (noaction) {
    489   1.1       cgd                         printf("mv %s %s\n",zfile1,zfile2);
    490   1.1       cgd                         printf("chmod %o %s\n", perm, zfile2);
    491   1.1       cgd                         printf("chown %d.%d %s\n",
    492   1.1       cgd                                owner_uid, group_gid, zfile2);
    493   1.1       cgd                 } else {
    494   1.1       cgd                         (void) rename(zfile1, zfile2);
    495   1.1       cgd                         (void) chmod(zfile2, perm);
    496   1.1       cgd                         (void) chown(zfile2, owner_uid, group_gid);
    497   1.1       cgd                 }
    498   1.1       cgd         }
    499   1.1       cgd         if (!noaction && !(flags & CE_BINARY))
    500   1.1       cgd                 (void) log_trim(log);  /* Report the trimming to the old log */
    501   1.1       cgd 
    502  1.17  christos 	if (ngen == 0) {
    503  1.11   thorpej 		if (noaction)
    504  1.11   thorpej 			printf("rm %s\n",log);
    505  1.11   thorpej 		else
    506  1.11   thorpej 			(void) unlink(log);
    507  1.17  christos 	} else
    508  1.11   thorpej 		if (noaction)
    509  1.11   thorpej 			printf("mv %s to %s\n",log,file1);
    510  1.11   thorpej 		else
    511  1.11   thorpej 			(void) rename(log,file1);
    512  1.11   thorpej 
    513  1.11   thorpej         if (noaction)
    514   1.1       cgd                 printf("Start new log...");
    515   1.1       cgd         else {
    516   1.1       cgd                 fd = creat(log,perm);
    517   1.1       cgd                 if (fd < 0) {
    518   1.1       cgd                         perror("can't start new log");
    519   1.1       cgd                         exit(1);
    520   1.1       cgd                 }
    521   1.1       cgd                 if (fchown(fd, owner_uid, group_gid)) {
    522   1.1       cgd                         perror("can't chmod new log file");
    523   1.1       cgd                         exit(1);
    524   1.1       cgd                 }
    525   1.1       cgd                 (void) close(fd);
    526   1.1       cgd                 if (!(flags & CE_BINARY))
    527   1.1       cgd                         if (log_trim(log)) {    /* Add status message */
    528   1.1       cgd                                 perror("can't add status message to log");
    529   1.1       cgd                                 exit(1);
    530   1.1       cgd                         }
    531   1.1       cgd         }
    532   1.1       cgd         if (noaction)
    533   1.1       cgd                 printf("chmod %o %s...",perm,log);
    534   1.1       cgd         else
    535   1.1       cgd                 (void) chmod(log,perm);
    536  1.21        ad 
    537  1.21        ad 	if ((flags & CE_NOSIGNAL) == 0) {
    538  1.21        ad 		if (noaction)
    539  1.21        ad 			printf("kill -HUP %d\n",pid);
    540  1.21        ad 		else if (pid < MIN_PID || pid > MAX_PID) {
    541  1.21        ad 			fprintf(stderr,"%s: preposterous process number: %d\n",
    542  1.21        ad 			    progname, pid);
    543  1.21        ad 		} else if (kill(pid, signum)) {
    544  1.21        ad 			fprintf(stderr,"%s: ", progname);
    545  1.21        ad 			perror("warning - could not restart daemon");
    546  1.21        ad 		}
    547  1.21        ad 	}
    548  1.21        ad 
    549  1.21        ad         if ((flags & CE_COMPACT) != 0) {
    550   1.1       cgd                 if (noaction)
    551   1.1       cgd                         printf("Compress %s.0\n",log);
    552   1.1       cgd                 else
    553   1.1       cgd                         compress_log(log);
    554   1.1       cgd         }
    555   1.1       cgd }
    556   1.1       cgd 
    557   1.1       cgd /* Log the fact that the logs were turned over */
    558  1.13     lukem int
    559   1.1       cgd log_trim(log)
    560   1.1       cgd         char    *log;
    561   1.1       cgd {
    562   1.1       cgd         FILE    *f;
    563   1.1       cgd         if ((f = fopen(log,"a")) == NULL)
    564   1.1       cgd                 return(-1);
    565  1.17  christos         fprintf(f,"%s %s newsyslog[%ld]: logfile turned over\n",
    566  1.17  christos                 daytime, hostname, (u_long)getpid());
    567   1.1       cgd         if (fclose(f) == EOF) {
    568  1.18     soren                 perror("log_trim: fclose");
    569   1.1       cgd                 exit(1);
    570   1.1       cgd         }
    571   1.1       cgd         return(0);
    572   1.1       cgd }
    573   1.1       cgd 
    574  1.21        ad /* Fork off compress/gzip to compress the old log file */
    575  1.13     lukem void
    576   1.1       cgd compress_log(log)
    577   1.1       cgd         char    *log;
    578   1.1       cgd {
    579   1.1       cgd         int     pid;
    580   1.1       cgd         char    tmp[128];
    581   1.1       cgd 
    582   1.1       cgd         pid = fork();
    583   1.1       cgd         (void) sprintf(tmp,"%s.0",log);
    584   1.1       cgd         if (pid < 0) {
    585   1.1       cgd                 fprintf(stderr,"%s: ",progname);
    586   1.1       cgd                 perror("fork");
    587   1.1       cgd                 exit(1);
    588   1.1       cgd         } else if (!pid) {
    589   1.1       cgd                 (void) execl(COMPRESS,"compress","-f",tmp,0);
    590   1.1       cgd                 fprintf(stderr,"%s: ",progname);
    591   1.1       cgd                 perror(COMPRESS);
    592   1.1       cgd                 exit(1);
    593   1.1       cgd         }
    594   1.1       cgd }
    595   1.1       cgd 
    596   1.1       cgd /* Return size in kilobytes of a file */
    597  1.13     lukem int
    598  1.13     lukem sizefile(file)
    599   1.1       cgd         char    *file;
    600   1.1       cgd {
    601   1.1       cgd         struct stat sb;
    602   1.1       cgd 
    603   1.1       cgd         if (stat(file,&sb) < 0)
    604   1.1       cgd                 return(-1);
    605   1.1       cgd         return(kbytes(dbtob(sb.st_blocks)));
    606   1.1       cgd }
    607   1.1       cgd 
    608   1.1       cgd /* Return the age of old log file (file.0) */
    609  1.13     lukem int
    610  1.13     lukem age_old_log(file)
    611   1.1       cgd         char    *file;
    612   1.1       cgd {
    613   1.1       cgd         struct stat sb;
    614   1.7        pk         char tmp[MAXPATHLEN+3];
    615   1.1       cgd 
    616   1.1       cgd         (void) strcpy(tmp,file);
    617   1.1       cgd         if (stat(strcat(tmp,".0"),&sb) < 0)
    618   1.3       cgd             if (stat(strcat(tmp,COMPRESS_POSTFIX), &sb) < 0)
    619   1.1       cgd                 return(-1);
    620   1.1       cgd         return( (int) (timenow - sb.st_mtime + 1800) / 3600);
    621   1.1       cgd }
    622   1.1       cgd 
    623   1.1       cgd /* Skip Over Blanks */
    624   1.1       cgd char *sob(p)
    625  1.13     lukem         char   *p;
    626   1.1       cgd {
    627  1.17  christos         while (p && *p && isspace((unsigned char)*p))
    628   1.1       cgd                 p++;
    629   1.1       cgd         return(p);
    630   1.1       cgd }
    631   1.1       cgd 
    632   1.1       cgd /* Skip Over Non-Blanks */
    633  1.13     lukem char *
    634  1.13     lukem son(p)
    635  1.13     lukem         char   *p;
    636   1.1       cgd {
    637  1.17  christos         while (p && *p && !isspace((unsigned char)*p))
    638   1.1       cgd                 p++;
    639   1.1       cgd         return(p);
    640   1.1       cgd }
    641   1.1       cgd 
    642   1.1       cgd 
    643   1.1       cgd /* Check if string is actually a number */
    644   1.1       cgd 
    645  1.13     lukem int
    646   1.1       cgd isnumber(string)
    647  1.13     lukem 	char *string;
    648   1.1       cgd {
    649   1.1       cgd         while (*string != '\0') {
    650   1.1       cgd             if (*string < '0' || *string > '9') return(0);
    651   1.1       cgd             string++;
    652   1.1       cgd         }
    653   1.1       cgd         return(1);
    654  1.21        ad }
    655  1.21        ad 
    656  1.21        ad int
    657  1.21        ad getsig(sig)
    658  1.21        ad 	char *sig;
    659  1.21        ad {
    660  1.21        ad 	int n;
    661  1.21        ad 
    662  1.21        ad 	if (isnumber(sig)) {
    663  1.21        ad 		n = strtol(sig, &sig, 0);
    664  1.21        ad 		if ((unsigned)n >= NSIG)
    665  1.21        ad 			return (-1);
    666  1.21        ad 		return (n);
    667  1.21        ad 	}
    668  1.21        ad 
    669  1.21        ad 	if (!strncasecmp(sig, "sig", 3))
    670  1.21        ad 		sig += 3;
    671  1.21        ad 	for (n = 1; n < NSIG; n++) {
    672  1.21        ad 		if (!strcasecmp(sys_signame[n], sig))
    673  1.21        ad 			return (n);
    674  1.21        ad 	}
    675  1.21        ad 	return (-1);
    676   1.1       cgd }
    677