Home | History | Annotate | Line # | Download | only in newsyslog
newsyslog.c revision 1.1
      1  1.1  cgd /*
      2  1.1  cgd  * This file contains changes from the Open Software Foundation.
      3  1.1  cgd  * The RCS history log will appear at the end of this file.
      4  1.1  cgd  * @(#)newsyslog.c	$Revision: 1.1 $ $Date: 1993/05/21 14:44:02 $ $Locker:  $
      5  1.1  cgd  */
      6  1.1  cgd 
      7  1.1  cgd /*
      8  1.1  cgd 
      9  1.1  cgd Copyright 1991 by the Massachusetts Institute of Technology
     10  1.1  cgd 
     11  1.1  cgd All rights reserved.
     12  1.1  cgd 
     13  1.1  cgd Permission to use, copy, modify, and distribute this software and its
     14  1.1  cgd documentation for any purpose and without fee is hereby granted,
     15  1.1  cgd provided that the above copyright notice appear in all copies and that
     16  1.1  cgd both that copyright notice and this permission notice appear in
     17  1.1  cgd supporting documentation, and that the name of the Massachusetts
     18  1.1  cgd Institute of Technology (M.I.T.) not be used in advertising or publicity
     19  1.1  cgd pertaining to distribution of the software without specific, written
     20  1.1  cgd prior permission.
     21  1.1  cgd 
     22  1.1  cgd M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     23  1.1  cgd ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     24  1.1  cgd M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     25  1.1  cgd ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     26  1.1  cgd WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     27  1.1  cgd ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     28  1.1  cgd SOFTWARE.
     29  1.1  cgd 
     30  1.1  cgd */
     31  1.1  cgd 
     32  1.1  cgd /*
     33  1.1  cgd  *      newsyslog - roll over selected logs at the appropriate time,
     34  1.1  cgd  *              keeping the a specified number of backup files around.
     35  1.1  cgd  *
     36  1.1  cgd  *      $Source: /tank/opengrok/rsync2/NetBSD/src/usr.bin/newsyslog/newsyslog.c,v $
     37  1.1  cgd  *      $Author: cgd $
     38  1.1  cgd  */
     39  1.1  cgd 
     40  1.1  cgd #if !defined(lint) && !defined(_NOIDENT)
     41  1.1  cgd static char rcsid[] = "@(#)$RCSfile: newsyslog.c,v $ $Revision: 1.1 $ (OSF) $Date: 1993/05/21 14:44:02 $";
     42  1.1  cgd #endif
     43  1.1  cgd 
     44  1.1  cgd #ifndef CONF
     45  1.1  cgd #define CONF "/etc/athena/newsyslog.conf" /* Configuration file */
     46  1.1  cgd #endif
     47  1.1  cgd #ifndef PIDFILE
     48  1.1  cgd #define PIDFILE "/etc/syslog.pid"
     49  1.1  cgd #endif
     50  1.1  cgd #ifndef COMPRESS
     51  1.1  cgd #define COMPRESS "/usr/ucb/compress" /* File compression program */
     52  1.1  cgd #endif
     53  1.1  cgd 
     54  1.1  cgd #include <stdio.h>
     55  1.1  cgd #include <strings.h>
     56  1.1  cgd #include <ctype.h>
     57  1.1  cgd #include <signal.h>
     58  1.1  cgd #include <pwd.h>
     59  1.1  cgd #include <grp.h>
     60  1.1  cgd #include <sys/types.h>
     61  1.1  cgd #include <sys/time.h>
     62  1.1  cgd #include <sys/stat.h>
     63  1.1  cgd #include <sys/param.h>
     64  1.1  cgd #include <sys/wait.h>
     65  1.1  cgd 
     66  1.1  cgd #define kbytes(size)  (((size) + 1023) >> 10)
     67  1.1  cgd #ifdef _IBMR2
     68  1.1  cgd /* Calculates (db * DEV_BSIZE) */
     69  1.1  cgd #define dbtob(db)  ((unsigned)(db) << UBSHIFT)
     70  1.1  cgd #endif
     71  1.1  cgd 
     72  1.1  cgd #define CE_COMPACT 1            /* Compact the achived log files */
     73  1.1  cgd #define CE_BINARY 2             /* Logfile is in binary, don't add */
     74  1.1  cgd                                 /* status messages */
     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.1  cgd         int     flags;          /* Flags (CE_COMPACT & CE_BINARY)  */
     86  1.1  cgd         struct conf_entry       *next; /* Linked list pointer */
     87  1.1  cgd };
     88  1.1  cgd 
     89  1.1  cgd extern int      optind;
     90  1.1  cgd extern char     *optarg;
     91  1.1  cgd extern char *malloc();
     92  1.1  cgd extern uid_t getuid(),geteuid();
     93  1.1  cgd extern time_t time();
     94  1.1  cgd 
     95  1.1  cgd char    *progname;              /* contains argv[0] */
     96  1.1  cgd int     verbose = 0;            /* Print out what's going on */
     97  1.1  cgd int     needroot = 1;           /* Root privs are necessary */
     98  1.1  cgd int     noaction = 0;           /* Don't do anything, just show it */
     99  1.1  cgd char    *conf = CONF;           /* Configuration file to use */
    100  1.1  cgd time_t  timenow;
    101  1.1  cgd int     syslog_pid;             /* read in from /etc/syslog.pid */
    102  1.1  cgd char    hostname[64];           /* hostname */
    103  1.1  cgd char    *daytime;               /* timenow in human readable form */
    104  1.1  cgd 
    105  1.1  cgd 
    106  1.1  cgd struct conf_entry *parse_file();
    107  1.1  cgd char *sob(), *son(), *strdup(), *missing_field();
    108  1.1  cgd 
    109  1.1  cgd main(argc,argv)
    110  1.1  cgd         int argc;
    111  1.1  cgd         char **argv;
    112  1.1  cgd {
    113  1.1  cgd         struct conf_entry *p, *q;
    114  1.1  cgd 
    115  1.1  cgd         PRS(argc,argv);
    116  1.1  cgd         if (needroot && getuid() && geteuid()) {
    117  1.1  cgd                 fprintf(stderr,"%s: must have root privs\n",progname);
    118  1.1  cgd                 exit(1);
    119  1.1  cgd         }
    120  1.1  cgd         p = q = parse_file();
    121  1.1  cgd         while (p) {
    122  1.1  cgd                 do_entry(p);
    123  1.1  cgd                 p=p->next;
    124  1.1  cgd                 free((char *) q);
    125  1.1  cgd                 q=p;
    126  1.1  cgd         }
    127  1.1  cgd         exit(0);
    128  1.1  cgd }
    129  1.1  cgd 
    130  1.1  cgd do_entry(ent)
    131  1.1  cgd         struct conf_entry       *ent;
    132  1.1  cgd 
    133  1.1  cgd {
    134  1.1  cgd         int     size, modtime;
    135  1.1  cgd 
    136  1.1  cgd         if (verbose) {
    137  1.1  cgd                 if (ent->flags & CE_COMPACT)
    138  1.1  cgd                         printf("%s <%dZ>: ",ent->log,ent->numlogs);
    139  1.1  cgd                 else
    140  1.1  cgd                         printf("%s <%d>: ",ent->log,ent->numlogs);
    141  1.1  cgd         }
    142  1.1  cgd         size = sizefile(ent->log);
    143  1.1  cgd         modtime = age_old_log(ent->log);
    144  1.1  cgd         if (size < 0) {
    145  1.1  cgd                 if (verbose)
    146  1.1  cgd                         printf("does not exist.\n");
    147  1.1  cgd         } else {
    148  1.1  cgd                 if (verbose && (ent->size > 0))
    149  1.1  cgd                         printf("size (Kb): %d [%d] ", size, ent->size);
    150  1.1  cgd                 if (verbose && (ent->hours > 0))
    151  1.1  cgd                         printf(" age (hr): %d [%d] ", modtime, ent->hours);
    152  1.1  cgd                 if (((ent->size > 0) && (size >= ent->size)) ||
    153  1.1  cgd                     ((ent->hours > 0) && ((modtime >= ent->hours)
    154  1.1  cgd                                         || (modtime < 0)))) {
    155  1.1  cgd                         if (verbose)
    156  1.1  cgd                                 printf("--> trimming log....\n");
    157  1.1  cgd                         if (noaction && !verbose) {
    158  1.1  cgd                                 if (ent->flags & CE_COMPACT)
    159  1.1  cgd                                         printf("%s <%dZ>: trimming",
    160  1.1  cgd                                                ent->log,ent->numlogs);
    161  1.1  cgd                                 else
    162  1.1  cgd                                         printf("%s <%d>: trimming",
    163  1.1  cgd                                                ent->log,ent->numlogs);
    164  1.1  cgd                         }
    165  1.1  cgd                         dotrim(ent->log, ent->numlogs, ent->flags,
    166  1.1  cgd                                ent->permissions, ent->uid, ent->gid);
    167  1.1  cgd                 } else {
    168  1.1  cgd                         if (verbose)
    169  1.1  cgd                                 printf("--> skipping\n");
    170  1.1  cgd                 }
    171  1.1  cgd         }
    172  1.1  cgd }
    173  1.1  cgd 
    174  1.1  cgd PRS(argc,argv)
    175  1.1  cgd         int argc;
    176  1.1  cgd         char **argv;
    177  1.1  cgd {
    178  1.1  cgd         int     c;
    179  1.1  cgd         FILE    *f;
    180  1.1  cgd         char    line[BUFSIZ];
    181  1.1  cgd 
    182  1.1  cgd         progname = argv[0];
    183  1.1  cgd         timenow = time((time_t *) 0);
    184  1.1  cgd         daytime = ctime(&timenow);
    185  1.1  cgd         daytime[strlen(daytime)-1] = '\0';
    186  1.1  cgd 
    187  1.1  cgd         /* Let's find the pid of syslogd */
    188  1.1  cgd         syslog_pid = 0;
    189  1.1  cgd         f = fopen(PIDFILE,"r");
    190  1.1  cgd         if (f && fgets(line,BUFSIZ,f))
    191  1.1  cgd                 syslog_pid = atoi(line);
    192  1.1  cgd 
    193  1.1  cgd         /* Let's get our hostname */
    194  1.1  cgd         if (gethostname(hostname, 64)) {
    195  1.1  cgd                 perror("gethostname");
    196  1.1  cgd                 (void) strcpy(hostname,"Mystery Host");
    197  1.1  cgd         }
    198  1.1  cgd 
    199  1.1  cgd         optind = 1;             /* Start options parsing */
    200  1.1  cgd         while ((c=getopt(argc,argv,"nrvf:t:")) != EOF)
    201  1.1  cgd                 switch (c) {
    202  1.1  cgd                 case 'n':
    203  1.1  cgd                         noaction++; /* This implies needroot as off */
    204  1.1  cgd                         /* fall through */
    205  1.1  cgd                 case 'r':
    206  1.1  cgd                         needroot = 0;
    207  1.1  cgd                         break;
    208  1.1  cgd                 case 'v':
    209  1.1  cgd                         verbose++;
    210  1.1  cgd                         break;
    211  1.1  cgd                 case 'f':
    212  1.1  cgd                         conf = optarg;
    213  1.1  cgd                         break;
    214  1.1  cgd                 default:
    215  1.1  cgd                         usage();
    216  1.1  cgd                 }
    217  1.1  cgd         }
    218  1.1  cgd 
    219  1.1  cgd usage()
    220  1.1  cgd {
    221  1.1  cgd         fprintf(stderr,
    222  1.1  cgd                 "Usage: %s <-nrv> <-f config-file>\n");
    223  1.1  cgd         exit(1);
    224  1.1  cgd }
    225  1.1  cgd 
    226  1.1  cgd /* Parse a configuration file and return a linked list of all the logs
    227  1.1  cgd  * to process
    228  1.1  cgd  */
    229  1.1  cgd struct conf_entry *parse_file()
    230  1.1  cgd {
    231  1.1  cgd         FILE    *f;
    232  1.1  cgd         char    line[BUFSIZ], *parse, *q;
    233  1.1  cgd         char    *errline, *group;
    234  1.1  cgd         struct conf_entry *first = NULL;
    235  1.1  cgd         struct conf_entry *working;
    236  1.1  cgd         struct passwd *pass;
    237  1.1  cgd         struct group *grp;
    238  1.1  cgd 
    239  1.1  cgd         if (strcmp(conf,"-"))
    240  1.1  cgd                 f = fopen(conf,"r");
    241  1.1  cgd         else
    242  1.1  cgd                 f = stdin;
    243  1.1  cgd         if (!f) {
    244  1.1  cgd                 (void) fprintf(stderr,"%s: ",progname);
    245  1.1  cgd                 perror(conf);
    246  1.1  cgd                 exit(1);
    247  1.1  cgd         }
    248  1.1  cgd         while (fgets(line,BUFSIZ,f)) {
    249  1.1  cgd                 if ((line[0]== '\n') || (line[0] == '#'))
    250  1.1  cgd                         continue;
    251  1.1  cgd                 errline = strdup(line);
    252  1.1  cgd                 if (!first) {
    253  1.1  cgd                         working = (struct conf_entry *) malloc(sizeof(struct conf_entry));
    254  1.1  cgd                         first = working;
    255  1.1  cgd                 } else {
    256  1.1  cgd                         working->next = (struct conf_entry *) malloc(sizeof(struct conf_entry));
    257  1.1  cgd                         working = working->next;
    258  1.1  cgd                 }
    259  1.1  cgd 
    260  1.1  cgd                 q = parse = missing_field(sob(line),errline);
    261  1.1  cgd                 *(parse = son(line)) = '\0';
    262  1.1  cgd                 working->log = strdup(q);
    263  1.1  cgd 
    264  1.1  cgd                 q = parse = missing_field(sob(++parse),errline);
    265  1.1  cgd                 *(parse = son(parse)) = '\0';
    266  1.1  cgd                 if ((group = index(q, '.')) != NULL) {
    267  1.1  cgd                     *group++ = '\0';
    268  1.1  cgd                     if (*q) {
    269  1.1  cgd                         if (!(isnumber(q))) {
    270  1.1  cgd                             if ((pass = getpwnam(q)) == NULL) {
    271  1.1  cgd                                 fprintf(stderr,
    272  1.1  cgd                                     "Error in config file; unknown user:\n");
    273  1.1  cgd                                 fputs(errline,stderr);
    274  1.1  cgd                                 exit(1);
    275  1.1  cgd                             }
    276  1.1  cgd                             working->uid = pass->pw_uid;
    277  1.1  cgd                         } else
    278  1.1  cgd                             working->uid = atoi(q);
    279  1.1  cgd                     } else
    280  1.1  cgd                         working->uid = NONE;
    281  1.1  cgd 
    282  1.1  cgd                     q = group;
    283  1.1  cgd                     if (*q) {
    284  1.1  cgd                         if (!(isnumber(q))) {
    285  1.1  cgd                             if ((grp = getgrnam(q)) == NULL) {
    286  1.1  cgd                                 fprintf(stderr,
    287  1.1  cgd                                     "Error in config file; unknown group:\n");
    288  1.1  cgd                                 fputs(errline,stderr);
    289  1.1  cgd                                 exit(1);
    290  1.1  cgd                             }
    291  1.1  cgd                             working->gid = grp->gr_gid;
    292  1.1  cgd                         } else
    293  1.1  cgd                             working->gid = atoi(q);
    294  1.1  cgd                     } else
    295  1.1  cgd                         working->gid = NONE;
    296  1.1  cgd 
    297  1.1  cgd                     q = parse = missing_field(sob(++parse),errline);
    298  1.1  cgd                     *(parse = son(parse)) = '\0';
    299  1.1  cgd                 }
    300  1.1  cgd                 else
    301  1.1  cgd                     working->uid = working->gid = NONE;
    302  1.1  cgd 
    303  1.1  cgd                 if (!sscanf(q,"%o",&working->permissions)) {
    304  1.1  cgd                         fprintf(stderr,
    305  1.1  cgd                                 "Error in config file; bad permissions:\n");
    306  1.1  cgd                         fputs(errline,stderr);
    307  1.1  cgd                         exit(1);
    308  1.1  cgd                 }
    309  1.1  cgd 
    310  1.1  cgd                 q = parse = missing_field(sob(++parse),errline);
    311  1.1  cgd                 *(parse = son(parse)) = '\0';
    312  1.1  cgd                 if (!sscanf(q,"%d",&working->numlogs)) {
    313  1.1  cgd                         fprintf(stderr,
    314  1.1  cgd                                 "Error in config file; bad number:\n");
    315  1.1  cgd                         fputs(errline,stderr);
    316  1.1  cgd                         exit(1);
    317  1.1  cgd                 }
    318  1.1  cgd 
    319  1.1  cgd                 q = parse = missing_field(sob(++parse),errline);
    320  1.1  cgd                 *(parse = son(parse)) = '\0';
    321  1.1  cgd                 if (isdigit(*q))
    322  1.1  cgd                         working->size = atoi(q);
    323  1.1  cgd                 else
    324  1.1  cgd                         working->size = -1;
    325  1.1  cgd 
    326  1.1  cgd                 q = parse = missing_field(sob(++parse),errline);
    327  1.1  cgd                 *(parse = son(parse)) = '\0';
    328  1.1  cgd                 if (isdigit(*q))
    329  1.1  cgd                         working->hours = atoi(q);
    330  1.1  cgd                 else
    331  1.1  cgd                         working->hours = -1;
    332  1.1  cgd 
    333  1.1  cgd                 q = parse = sob(++parse); /* Optional field */
    334  1.1  cgd                 *(parse = son(parse)) = '\0';
    335  1.1  cgd                 working->flags = 0;
    336  1.1  cgd                 while (q && *q && !isspace(*q)) {
    337  1.1  cgd                         if ((*q == 'Z') || (*q == 'z'))
    338  1.1  cgd                                 working->flags |= CE_COMPACT;
    339  1.1  cgd                         else if ((*q == 'B') || (*q == 'b'))
    340  1.1  cgd                                 working->flags |= CE_BINARY;
    341  1.1  cgd                         else {
    342  1.1  cgd                                 fprintf(stderr,
    343  1.1  cgd                                         "Illegal flag in config file -- %c\n",
    344  1.1  cgd                                         *q);
    345  1.1  cgd                                 exit(1);
    346  1.1  cgd                         }
    347  1.1  cgd                         q++;
    348  1.1  cgd                 }
    349  1.1  cgd 
    350  1.1  cgd                 free(errline);
    351  1.1  cgd         }
    352  1.1  cgd         if (working)
    353  1.1  cgd                 working->next = (struct conf_entry *) NULL;
    354  1.1  cgd         (void) fclose(f);
    355  1.1  cgd         return(first);
    356  1.1  cgd }
    357  1.1  cgd 
    358  1.1  cgd char *missing_field(p,errline)
    359  1.1  cgd         char    *p,*errline;
    360  1.1  cgd {
    361  1.1  cgd         if (!p || !*p) {
    362  1.1  cgd                 fprintf(stderr,"Missing field in config file:\n");
    363  1.1  cgd                 fputs(errline,stderr);
    364  1.1  cgd                 exit(1);
    365  1.1  cgd         }
    366  1.1  cgd         return(p);
    367  1.1  cgd }
    368  1.1  cgd 
    369  1.1  cgd dotrim(log,numdays,flags,perm,owner_uid,group_gid)
    370  1.1  cgd         char    *log;
    371  1.1  cgd         int     numdays;
    372  1.1  cgd         int     flags;
    373  1.1  cgd         int     perm;
    374  1.1  cgd         int     owner_uid;
    375  1.1  cgd         int     group_gid;
    376  1.1  cgd {
    377  1.1  cgd         char    file1[128], file2[128];
    378  1.1  cgd         char    zfile1[128], zfile2[128];
    379  1.1  cgd         int     fd;
    380  1.1  cgd         struct  stat st;
    381  1.1  cgd 
    382  1.1  cgd #ifdef _IBMR2
    383  1.1  cgd /* AIX 3.1 has a broken fchown- if the owner_uid is -1, it will actually */
    384  1.1  cgd /* change it to be owned by uid -1, instead of leaving it as is, as it is */
    385  1.1  cgd /* supposed to. */
    386  1.1  cgd                 if (owner_uid == -1)
    387  1.1  cgd                   owner_uid = geteuid();
    388  1.1  cgd #endif
    389  1.1  cgd 
    390  1.1  cgd         /* Remove oldest log */
    391  1.1  cgd         (void) sprintf(file1,"%s.%d",log,numdays);
    392  1.1  cgd         (void) strcpy(zfile1, file1);
    393  1.1  cgd         (void) strcat(zfile1, ".Z");
    394  1.1  cgd 
    395  1.1  cgd         if (noaction) {
    396  1.1  cgd                 printf("rm -f %s\n", file1);
    397  1.1  cgd                 printf("rm -f %s\n", zfile1);
    398  1.1  cgd         } else {
    399  1.1  cgd                 (void) unlink(file1);
    400  1.1  cgd                 (void) unlink(zfile1);
    401  1.1  cgd         }
    402  1.1  cgd 
    403  1.1  cgd         /* Move down log files */
    404  1.1  cgd         while (numdays--) {
    405  1.1  cgd                 (void) strcpy(file2,file1);
    406  1.1  cgd                 (void) sprintf(file1,"%s.%d",log,numdays);
    407  1.1  cgd                 (void) strcpy(zfile1, file1);
    408  1.1  cgd                 (void) strcpy(zfile2, file2);
    409  1.1  cgd                 if (lstat(file1, &st)) {
    410  1.1  cgd                         (void) strcat(zfile1, ".Z");
    411  1.1  cgd                         (void) strcat(zfile2, ".Z");
    412  1.1  cgd                         if (lstat(zfile1, &st)) continue;
    413  1.1  cgd                 }
    414  1.1  cgd                 if (noaction) {
    415  1.1  cgd                         printf("mv %s %s\n",zfile1,zfile2);
    416  1.1  cgd                         printf("chmod %o %s\n", perm, zfile2);
    417  1.1  cgd                         printf("chown %d.%d %s\n",
    418  1.1  cgd                                owner_uid, group_gid, zfile2);
    419  1.1  cgd                 } else {
    420  1.1  cgd                         (void) rename(zfile1, zfile2);
    421  1.1  cgd                         (void) chmod(zfile2, perm);
    422  1.1  cgd                         (void) chown(zfile2, owner_uid, group_gid);
    423  1.1  cgd                 }
    424  1.1  cgd         }
    425  1.1  cgd         if (!noaction && !(flags & CE_BINARY))
    426  1.1  cgd                 (void) log_trim(log);  /* Report the trimming to the old log */
    427  1.1  cgd 
    428  1.1  cgd         if (noaction)
    429  1.1  cgd                 printf("mv %s to %s\n",log,file1);
    430  1.1  cgd         else
    431  1.1  cgd                 (void) rename(log,file1);
    432  1.1  cgd         if (noaction)
    433  1.1  cgd                 printf("Start new log...");
    434  1.1  cgd         else {
    435  1.1  cgd                 fd = creat(log,perm);
    436  1.1  cgd                 if (fd < 0) {
    437  1.1  cgd                         perror("can't start new log");
    438  1.1  cgd                         exit(1);
    439  1.1  cgd                 }
    440  1.1  cgd                 if (fchown(fd, owner_uid, group_gid)) {
    441  1.1  cgd                         perror("can't chmod new log file");
    442  1.1  cgd                         exit(1);
    443  1.1  cgd                 }
    444  1.1  cgd                 (void) close(fd);
    445  1.1  cgd                 if (!(flags & CE_BINARY))
    446  1.1  cgd                         if (log_trim(log)) {    /* Add status message */
    447  1.1  cgd                                 perror("can't add status message to log");
    448  1.1  cgd                                 exit(1);
    449  1.1  cgd                         }
    450  1.1  cgd         }
    451  1.1  cgd         if (noaction)
    452  1.1  cgd                 printf("chmod %o %s...",perm,log);
    453  1.1  cgd         else
    454  1.1  cgd                 (void) chmod(log,perm);
    455  1.1  cgd         if (noaction)
    456  1.1  cgd                 printf("kill -HUP %d (syslogd)\n",syslog_pid);
    457  1.1  cgd         else
    458  1.1  cgd         if (kill(syslog_pid,SIGHUP)) {
    459  1.1  cgd                         fprintf(stderr,"%s: ",progname);
    460  1.1  cgd                         perror("warning - could not restart syslogd");
    461  1.1  cgd                 }
    462  1.1  cgd         if (flags & CE_COMPACT) {
    463  1.1  cgd                 if (noaction)
    464  1.1  cgd                         printf("Compress %s.0\n",log);
    465  1.1  cgd                 else
    466  1.1  cgd                         compress_log(log);
    467  1.1  cgd         }
    468  1.1  cgd }
    469  1.1  cgd 
    470  1.1  cgd /* Log the fact that the logs were turned over */
    471  1.1  cgd log_trim(log)
    472  1.1  cgd         char    *log;
    473  1.1  cgd {
    474  1.1  cgd         FILE    *f;
    475  1.1  cgd         if ((f = fopen(log,"a")) == NULL)
    476  1.1  cgd                 return(-1);
    477  1.1  cgd         fprintf(f,"%s %s newsyslog[%d]: logfile turned over\n",
    478  1.1  cgd                 daytime, hostname, getpid());
    479  1.1  cgd         if (fclose(f) == EOF) {
    480  1.1  cgd                 perror("log_trim: fclose:");
    481  1.1  cgd                 exit(1);
    482  1.1  cgd         }
    483  1.1  cgd         return(0);
    484  1.1  cgd }
    485  1.1  cgd 
    486  1.1  cgd /* Fork of /usr/ucb/compress to compress the old log file */
    487  1.1  cgd compress_log(log)
    488  1.1  cgd         char    *log;
    489  1.1  cgd {
    490  1.1  cgd         int     pid;
    491  1.1  cgd         char    tmp[128];
    492  1.1  cgd 
    493  1.1  cgd         pid = fork();
    494  1.1  cgd         (void) sprintf(tmp,"%s.0",log);
    495  1.1  cgd         if (pid < 0) {
    496  1.1  cgd                 fprintf(stderr,"%s: ",progname);
    497  1.1  cgd                 perror("fork");
    498  1.1  cgd                 exit(1);
    499  1.1  cgd         } else if (!pid) {
    500  1.1  cgd                 (void) execl(COMPRESS,"compress","-f",tmp,0);
    501  1.1  cgd                 fprintf(stderr,"%s: ",progname);
    502  1.1  cgd                 perror(COMPRESS);
    503  1.1  cgd                 exit(1);
    504  1.1  cgd         }
    505  1.1  cgd }
    506  1.1  cgd 
    507  1.1  cgd /* Return size in kilobytes of a file */
    508  1.1  cgd int sizefile(file)
    509  1.1  cgd         char    *file;
    510  1.1  cgd {
    511  1.1  cgd         struct stat sb;
    512  1.1  cgd 
    513  1.1  cgd         if (stat(file,&sb) < 0)
    514  1.1  cgd                 return(-1);
    515  1.1  cgd         return(kbytes(dbtob(sb.st_blocks)));
    516  1.1  cgd }
    517  1.1  cgd 
    518  1.1  cgd /* Return the age of old log file (file.0) */
    519  1.1  cgd int age_old_log(file)
    520  1.1  cgd         char    *file;
    521  1.1  cgd {
    522  1.1  cgd         struct stat sb;
    523  1.1  cgd         char tmp[80];
    524  1.1  cgd 
    525  1.1  cgd         (void) strcpy(tmp,file);
    526  1.1  cgd         if (stat(strcat(tmp,".0"),&sb) < 0)
    527  1.1  cgd             if (stat(strcat(tmp,".Z"), &sb) < 0)
    528  1.1  cgd                 return(-1);
    529  1.1  cgd         return( (int) (timenow - sb.st_mtime + 1800) / 3600);
    530  1.1  cgd }
    531  1.1  cgd 
    532  1.1  cgd 
    533  1.1  cgd #ifndef OSF
    534  1.1  cgd /* Duplicate a string using malloc */
    535  1.1  cgd 
    536  1.1  cgd char *strdup(strp)
    537  1.1  cgd register char   *strp;
    538  1.1  cgd {
    539  1.1  cgd         register char *cp;
    540  1.1  cgd 
    541  1.1  cgd         if ((cp = malloc((unsigned) strlen(strp) + 1)) == NULL)
    542  1.1  cgd                 abort();
    543  1.1  cgd         return(strcpy (cp, strp));
    544  1.1  cgd }
    545  1.1  cgd #endif
    546  1.1  cgd 
    547  1.1  cgd /* Skip Over Blanks */
    548  1.1  cgd char *sob(p)
    549  1.1  cgd         register char   *p;
    550  1.1  cgd {
    551  1.1  cgd         while (p && *p && isspace(*p))
    552  1.1  cgd                 p++;
    553  1.1  cgd         return(p);
    554  1.1  cgd }
    555  1.1  cgd 
    556  1.1  cgd /* Skip Over Non-Blanks */
    557  1.1  cgd char *son(p)
    558  1.1  cgd         register char   *p;
    559  1.1  cgd {
    560  1.1  cgd         while (p && *p && !isspace(*p))
    561  1.1  cgd                 p++;
    562  1.1  cgd         return(p);
    563  1.1  cgd }
    564  1.1  cgd 
    565  1.1  cgd 
    566  1.1  cgd /* Check if string is actually a number */
    567  1.1  cgd 
    568  1.1  cgd isnumber(string)
    569  1.1  cgd char *string;
    570  1.1  cgd {
    571  1.1  cgd         while (*string != '\0') {
    572  1.1  cgd             if (*string < '0' || *string > '9') return(0);
    573  1.1  cgd             string++;
    574  1.1  cgd         }
    575  1.1  cgd         return(1);
    576  1.1  cgd }
    577  1.1  cgd 
    578  1.1  cgd #if !defined(__SABER__) && !defined(lint) && !defined(NO_WHAT_STRINGS)
    579  1.1  cgd static char *what_string = "@(#)newsyslog.c\t$Revision: 1.1 $ $Date: 1993/05/21 14:44:02 $ $Locker:  $";
    580  1.1  cgd #endif
    581  1.1  cgd 
    582  1.1  cgd /*
    583  1.1  cgd  * HISTORY
    584  1.1  cgd  * $Log: newsyslog.c,v $
    585  1.1  cgd  * Revision 1.1  1993/05/21 14:44:02  cgd
    586  1.1  cgd  * initial import of this log-rotation program to NetBSD
    587  1.1  cgd  *
    588  1.1  cgd  * Revision 3.0.2.2  1993/02/06  04:14:51  brezak
    589  1.1  cgd  * 	Fix up rcsid.
    590  1.1  cgd  * 	[1993/02/06  04:14:03  brezak]
    591  1.1  cgd  *
    592  1.1  cgd  * Revision 3.0  1993/01/01  07:39:17  ede
    593  1.1  cgd  * 	Initial revision for OSF/1 R1.3
    594  1.1  cgd  *
    595  1.1  cgd  * Revision 1.2  1991/08/16  09:50:26  devrcs
    596  1.1  cgd  * 	From John Brezak, brezak (at) apollo.com, originally from Project Athena
    597  1.1  cgd  * 	[91/07/24  09:33:18  meissner]
    598            *
    599            * $EndLog$
    600            */
    601