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