newsyslog.c revision 30160
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 */
2713244Sgraichen
2813244Sgraichen#ifndef lint
2930160Scharnierstatic const char rcsid[] =
3030160Scharnier	"$Id: newsyslog.c,v 1.13 1997/05/06 23:11:06 brian Exp $";
3113244Sgraichen#endif /* not lint */
3213244Sgraichen
3313244Sgraichen#ifndef CONF
3413244Sgraichen#define CONF "/etc/athena/newsyslog.conf" /* Configuration file */
3513244Sgraichen#endif
3613244Sgraichen#ifndef PIDFILE
3713244Sgraichen#define PIDFILE "/etc/syslog.pid"
3813244Sgraichen#endif
3913460Sgraichen#ifndef COMPRESS_PATH
4013460Sgraichen#define COMPRESS_PATH "/usr/ucb/compress" /* File compression program */
4113244Sgraichen#endif
4213460Sgraichen#ifndef COMPRESS_PROG
4313460Sgraichen#define COMPRESS_PROG "compress"
4413460Sgraichen#endif
4513244Sgraichen#ifndef COMPRESS_POSTFIX
4613244Sgraichen#define COMPRESS_POSTFIX ".Z"
4713244Sgraichen#endif
4813244Sgraichen
4930160Scharnier#include <ctype.h>
5030160Scharnier#include <err.h>
5130160Scharnier#include <fcntl.h>
5230160Scharnier#include <grp.h>
5330160Scharnier#include <pwd.h>
5430160Scharnier#include <signal.h>
5513244Sgraichen#include <stdio.h>
5613244Sgraichen#include <stdlib.h>
5713244Sgraichen#include <string.h>
5816240Salex#include <unistd.h>
5913244Sgraichen#include <sys/types.h>
6013244Sgraichen#include <sys/time.h>
6113244Sgraichen#include <sys/stat.h>
6213244Sgraichen#include <sys/param.h>
6313244Sgraichen#include <sys/wait.h>
6413244Sgraichen
6513244Sgraichen#define kbytes(size)  (((size) + 1023) >> 10)
6613244Sgraichen#ifdef _IBMR2
6713244Sgraichen/* Calculates (db * DEV_BSIZE) */
6813244Sgraichen#define dbtob(db)  ((unsigned)(db) << UBSHIFT)
6913244Sgraichen#endif
7013244Sgraichen
7113244Sgraichen#define CE_COMPACT 1            /* Compact the achived log files */
7213460Sgraichen#define CE_BINARY  2            /* Logfile is in binary, don't add */
7313244Sgraichen                                /* status messages */
7413244Sgraichen#define NONE -1
7513244Sgraichen
7613244Sgraichenstruct conf_entry {
7713244Sgraichen        char    *log;           /* Name of the log */
7825443Sache	char	*pid_file;	/* PID file */
7913244Sgraichen        int     uid;            /* Owner of log */
8013244Sgraichen        int     gid;            /* Group of log */
8113244Sgraichen        int     numlogs;        /* Number of logs to keep */
8213244Sgraichen        int     size;           /* Size cutoff to trigger trimming the log */
8313244Sgraichen        int     hours;          /* Hours between log trimming */
8413244Sgraichen        int     permissions;    /* File permissions on the log */
8513244Sgraichen        int     flags;          /* Flags (CE_COMPACT & CE_BINARY)  */
8613244Sgraichen        struct conf_entry       *next; /* Linked list pointer */
8713244Sgraichen};
8813244Sgraichen
8913244Sgraichenint     verbose = 0;            /* Print out what's going on */
9013244Sgraichenint     needroot = 1;           /* Root privs are necessary */
9113244Sgraichenint     noaction = 0;           /* Don't do anything, just show it */
9213244Sgraichenchar    *conf = CONF;           /* Configuration file to use */
9313244Sgraichentime_t  timenow;
9425443Sachepid_t   syslog_pid;             /* read in from /etc/syslog.pid */
9525443Sache#define MIN_PID         5
9613460Sgraichen#define MAX_PID		30000   /* was 65534, see /usr/include/sys/proc.h */
9713460Sgraichenchar    hostname[MAXHOSTNAMELEN+1]; /* hostname */
9813244Sgraichenchar    *daytime;               /* timenow in human readable form */
9913244Sgraichen
10016240Salex#ifndef OSF
10116240Salexchar *strdup(char *strp);
10216240Salex#endif
10313244Sgraichen
10416240Salexstatic struct conf_entry *parse_file();
10516240Salexstatic char *sob(char *p);
10616240Salexstatic char *son(char *p);
10716240Salexstatic char *missing_field(char *p,char *errline);
10816240Salexstatic void do_entry(struct conf_entry *ent);
10916240Salexstatic void PRS(int argc,char **argv);
11016240Salexstatic void usage();
11125443Sachestatic void dotrim(char *log,char *pid_file,int numdays,int falgs,int perm, int owner_uid,int group_gid);
11216240Salexstatic int log_trim(char *log);
11316240Salexstatic void compress_log(char *log);
11416240Salexstatic int sizefile(char *file);
11516240Salexstatic int age_old_log(char *file);
11625443Sachestatic pid_t get_pid(char *pid_file);
11713244Sgraichen
11816240Salexint main(argc,argv)
11913244Sgraichen        int argc;
12013244Sgraichen        char **argv;
12113244Sgraichen{
12213244Sgraichen        struct conf_entry *p, *q;
12313244Sgraichen
12413244Sgraichen        PRS(argc,argv);
12530160Scharnier        if (needroot && getuid() && geteuid())
12630160Scharnier                errx(1, "must have root privs");
12713244Sgraichen        p = q = parse_file();
12825443Sache
12925496Sache	syslog_pid = needroot ? get_pid(PIDFILE) : 0;
13025443Sache
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                        }
17525443Sache                        dotrim(ent->log, ent->pid_file, ent->numlogs,
17625443Sache			    ent->flags, 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	char	*p;
19013244Sgraichen
19113244Sgraichen        timenow = time((time_t *) 0);
19213244Sgraichen        daytime = ctime(&timenow) + 4;
19313358Sgraichen        daytime[15] = '\0';
19413244Sgraichen
19513244Sgraichen        /* Let's get our hostname */
19613244Sgraichen        (void) gethostname(hostname, sizeof(hostname));
19713244Sgraichen
19813244Sgraichen	/* Truncate domain */
19916240Salex	if ((p = strchr(hostname, '.'))) {
20013244Sgraichen		*p = '\0';
20113244Sgraichen	}
20213244Sgraichen
20313244Sgraichen        optind = 1;             /* Start options parsing */
20424428Simp        while ((c=getopt(argc,argv,"nrvf:t:")) != -1)
20513244Sgraichen                switch (c) {
20613244Sgraichen                case 'n':
20713244Sgraichen                        noaction++; /* This implies needroot as off */
20813244Sgraichen                        /* fall through */
20913244Sgraichen                case 'r':
21013244Sgraichen                        needroot = 0;
21113244Sgraichen                        break;
21213244Sgraichen                case 'v':
21313244Sgraichen                        verbose++;
21413244Sgraichen                        break;
21513244Sgraichen                case 'f':
21613244Sgraichen                        conf = optarg;
21713244Sgraichen                        break;
21813244Sgraichen                default:
21913244Sgraichen                        usage();
22013244Sgraichen                }
22113244Sgraichen        }
22213244Sgraichen
22316240Salexstatic void usage()
22413244Sgraichen{
22530160Scharnier        fprintf(stderr, "usage: newsyslog [-nrv] [-f config-file]\n");
22613244Sgraichen        exit(1);
22713244Sgraichen}
22813244Sgraichen
22913244Sgraichen/* Parse a configuration file and return a linked list of all the logs
23013244Sgraichen * to process
23113244Sgraichen */
23216240Salexstatic struct conf_entry *parse_file()
23313244Sgraichen{
23413244Sgraichen        FILE    *f;
23513244Sgraichen        char    line[BUFSIZ], *parse, *q;
23613244Sgraichen        char    *errline, *group;
23713244Sgraichen        struct conf_entry *first = NULL;
23816174Salex        struct conf_entry *working = NULL;
23913244Sgraichen        struct passwd *pass;
24013244Sgraichen        struct group *grp;
24125518Sbrian	int eol;
24213244Sgraichen
24313244Sgraichen        if (strcmp(conf,"-"))
24413244Sgraichen                f = fopen(conf,"r");
24513244Sgraichen        else
24613244Sgraichen                f = stdin;
24713460Sgraichen        if (!f)
24813460Sgraichen                err(1, "%s", conf);
24913244Sgraichen        while (fgets(line,BUFSIZ,f)) {
25013244Sgraichen                if ((line[0]== '\n') || (line[0] == '#'))
25113244Sgraichen                        continue;
25213244Sgraichen                errline = strdup(line);
25313244Sgraichen                if (!first) {
25413244Sgraichen                        working = (struct conf_entry *) malloc(sizeof(struct conf_entry));
25513244Sgraichen                        first = working;
25613244Sgraichen                } else {
25713244Sgraichen                        working->next = (struct conf_entry *) malloc(sizeof(struct conf_entry));
25813244Sgraichen                        working = working->next;
25913244Sgraichen                }
26013244Sgraichen
26113244Sgraichen                q = parse = missing_field(sob(line),errline);
26225518Sbrian                parse = son(line);
26325518Sbrian		if (!*parse)
26430160Scharnier                  errx(1, "malformed line (missing fields):\n%s", errline);
26525518Sbrian                *parse = '\0';
26613244Sgraichen                working->log = strdup(q);
26713244Sgraichen
26813244Sgraichen                q = parse = missing_field(sob(++parse),errline);
26925518Sbrian                parse = son(parse);
27025518Sbrian		if (!*parse)
27130160Scharnier                  errx(1, "malformed line (missing fields):\n%s", errline);
27225518Sbrian                *parse = '\0';
27313244Sgraichen                if ((group = strchr(q, '.')) != NULL) {
27413244Sgraichen                    *group++ = '\0';
27513244Sgraichen                    if (*q) {
27613244Sgraichen                        if (!(isnumber(*q))) {
27713460Sgraichen                            if ((pass = getpwnam(q)) == NULL)
27813460Sgraichen                                errx(1,
27930160Scharnier                                  "error in config file; unknown user:\n%s",
28013460Sgraichen                                  errline);
28113244Sgraichen                            working->uid = pass->pw_uid;
28213244Sgraichen                        } else
28313244Sgraichen                            working->uid = atoi(q);
28413244Sgraichen                    } else
28513244Sgraichen                        working->uid = NONE;
28613244Sgraichen
28713244Sgraichen                    q = group;
28813244Sgraichen                    if (*q) {
28913244Sgraichen                        if (!(isnumber(*q))) {
29013460Sgraichen                            if ((grp = getgrnam(q)) == NULL)
29113460Sgraichen                                errx(1,
29230160Scharnier                                  "error in config file; unknown group:\n%s",
29313460Sgraichen                                  errline);
29413244Sgraichen                            working->gid = grp->gr_gid;
29513244Sgraichen                        } else
29613244Sgraichen                            working->gid = atoi(q);
29713244Sgraichen                    } else
29813244Sgraichen                        working->gid = NONE;
29913244Sgraichen
30013244Sgraichen                    q = parse = missing_field(sob(++parse),errline);
30125518Sbrian                    parse = son(parse);
30225518Sbrian		    if (!*parse)
30330160Scharnier                      errx(1, "malformed line (missing fields):\n%s", errline);
30425518Sbrian                    *parse = '\0';
30513244Sgraichen                }
30613244Sgraichen                else
30713244Sgraichen                    working->uid = working->gid = NONE;
30813244Sgraichen
30913460Sgraichen                if (!sscanf(q,"%o",&working->permissions))
31030160Scharnier                        errx(1, "error in config file; bad permissions:\n%s",
31113460Sgraichen                          errline);
31213244Sgraichen
31313244Sgraichen                q = parse = missing_field(sob(++parse),errline);
31425518Sbrian                parse = son(parse);
31525518Sbrian		if (!*parse)
31630160Scharnier                  errx(1, "malformed line (missing fields):\n%s", errline);
31725518Sbrian                *parse = '\0';
31813460Sgraichen                if (!sscanf(q,"%d",&working->numlogs))
31930160Scharnier                        errx(1, "error in config file; bad number:\n%s",
32013460Sgraichen                          errline);
32113244Sgraichen
32213244Sgraichen                q = parse = missing_field(sob(++parse),errline);
32325518Sbrian                parse = son(parse);
32425518Sbrian		if (!*parse)
32530160Scharnier                  errx(1, "malformed line (missing fields):\n%s", errline);
32625518Sbrian                *parse = '\0';
32713244Sgraichen                if (isdigit(*q))
32813244Sgraichen                        working->size = atoi(q);
32913244Sgraichen                else
33013244Sgraichen                        working->size = -1;
33113244Sgraichen
33213244Sgraichen                q = parse = missing_field(sob(++parse),errline);
33325518Sbrian                parse = son(parse);
33425518Sbrian		eol = !*parse;
33525518Sbrian                *parse = '\0';
33613244Sgraichen                if (isdigit(*q))
33713244Sgraichen                        working->hours = atoi(q);
33813244Sgraichen                else
33913244Sgraichen                        working->hours = -1;
34013244Sgraichen
34125518Sbrian		if (eol)
34225518Sbrian		  q = NULL;
34325518Sbrian		else {
34425518Sbrian                  q = parse = sob(++parse); /* Optional field */
34525518Sbrian                  parse = son(parse);
34625518Sbrian		  if (!*parse)
34725518Sbrian                    eol = 1;
34825518Sbrian                  *parse = '\0';
34925518Sbrian		}
35025443Sache
35113244Sgraichen                working->flags = 0;
35213244Sgraichen                while (q && *q && !isspace(*q)) {
35313244Sgraichen                        if ((*q == 'Z') || (*q == 'z'))
35413244Sgraichen                                working->flags |= CE_COMPACT;
35513244Sgraichen                        else if ((*q == 'B') || (*q == 'b'))
35613244Sgraichen                                working->flags |= CE_BINARY;
35725518Sbrian                        else if (*q != '-')
35830160Scharnier                           errx(1, "illegal flag in config file -- %c", *q);
35913244Sgraichen                        q++;
36013244Sgraichen                }
36113244Sgraichen
36225518Sbrian		if (eol)
36325518Sbrian		  q = NULL;
36425518Sbrian		else {
36525518Sbrian		  q = parse = sob(++parse); /* Optional field */
36625518Sbrian		  *(parse = son(parse)) = '\0';
36725518Sbrian		}
36825443Sache
36925443Sache		working->pid_file = NULL;
37025443Sache		if (q && *q) {
37125443Sache			if (*q == '/')
37225443Sache				working->pid_file = strdup(q);
37325443Sache                        else
37430160Scharnier			   errx(1, "illegal pid file in config file:\n%s", q);
37525443Sache		}
37625443Sache
37713244Sgraichen                free(errline);
37813244Sgraichen        }
37913244Sgraichen        if (working)
38013244Sgraichen                working->next = (struct conf_entry *) NULL;
38113244Sgraichen        (void) fclose(f);
38213244Sgraichen        return(first);
38313244Sgraichen}
38413244Sgraichen
38516240Salexstatic char *missing_field(p,errline)
38613244Sgraichen        char    *p,*errline;
38713244Sgraichen{
38813460Sgraichen        if (!p || !*p)
38930160Scharnier            errx(1, "missing field in config file:\n%s", errline);
39013244Sgraichen        return(p);
39113244Sgraichen}
39213244Sgraichen
39325443Sachestatic void dotrim(log,pid_file,numdays,flags,perm,owner_uid,group_gid)
39413244Sgraichen        char    *log;
39525443Sache	char    *pid_file;
39613244Sgraichen        int     numdays;
39713244Sgraichen        int     flags;
39813244Sgraichen        int     perm;
39913244Sgraichen        int     owner_uid;
40013244Sgraichen        int     group_gid;
40113244Sgraichen{
40213460Sgraichen        char    file1 [MAXPATHLEN+1], file2 [MAXPATHLEN+1];
40313460Sgraichen        char    zfile1[MAXPATHLEN+1], zfile2[MAXPATHLEN+1];
40425443Sache	int     notified, need_notification, fd, _numdays;
40513244Sgraichen        struct  stat st;
40625443Sache	pid_t   pid;
40713244Sgraichen
40813244Sgraichen#ifdef _IBMR2
40913244Sgraichen/* AIX 3.1 has a broken fchown- if the owner_uid is -1, it will actually */
41013244Sgraichen/* change it to be owned by uid -1, instead of leaving it as is, as it is */
41113244Sgraichen/* supposed to. */
41213244Sgraichen                if (owner_uid == -1)
41313244Sgraichen                  owner_uid = geteuid();
41413244Sgraichen#endif
41513244Sgraichen
41613244Sgraichen        /* Remove oldest log */
41713244Sgraichen        (void) sprintf(file1,"%s.%d",log,numdays);
41813244Sgraichen        (void) strcpy(zfile1, file1);
41913244Sgraichen        (void) strcat(zfile1, COMPRESS_POSTFIX);
42013244Sgraichen
42113244Sgraichen        if (noaction) {
42213244Sgraichen                printf("rm -f %s\n", file1);
42313244Sgraichen                printf("rm -f %s\n", zfile1);
42413244Sgraichen        } else {
42513244Sgraichen                (void) unlink(file1);
42613244Sgraichen                (void) unlink(zfile1);
42713244Sgraichen        }
42813244Sgraichen
42913244Sgraichen        /* Move down log files */
43018188Sjkh	_numdays = numdays;	/* preserve */
43113244Sgraichen        while (numdays--) {
43213244Sgraichen                (void) strcpy(file2,file1);
43313244Sgraichen                (void) sprintf(file1,"%s.%d",log,numdays);
43413244Sgraichen                (void) strcpy(zfile1, file1);
43513244Sgraichen                (void) strcpy(zfile2, file2);
43613244Sgraichen                if (lstat(file1, &st)) {
43713244Sgraichen                        (void) strcat(zfile1, COMPRESS_POSTFIX);
43813244Sgraichen                        (void) strcat(zfile2, COMPRESS_POSTFIX);
43925443Sache			if (lstat(zfile1, &st)) continue;
44013244Sgraichen                }
44113244Sgraichen                if (noaction) {
44213244Sgraichen                        printf("mv %s %s\n",zfile1,zfile2);
44313244Sgraichen                        printf("chmod %o %s\n", perm, zfile2);
44413244Sgraichen                        printf("chown %d.%d %s\n",
44513244Sgraichen                               owner_uid, group_gid, zfile2);
44613244Sgraichen                } else {
44713244Sgraichen                        (void) rename(zfile1, zfile2);
44813244Sgraichen                        (void) chmod(zfile2, perm);
44913244Sgraichen                        (void) chown(zfile2, owner_uid, group_gid);
45013244Sgraichen                }
45113244Sgraichen        }
45213244Sgraichen        if (!noaction && !(flags & CE_BINARY))
45313244Sgraichen                (void) log_trim(log);  /* Report the trimming to the old log */
45413244Sgraichen
45518188Sjkh	if (!_numdays) {
45618075Sjkh		if (noaction)
45718075Sjkh			printf("rm %s\n",log);
45818075Sjkh		else
45918075Sjkh			(void)unlink(log);
46018075Sjkh	}
46118075Sjkh	else {
46218075Sjkh		if (noaction)
46318075Sjkh			printf("mv %s to %s\n",log,file1);
46418075Sjkh		else
46518075Sjkh			(void)rename(log, file1);
46618075Sjkh	}
46718075Sjkh
46813244Sgraichen        if (noaction)
46913244Sgraichen                printf("Start new log...");
47013244Sgraichen        else {
47113244Sgraichen                fd = creat(log,perm);
47213460Sgraichen                if (fd < 0)
47313460Sgraichen                        err(1, "can't start new log");
47413460Sgraichen                if (fchown(fd, owner_uid, group_gid))
47513460Sgraichen                        err(1, "can't chmod new log file");
47613244Sgraichen                (void) close(fd);
47713244Sgraichen                if (!(flags & CE_BINARY))
47813460Sgraichen                        if (log_trim(log))    /* Add status message */
47913460Sgraichen                             err(1, "can't add status message to log");
48013244Sgraichen        }
48113244Sgraichen        if (noaction)
48213244Sgraichen                printf("chmod %o %s...",perm,log);
48313244Sgraichen        else
48413244Sgraichen                (void) chmod(log,perm);
48525443Sache
48625443Sache	pid = 0;
48725443Sache	need_notification = notified = 0;
48825443Sache	if (pid_file != NULL) {
48925443Sache		need_notification = 1;
49025443Sache		pid = get_pid(pid_file);
49125496Sache	} else if (needroot && !(flags & CE_BINARY)) {
49225443Sache		need_notification = 1;
49325443Sache		pid = syslog_pid;
49425443Sache	}
49525443Sache
49625443Sache	if (pid) {
49725443Sache		if (noaction) {
49825443Sache			notified = 1;
49925443Sache			printf("kill -HUP %d\n", (int)pid);
50025443Sache		} else if (kill(pid,SIGHUP))
50125443Sache			warn("can't notify daemon, pid %d", (int)pid);
50225443Sache		else {
50325443Sache			notified = 1;
50425443Sache			if (verbose)
50525443Sache				printf("daemon pid %d notified\n", (int)pid);
50625443Sache		}
50725443Sache	}
50825443Sache
50925443Sache	if ((flags & CE_COMPACT)) {
51025443Sache		if (need_notification && !notified)
51125443Sache			warnx("log not compressed because daemon not notified");
51225443Sache		else if (noaction)
51313244Sgraichen                        printf("Compress %s.0\n",log);
51425443Sache		else {
51525443Sache			if (notified) {
51625443Sache				if (verbose)
51725443Sache					printf("small pause to allow daemon to close log\n");
51825443Sache				sleep(3);
51925443Sache			}
52013244Sgraichen                        compress_log(log);
52125443Sache		}
52213244Sgraichen        }
52313244Sgraichen}
52413244Sgraichen
52513244Sgraichen/* Log the fact that the logs were turned over */
52616240Salexstatic int log_trim(log)
52713244Sgraichen        char    *log;
52813244Sgraichen{
52913244Sgraichen        FILE    *f;
53013244Sgraichen        if ((f = fopen(log,"a")) == NULL)
53113244Sgraichen                return(-1);
53213244Sgraichen        fprintf(f,"%s %s newsyslog[%d]: logfile turned over\n",
53316240Salex                daytime, hostname, (int)getpid());
53413460Sgraichen        if (fclose(f) == EOF)
53513460Sgraichen                err(1, "log_trim: fclose:");
53613244Sgraichen        return(0);
53713244Sgraichen}
53813244Sgraichen
53913244Sgraichen/* Fork of /usr/ucb/compress to compress the old log file */
54016240Salexstatic void compress_log(log)
54113244Sgraichen        char    *log;
54213244Sgraichen{
54325443Sache	pid_t   pid;
54425443Sache	char    tmp[MAXPATHLEN+1];
54513244Sgraichen
54613244Sgraichen        (void) sprintf(tmp,"%s.0",log);
54725443Sache	pid = fork();
54813460Sgraichen        if (pid < 0)
54913460Sgraichen                err(1, "fork");
55013460Sgraichen        else if (!pid) {
55125443Sache		(void) execl(COMPRESS_PATH,COMPRESS_PROG,"-f",tmp,0);
55225443Sache		err(1, COMPRESS_PATH);
55313244Sgraichen        }
55413244Sgraichen}
55513244Sgraichen
55613244Sgraichen/* Return size in kilobytes of a file */
55716240Salexstatic int sizefile(file)
55813244Sgraichen        char    *file;
55913244Sgraichen{
56013244Sgraichen        struct stat sb;
56113244Sgraichen
56213244Sgraichen        if (stat(file,&sb) < 0)
56313244Sgraichen                return(-1);
56413244Sgraichen        return(kbytes(dbtob(sb.st_blocks)));
56513244Sgraichen}
56613244Sgraichen
56713244Sgraichen/* Return the age of old log file (file.0) */
56816240Salexstatic int age_old_log(file)
56913244Sgraichen        char    *file;
57013244Sgraichen{
57113244Sgraichen        struct stat sb;
57213460Sgraichen        char tmp[MAXPATHLEN+sizeof(".0")+sizeof(COMPRESS_POSTFIX)+1];
57313244Sgraichen
57413244Sgraichen        (void) strcpy(tmp,file);
57513244Sgraichen        if (stat(strcat(tmp,".0"),&sb) < 0)
57613244Sgraichen            if (stat(strcat(tmp,COMPRESS_POSTFIX), &sb) < 0)
57713244Sgraichen                return(-1);
57813244Sgraichen        return( (int) (timenow - sb.st_mtime + 1800) / 3600);
57913244Sgraichen}
58013244Sgraichen
58125443Sachestatic pid_t get_pid(pid_file)
58225443Sache	char *pid_file;
58325443Sache{
58425443Sache	FILE *f;
58525443Sache	char  line[BUFSIZ];
58625443Sache	pid_t pid = 0;
58713244Sgraichen
58825443Sache	if ((f = fopen(pid_file,"r")) == NULL)
58925443Sache		warn("can't open %s pid file to restart a daemon",
59025443Sache			pid_file);
59125443Sache	else {
59225443Sache		if (fgets(line,BUFSIZ,f)) {
59325443Sache			pid = atol(line);
59425443Sache			if (pid < MIN_PID || pid > MAX_PID) {
59525443Sache				warnx("preposterous process number: %d", (int)pid);
59625443Sache				pid = 0;
59725443Sache			}
59825443Sache		} else
59925443Sache			warn("can't read %s pid file to restart a daemon",
60025443Sache				pid_file);
60125443Sache		(void)fclose(f);
60225443Sache	}
60325443Sache	return pid;
60425443Sache}
60525443Sache
60613244Sgraichen#ifndef OSF
60713244Sgraichen/* Duplicate a string using malloc */
60813244Sgraichen
60913244Sgraichenchar *strdup(strp)
61013244Sgraichenregister char   *strp;
61113244Sgraichen{
61213244Sgraichen        register char *cp;
61313244Sgraichen
61413244Sgraichen        if ((cp = malloc((unsigned) strlen(strp) + 1)) == NULL)
61513244Sgraichen                abort();
61613244Sgraichen        return(strcpy (cp, strp));
61713244Sgraichen}
61813244Sgraichen#endif
61913244Sgraichen
62013244Sgraichen/* Skip Over Blanks */
62113244Sgraichenchar *sob(p)
62225443Sache	register char   *p;
62313244Sgraichen{
62413244Sgraichen        while (p && *p && isspace(*p))
62513244Sgraichen                p++;
62613244Sgraichen        return(p);
62713244Sgraichen}
62813244Sgraichen
62913244Sgraichen/* Skip Over Non-Blanks */
63013244Sgraichenchar *son(p)
63125443Sache	register char   *p;
63213244Sgraichen{
63313244Sgraichen        while (p && *p && !isspace(*p))
63413244Sgraichen                p++;
63513244Sgraichen        return(p);
63613244Sgraichen}
637