newsyslog.c revision 18075
113244Sgraichen/*
213244Sgraichen * This file contains changes from the Open Software Foundation.
313244Sgraichen */
413244Sgraichen
513244Sgraichen/*
613244Sgraichen
713244SgraichenCopyright 1988, 1989 by the Massachusetts Institute of Technology
813244Sgraichen
913244SgraichenPermission to use, copy, modify, and distribute this software
1013244Sgraichenand its documentation for any purpose and without fee is
1113244Sgraichenhereby granted, provided that the above copyright notice
1213244Sgraichenappear in all copies and that both that copyright notice and
1313244Sgraichenthis permission notice appear in supporting documentation,
1413244Sgraichenand that the names of M.I.T. and the M.I.T. S.I.P.B. not be
1513244Sgraichenused in advertising or publicity pertaining to distribution
1613244Sgraichenof the software without specific, written prior permission.
1713244SgraichenM.I.T. and the M.I.T. S.I.P.B. make no representations about
1813244Sgraichenthe suitability of this software for any purpose.  It is
1913244Sgraichenprovided "as is" without express or implied warranty.
2013244Sgraichen
2113244Sgraichen*/
2213244Sgraichen
2313244Sgraichen/*
2413244Sgraichen *      newsyslog - roll over selected logs at the appropriate time,
2513244Sgraichen *              keeping the a specified number of backup files around.
2613244Sgraichen *
2718075Sjkh *      $Source: /home/ncvs/src/usr.sbin/newsyslog/newsyslog.c,v $
2816240Salex *      $Author: alex $
2913244Sgraichen */
3013244Sgraichen
3113244Sgraichen#ifndef lint
3218075Sjkhstatic char rcsid[] = "$Id: newsyslog.c,v 1.5 1996/06/08 23:32:10 alex Exp $";
3313244Sgraichen#endif /* not lint */
3413244Sgraichen
3513244Sgraichen#ifndef CONF
3613244Sgraichen#define CONF "/etc/athena/newsyslog.conf" /* Configuration file */
3713244Sgraichen#endif
3813244Sgraichen#ifndef PIDFILE
3913244Sgraichen#define PIDFILE "/etc/syslog.pid"
4013244Sgraichen#endif
4113460Sgraichen#ifndef COMPRESS_PATH
4213460Sgraichen#define COMPRESS_PATH "/usr/ucb/compress" /* File compression program */
4313244Sgraichen#endif
4413460Sgraichen#ifndef COMPRESS_PROG
4513460Sgraichen#define COMPRESS_PROG "compress"
4613460Sgraichen#endif
4713244Sgraichen#ifndef COMPRESS_POSTFIX
4813244Sgraichen#define COMPRESS_POSTFIX ".Z"
4913244Sgraichen#endif
5013244Sgraichen
5113244Sgraichen#include <stdio.h>
5213244Sgraichen#include <stdlib.h>
5313244Sgraichen#include <string.h>
5413244Sgraichen#include <ctype.h>
5513244Sgraichen#include <signal.h>
5613244Sgraichen#include <pwd.h>
5713244Sgraichen#include <grp.h>
5816240Salex#include <fcntl.h>
5916240Salex#include <unistd.h>
6016240Salex#include <err.h>
6113244Sgraichen#include <sys/types.h>
6213244Sgraichen#include <sys/time.h>
6313244Sgraichen#include <sys/stat.h>
6413244Sgraichen#include <sys/param.h>
6513244Sgraichen#include <sys/wait.h>
6613244Sgraichen
6713244Sgraichen#define kbytes(size)  (((size) + 1023) >> 10)
6813244Sgraichen#ifdef _IBMR2
6913244Sgraichen/* Calculates (db * DEV_BSIZE) */
7013244Sgraichen#define dbtob(db)  ((unsigned)(db) << UBSHIFT)
7113244Sgraichen#endif
7213244Sgraichen
7313244Sgraichen#define CE_COMPACT 1            /* Compact the achived log files */
7413460Sgraichen#define CE_BINARY  2            /* Logfile is in binary, don't add */
7513244Sgraichen                                /* status messages */
7613244Sgraichen#define NONE -1
7713244Sgraichen
7813244Sgraichenstruct conf_entry {
7913244Sgraichen        char    *log;           /* Name of the log */
8013244Sgraichen        int     uid;            /* Owner of log */
8113244Sgraichen        int     gid;            /* Group of log */
8213244Sgraichen        int     numlogs;        /* Number of logs to keep */
8313244Sgraichen        int     size;           /* Size cutoff to trigger trimming the log */
8413244Sgraichen        int     hours;          /* Hours between log trimming */
8513244Sgraichen        int     permissions;    /* File permissions on the log */
8613244Sgraichen        int     flags;          /* Flags (CE_COMPACT & CE_BINARY)  */
8713244Sgraichen        struct conf_entry       *next; /* Linked list pointer */
8813244Sgraichen};
8913244Sgraichen
9013244Sgraichenchar    *progname;              /* contains argv[0] */
9113244Sgraichenint     verbose = 0;            /* Print out what's going on */
9213244Sgraichenint     needroot = 1;           /* Root privs are necessary */
9313244Sgraichenint     noaction = 0;           /* Don't do anything, just show it */
9413244Sgraichenchar    *conf = CONF;           /* Configuration file to use */
9513244Sgraichentime_t  timenow;
9613244Sgraichenint     syslog_pid;             /* read in from /etc/syslog.pid */
9713244Sgraichen#define MIN_PID		3
9813460Sgraichen#define MAX_PID		30000   /* was 65534, see /usr/include/sys/proc.h */
9913460Sgraichenchar    hostname[MAXHOSTNAMELEN+1]; /* hostname */
10013244Sgraichenchar    *daytime;               /* timenow in human readable form */
10113244Sgraichen
10216240Salex#ifndef OSF
10316240Salexchar *strdup(char *strp);
10416240Salex#endif
10513244Sgraichen
10616240Salexstatic struct conf_entry *parse_file();
10716240Salexstatic char *sob(char *p);
10816240Salexstatic char *son(char *p);
10916240Salexstatic char *missing_field(char *p,char *errline);
11016240Salexstatic void do_entry(struct conf_entry *ent);
11116240Salexstatic void PRS(int argc,char **argv);
11216240Salexstatic void usage();
11316240Salexstatic void dotrim(char *log,int numdays,int falgs,int perm, int owner_uid,int group_gid);
11416240Salexstatic int log_trim(char *log);
11516240Salexstatic void compress_log(char *log);
11616240Salexstatic int sizefile(char *file);
11716240Salexstatic int age_old_log(char *file);
11813244Sgraichen
11916240Salexint main(argc,argv)
12013244Sgraichen        int argc;
12113244Sgraichen        char **argv;
12213244Sgraichen{
12313244Sgraichen        struct conf_entry *p, *q;
12413244Sgraichen
12513244Sgraichen        PRS(argc,argv);
12613244Sgraichen        if (needroot && getuid() && geteuid()) {
12713244Sgraichen                fprintf(stderr,"%s: must have root privs\n",progname);
12816240Salex                return(1);
12913244Sgraichen        }
13013244Sgraichen        p = q = parse_file();
13113244Sgraichen        while (p) {
13213244Sgraichen                do_entry(p);
13313244Sgraichen                p=p->next;
13413244Sgraichen                free((char *) q);
13513244Sgraichen                q=p;
13613244Sgraichen        }
13716240Salex        return(0);
13813244Sgraichen}
13913244Sgraichen
14016240Salexstatic void do_entry(ent)
14113244Sgraichen        struct conf_entry       *ent;
14213244Sgraichen
14313244Sgraichen{
14413244Sgraichen        int     size, modtime;
14513244Sgraichen
14613244Sgraichen        if (verbose) {
14713244Sgraichen                if (ent->flags & CE_COMPACT)
14813244Sgraichen                        printf("%s <%dZ>: ",ent->log,ent->numlogs);
14913244Sgraichen                else
15013244Sgraichen                        printf("%s <%d>: ",ent->log,ent->numlogs);
15113244Sgraichen        }
15213244Sgraichen        size = sizefile(ent->log);
15313244Sgraichen        modtime = age_old_log(ent->log);
15413244Sgraichen        if (size < 0) {
15513244Sgraichen                if (verbose)
15613244Sgraichen                        printf("does not exist.\n");
15713244Sgraichen        } else {
15813244Sgraichen                if (verbose && (ent->size > 0))
15913244Sgraichen                        printf("size (Kb): %d [%d] ", size, ent->size);
16013244Sgraichen                if (verbose && (ent->hours > 0))
16113244Sgraichen                        printf(" age (hr): %d [%d] ", modtime, ent->hours);
16213244Sgraichen                if (((ent->size > 0) && (size >= ent->size)) ||
16313244Sgraichen                    ((ent->hours > 0) && ((modtime >= ent->hours)
16413244Sgraichen                                        || (modtime < 0)))) {
16513244Sgraichen                        if (verbose)
16613244Sgraichen                                printf("--> trimming log....\n");
16713244Sgraichen                        if (noaction && !verbose) {
16813244Sgraichen                                if (ent->flags & CE_COMPACT)
16913244Sgraichen                                        printf("%s <%dZ>: trimming",
17013244Sgraichen                                               ent->log,ent->numlogs);
17113244Sgraichen                                else
17213244Sgraichen                                        printf("%s <%d>: trimming",
17313244Sgraichen                                               ent->log,ent->numlogs);
17413244Sgraichen                        }
17513244Sgraichen                        dotrim(ent->log, ent->numlogs, ent->flags,
17613244Sgraichen                               ent->permissions, ent->uid, ent->gid);
17713244Sgraichen                } else {
17813244Sgraichen                        if (verbose)
17913244Sgraichen                                printf("--> skipping\n");
18013244Sgraichen                }
18113244Sgraichen        }
18213244Sgraichen}
18313244Sgraichen
18416240Salexstatic void PRS(argc,argv)
18513244Sgraichen        int argc;
18613244Sgraichen        char **argv;
18713244Sgraichen{
18813244Sgraichen        int     c;
18913244Sgraichen        FILE    *f;
19013244Sgraichen        char    line[BUFSIZ];
19113244Sgraichen	char	*p;
19213244Sgraichen
19313244Sgraichen        progname = argv[0];
19413244Sgraichen        timenow = time((time_t *) 0);
19513244Sgraichen        daytime = ctime(&timenow) + 4;
19613358Sgraichen        daytime[15] = '\0';
19713244Sgraichen
19813244Sgraichen        /* Let's find the pid of syslogd */
19913244Sgraichen        syslog_pid = 0;
20013244Sgraichen        f = fopen(PIDFILE,"r");
20113244Sgraichen        if (f && fgets(line,BUFSIZ,f))
20213244Sgraichen                syslog_pid = atoi(line);
20313244Sgraichen	if (f)
20413244Sgraichen		(void)fclose(f);
20513244Sgraichen
20613244Sgraichen        /* Let's get our hostname */
20713244Sgraichen        (void) gethostname(hostname, sizeof(hostname));
20813244Sgraichen
20913244Sgraichen	/* Truncate domain */
21016240Salex	if ((p = strchr(hostname, '.'))) {
21113244Sgraichen		*p = '\0';
21213244Sgraichen	}
21313244Sgraichen
21413244Sgraichen        optind = 1;             /* Start options parsing */
21513244Sgraichen        while ((c=getopt(argc,argv,"nrvf:t:")) != EOF)
21613244Sgraichen                switch (c) {
21713244Sgraichen                case 'n':
21813244Sgraichen                        noaction++; /* This implies needroot as off */
21913244Sgraichen                        /* fall through */
22013244Sgraichen                case 'r':
22113244Sgraichen                        needroot = 0;
22213244Sgraichen                        break;
22313244Sgraichen                case 'v':
22413244Sgraichen                        verbose++;
22513244Sgraichen                        break;
22613244Sgraichen                case 'f':
22713244Sgraichen                        conf = optarg;
22813244Sgraichen                        break;
22913244Sgraichen                default:
23013244Sgraichen                        usage();
23113244Sgraichen                }
23213244Sgraichen        }
23313244Sgraichen
23416240Salexstatic void usage()
23513244Sgraichen{
23613244Sgraichen        fprintf(stderr,
23713244Sgraichen                "Usage: %s <-nrv> <-f config-file>\n", progname);
23813244Sgraichen        exit(1);
23913244Sgraichen}
24013244Sgraichen
24113244Sgraichen/* Parse a configuration file and return a linked list of all the logs
24213244Sgraichen * to process
24313244Sgraichen */
24416240Salexstatic struct conf_entry *parse_file()
24513244Sgraichen{
24613244Sgraichen        FILE    *f;
24713244Sgraichen        char    line[BUFSIZ], *parse, *q;
24813244Sgraichen        char    *errline, *group;
24913244Sgraichen        struct conf_entry *first = NULL;
25016174Salex        struct conf_entry *working = NULL;
25113244Sgraichen        struct passwd *pass;
25213244Sgraichen        struct group *grp;
25313244Sgraichen
25413244Sgraichen        if (strcmp(conf,"-"))
25513244Sgraichen                f = fopen(conf,"r");
25613244Sgraichen        else
25713244Sgraichen                f = stdin;
25813460Sgraichen        if (!f)
25913460Sgraichen                err(1, "%s", conf);
26013244Sgraichen        while (fgets(line,BUFSIZ,f)) {
26113244Sgraichen                if ((line[0]== '\n') || (line[0] == '#'))
26213244Sgraichen                        continue;
26313244Sgraichen                errline = strdup(line);
26413244Sgraichen                if (!first) {
26513244Sgraichen                        working = (struct conf_entry *) malloc(sizeof(struct conf_entry));
26613244Sgraichen                        first = working;
26713244Sgraichen                } else {
26813244Sgraichen                        working->next = (struct conf_entry *) malloc(sizeof(struct conf_entry));
26913244Sgraichen                        working = working->next;
27013244Sgraichen                }
27113244Sgraichen
27213244Sgraichen                q = parse = missing_field(sob(line),errline);
27313244Sgraichen                *(parse = son(line)) = '\0';
27413244Sgraichen                working->log = strdup(q);
27513244Sgraichen
27613244Sgraichen                q = parse = missing_field(sob(++parse),errline);
27713244Sgraichen                *(parse = son(parse)) = '\0';
27813244Sgraichen                if ((group = strchr(q, '.')) != NULL) {
27913244Sgraichen                    *group++ = '\0';
28013244Sgraichen                    if (*q) {
28113244Sgraichen                        if (!(isnumber(*q))) {
28213460Sgraichen                            if ((pass = getpwnam(q)) == NULL)
28313460Sgraichen                                errx(1,
28413460Sgraichen                                  "Error in config file; unknown user:\n%s",
28513460Sgraichen                                  errline);
28613244Sgraichen                            working->uid = pass->pw_uid;
28713244Sgraichen                        } else
28813244Sgraichen                            working->uid = atoi(q);
28913244Sgraichen                    } else
29013244Sgraichen                        working->uid = NONE;
29113244Sgraichen
29213244Sgraichen                    q = group;
29313244Sgraichen                    if (*q) {
29413244Sgraichen                        if (!(isnumber(*q))) {
29513460Sgraichen                            if ((grp = getgrnam(q)) == NULL)
29613460Sgraichen                                errx(1,
29713460Sgraichen                                  "Error in config file; unknown group:\n%s",
29813460Sgraichen                                  errline);
29913244Sgraichen                            working->gid = grp->gr_gid;
30013244Sgraichen                        } else
30113244Sgraichen                            working->gid = atoi(q);
30213244Sgraichen                    } else
30313244Sgraichen                        working->gid = NONE;
30413244Sgraichen
30513244Sgraichen                    q = parse = missing_field(sob(++parse),errline);
30613244Sgraichen                    *(parse = son(parse)) = '\0';
30713244Sgraichen                }
30813244Sgraichen                else
30913244Sgraichen                    working->uid = working->gid = NONE;
31013244Sgraichen
31113460Sgraichen                if (!sscanf(q,"%o",&working->permissions))
31213460Sgraichen                        errx(1, "Error in config file; bad permissions:\n%s",
31313460Sgraichen                          errline);
31413244Sgraichen
31513244Sgraichen                q = parse = missing_field(sob(++parse),errline);
31613244Sgraichen                *(parse = son(parse)) = '\0';
31713460Sgraichen                if (!sscanf(q,"%d",&working->numlogs))
31813460Sgraichen                        errx(1, "Error in config file; bad number:\n%s",
31913460Sgraichen                          errline);
32013244Sgraichen
32113244Sgraichen                q = parse = missing_field(sob(++parse),errline);
32213244Sgraichen                *(parse = son(parse)) = '\0';
32313244Sgraichen                if (isdigit(*q))
32413244Sgraichen                        working->size = atoi(q);
32513244Sgraichen                else
32613244Sgraichen                        working->size = -1;
32713244Sgraichen
32813244Sgraichen                q = parse = missing_field(sob(++parse),errline);
32913244Sgraichen                *(parse = son(parse)) = '\0';
33013244Sgraichen                if (isdigit(*q))
33113244Sgraichen                        working->hours = atoi(q);
33213244Sgraichen                else
33313244Sgraichen                        working->hours = -1;
33413244Sgraichen
33513244Sgraichen                q = parse = sob(++parse); /* Optional field */
33613244Sgraichen                *(parse = son(parse)) = '\0';
33713244Sgraichen                working->flags = 0;
33813244Sgraichen                while (q && *q && !isspace(*q)) {
33913244Sgraichen                        if ((*q == 'Z') || (*q == 'z'))
34013244Sgraichen                                working->flags |= CE_COMPACT;
34113244Sgraichen                        else if ((*q == 'B') || (*q == 'b'))
34213244Sgraichen                                working->flags |= CE_BINARY;
34313460Sgraichen                        else
34413460Sgraichen                           errx(1, "Illegal flag in config file -- %c", *q);
34513244Sgraichen                        q++;
34613244Sgraichen                }
34713244Sgraichen
34813244Sgraichen                free(errline);
34913244Sgraichen        }
35013244Sgraichen        if (working)
35113244Sgraichen                working->next = (struct conf_entry *) NULL;
35213244Sgraichen        (void) fclose(f);
35313244Sgraichen        return(first);
35413244Sgraichen}
35513244Sgraichen
35616240Salexstatic char *missing_field(p,errline)
35713244Sgraichen        char    *p,*errline;
35813244Sgraichen{
35913460Sgraichen        if (!p || !*p)
36013460Sgraichen            errx(1, "Missing field in config file:\n%s", errline);
36113244Sgraichen        return(p);
36213244Sgraichen}
36313244Sgraichen
36416240Salexstatic void dotrim(log,numdays,flags,perm,owner_uid,group_gid)
36513244Sgraichen        char    *log;
36613244Sgraichen        int     numdays;
36713244Sgraichen        int     flags;
36813244Sgraichen        int     perm;
36913244Sgraichen        int     owner_uid;
37013244Sgraichen        int     group_gid;
37113244Sgraichen{
37213460Sgraichen        char    file1 [MAXPATHLEN+1], file2 [MAXPATHLEN+1];
37313460Sgraichen        char    zfile1[MAXPATHLEN+1], zfile2[MAXPATHLEN+1];
37413244Sgraichen        int     fd;
37513244Sgraichen        struct  stat st;
37613244Sgraichen
37713244Sgraichen#ifdef _IBMR2
37813244Sgraichen/* AIX 3.1 has a broken fchown- if the owner_uid is -1, it will actually */
37913244Sgraichen/* change it to be owned by uid -1, instead of leaving it as is, as it is */
38013244Sgraichen/* supposed to. */
38113244Sgraichen                if (owner_uid == -1)
38213244Sgraichen                  owner_uid = geteuid();
38313244Sgraichen#endif
38413244Sgraichen
38513244Sgraichen        /* Remove oldest log */
38613244Sgraichen        (void) sprintf(file1,"%s.%d",log,numdays);
38713244Sgraichen        (void) strcpy(zfile1, file1);
38813244Sgraichen        (void) strcat(zfile1, COMPRESS_POSTFIX);
38913244Sgraichen
39013244Sgraichen        if (noaction) {
39113244Sgraichen                printf("rm -f %s\n", file1);
39213244Sgraichen                printf("rm -f %s\n", zfile1);
39313244Sgraichen        } else {
39413244Sgraichen                (void) unlink(file1);
39513244Sgraichen                (void) unlink(zfile1);
39613244Sgraichen        }
39713244Sgraichen
39813244Sgraichen        /* Move down log files */
39913244Sgraichen        while (numdays--) {
40013244Sgraichen                (void) strcpy(file2,file1);
40113244Sgraichen                (void) sprintf(file1,"%s.%d",log,numdays);
40213244Sgraichen                (void) strcpy(zfile1, file1);
40313244Sgraichen                (void) strcpy(zfile2, file2);
40413244Sgraichen                if (lstat(file1, &st)) {
40513244Sgraichen                        (void) strcat(zfile1, COMPRESS_POSTFIX);
40613244Sgraichen                        (void) strcat(zfile2, COMPRESS_POSTFIX);
40713244Sgraichen                        if (lstat(zfile1, &st)) continue;
40813244Sgraichen                }
40913244Sgraichen                if (noaction) {
41013244Sgraichen                        printf("mv %s %s\n",zfile1,zfile2);
41113244Sgraichen                        printf("chmod %o %s\n", perm, zfile2);
41213244Sgraichen                        printf("chown %d.%d %s\n",
41313244Sgraichen                               owner_uid, group_gid, zfile2);
41413244Sgraichen                } else {
41513244Sgraichen                        (void) rename(zfile1, zfile2);
41613244Sgraichen                        (void) chmod(zfile2, perm);
41713244Sgraichen                        (void) chown(zfile2, owner_uid, group_gid);
41813244Sgraichen                }
41913244Sgraichen        }
42013244Sgraichen        if (!noaction && !(flags & CE_BINARY))
42113244Sgraichen                (void) log_trim(log);  /* Report the trimming to the old log */
42213244Sgraichen
42318075Sjkh	if (numdays == -1) {
42418075Sjkh		if (noaction)
42518075Sjkh			printf("rm %s\n",log);
42618075Sjkh		else
42718075Sjkh			(void)unlink(log);
42818075Sjkh	}
42918075Sjkh	else {
43018075Sjkh		if (noaction)
43118075Sjkh			printf("mv %s to %s\n",log,file1);
43218075Sjkh		else
43318075Sjkh			(void)rename(log, file1);
43418075Sjkh	}
43518075Sjkh
43613244Sgraichen        if (noaction)
43713244Sgraichen                printf("Start new log...");
43813244Sgraichen        else {
43913244Sgraichen                fd = creat(log,perm);
44013460Sgraichen                if (fd < 0)
44113460Sgraichen                        err(1, "can't start new log");
44213460Sgraichen                if (fchown(fd, owner_uid, group_gid))
44313460Sgraichen                        err(1, "can't chmod new log file");
44413244Sgraichen                (void) close(fd);
44513244Sgraichen                if (!(flags & CE_BINARY))
44613460Sgraichen                        if (log_trim(log))    /* Add status message */
44713460Sgraichen                             err(1, "can't add status message to log");
44813244Sgraichen        }
44913244Sgraichen        if (noaction)
45013244Sgraichen                printf("chmod %o %s...",perm,log);
45113244Sgraichen        else
45213244Sgraichen                (void) chmod(log,perm);
45313244Sgraichen        if (noaction)
45413244Sgraichen                printf("kill -HUP %d (syslogd)\n",syslog_pid);
45513244Sgraichen        else
45613244Sgraichen	if (syslog_pid < MIN_PID || syslog_pid > MAX_PID) {
45713460Sgraichen		warnx("preposterous process number: %d", syslog_pid);
45813460Sgraichen        } else if (kill(syslog_pid,SIGHUP))
45913460Sgraichen                warn("could not restart syslogd");
46013244Sgraichen        if (flags & CE_COMPACT) {
46113244Sgraichen                if (noaction)
46213244Sgraichen                        printf("Compress %s.0\n",log);
46313244Sgraichen                else
46413244Sgraichen                        compress_log(log);
46513244Sgraichen        }
46613244Sgraichen}
46713244Sgraichen
46813244Sgraichen/* Log the fact that the logs were turned over */
46916240Salexstatic int log_trim(log)
47013244Sgraichen        char    *log;
47113244Sgraichen{
47213244Sgraichen        FILE    *f;
47313244Sgraichen        if ((f = fopen(log,"a")) == NULL)
47413244Sgraichen                return(-1);
47513244Sgraichen        fprintf(f,"%s %s newsyslog[%d]: logfile turned over\n",
47616240Salex                daytime, hostname, (int)getpid());
47713460Sgraichen        if (fclose(f) == EOF)
47813460Sgraichen                err(1, "log_trim: fclose:");
47913244Sgraichen        return(0);
48013244Sgraichen}
48113244Sgraichen
48213244Sgraichen/* Fork of /usr/ucb/compress to compress the old log file */
48316240Salexstatic void compress_log(log)
48413244Sgraichen        char    *log;
48513244Sgraichen{
48613244Sgraichen        int     pid;
48713244Sgraichen        char    tmp[128];
48813244Sgraichen
48913244Sgraichen        pid = fork();
49013244Sgraichen        (void) sprintf(tmp,"%s.0",log);
49113460Sgraichen        if (pid < 0)
49213460Sgraichen                err(1, "fork");
49313460Sgraichen        else if (!pid) {
49413460Sgraichen                (void) execl(COMPRESS_PATH,COMPRESS_PROG,"-f",tmp,0);
49513460Sgraichen                err(1, COMPRESS_PATH);
49613244Sgraichen        }
49713244Sgraichen}
49813244Sgraichen
49913244Sgraichen/* Return size in kilobytes of a file */
50016240Salexstatic int sizefile(file)
50113244Sgraichen        char    *file;
50213244Sgraichen{
50313244Sgraichen        struct stat sb;
50413244Sgraichen
50513244Sgraichen        if (stat(file,&sb) < 0)
50613244Sgraichen                return(-1);
50713244Sgraichen        return(kbytes(dbtob(sb.st_blocks)));
50813244Sgraichen}
50913244Sgraichen
51013244Sgraichen/* Return the age of old log file (file.0) */
51116240Salexstatic int age_old_log(file)
51213244Sgraichen        char    *file;
51313244Sgraichen{
51413244Sgraichen        struct stat sb;
51513460Sgraichen        char tmp[MAXPATHLEN+sizeof(".0")+sizeof(COMPRESS_POSTFIX)+1];
51613244Sgraichen
51713244Sgraichen        (void) strcpy(tmp,file);
51813244Sgraichen        if (stat(strcat(tmp,".0"),&sb) < 0)
51913244Sgraichen            if (stat(strcat(tmp,COMPRESS_POSTFIX), &sb) < 0)
52013244Sgraichen                return(-1);
52113244Sgraichen        return( (int) (timenow - sb.st_mtime + 1800) / 3600);
52213244Sgraichen}
52313244Sgraichen
52413244Sgraichen
52513244Sgraichen#ifndef OSF
52613244Sgraichen/* Duplicate a string using malloc */
52713244Sgraichen
52813244Sgraichenchar *strdup(strp)
52913244Sgraichenregister char   *strp;
53013244Sgraichen{
53113244Sgraichen        register char *cp;
53213244Sgraichen
53313244Sgraichen        if ((cp = malloc((unsigned) strlen(strp) + 1)) == NULL)
53413244Sgraichen                abort();
53513244Sgraichen        return(strcpy (cp, strp));
53613244Sgraichen}
53713244Sgraichen#endif
53813244Sgraichen
53913244Sgraichen/* Skip Over Blanks */
54013244Sgraichenchar *sob(p)
54113244Sgraichen        register char   *p;
54213244Sgraichen{
54313244Sgraichen        while (p && *p && isspace(*p))
54413244Sgraichen                p++;
54513244Sgraichen        return(p);
54613244Sgraichen}
54713244Sgraichen
54813244Sgraichen/* Skip Over Non-Blanks */
54913244Sgraichenchar *son(p)
55013244Sgraichen        register char   *p;
55113244Sgraichen{
55213244Sgraichen        while (p && *p && !isspace(*p))
55313244Sgraichen                p++;
55413244Sgraichen        return(p);
55513244Sgraichen}
556