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