newsyslog.c revision 30160
1100966Siwasaki/* 2100966Siwasaki * This file contains changes from the Open Software Foundation. 3100966Siwasaki */ 4100966Siwasaki 5167802Sjkim/* 6100966Siwasaki 7100966SiwasakiCopyright 1988, 1989 by the Massachusetts Institute of Technology 8100966Siwasaki 9100966SiwasakiPermission to use, copy, modify, and distribute this software 10100966Siwasakiand its documentation for any purpose and without fee is 11100966Siwasakihereby granted, provided that the above copyright notice 12100966Siwasakiappear in all copies and that both that copyright notice and 13167802Sjkimthis permission notice appear in supporting documentation, 14100966Siwasakiand that the names of M.I.T. and the M.I.T. S.I.P.B. not be 15100966Siwasakiused in advertising or publicity pertaining to distribution 16100966Siwasakiof the software without specific, written prior permission. 17100966SiwasakiM.I.T. and the M.I.T. S.I.P.B. make no representations about 18100966Siwasakithe suitability of this software for any purpose. It is 19100966Siwasakiprovided "as is" without express or implied warranty. 20100966Siwasaki 21100966Siwasaki*/ 22100966Siwasaki 23100966Siwasaki/* 24100966Siwasaki * newsyslog - roll over selected logs at the appropriate time, 25100966Siwasaki * keeping the a specified number of backup files around. 26100966Siwasaki */ 27100966Siwasaki 28100966Siwasaki#ifndef lint 29100966Siwasakistatic const char rcsid[] = 30100966Siwasaki "$Id: newsyslog.c,v 1.13 1997/05/06 23:11:06 brian Exp $"; 31100966Siwasaki#endif /* not lint */ 32100966Siwasaki 33100966Siwasaki#ifndef CONF 34100966Siwasaki#define CONF "/etc/athena/newsyslog.conf" /* Configuration file */ 35100966Siwasaki#endif 36100966Siwasaki#ifndef PIDFILE 37100966Siwasaki#define PIDFILE "/etc/syslog.pid" 38100966Siwasaki#endif 39100966Siwasaki#ifndef COMPRESS_PATH 40100966Siwasaki#define COMPRESS_PATH "/usr/ucb/compress" /* File compression program */ 41100966Siwasaki#endif 42100966Siwasaki#ifndef COMPRESS_PROG 43100966Siwasaki#define COMPRESS_PROG "compress" 44100966Siwasaki#endif 45100966Siwasaki#ifndef COMPRESS_POSTFIX 46100966Siwasaki#define COMPRESS_POSTFIX ".Z" 47100966Siwasaki#endif 48100966Siwasaki 49100966Siwasaki#include <ctype.h> 50100966Siwasaki#include <err.h> 51100966Siwasaki#include <fcntl.h> 52100966Siwasaki#include <grp.h> 53100966Siwasaki#include <pwd.h> 54100966Siwasaki#include <signal.h> 55100966Siwasaki#include <stdio.h> 56100966Siwasaki#include <stdlib.h> 57100966Siwasaki#include <string.h> 58100966Siwasaki#include <unistd.h> 59100966Siwasaki#include <sys/types.h> 60100966Siwasaki#include <sys/time.h> 61100966Siwasaki#include <sys/stat.h> 62100966Siwasaki#include <sys/param.h> 63100966Siwasaki#include <sys/wait.h> 64100966Siwasaki 65100966Siwasaki#define kbytes(size) (((size) + 1023) >> 10) 66100966Siwasaki#ifdef _IBMR2 67100966Siwasaki/* Calculates (db * DEV_BSIZE) */ 68100966Siwasaki#define dbtob(db) ((unsigned)(db) << UBSHIFT) 69100966Siwasaki#endif 70100966Siwasaki 71100966Siwasaki#define CE_COMPACT 1 /* Compact the achived log files */ 72100966Siwasaki#define CE_BINARY 2 /* Logfile is in binary, don't add */ 73100966Siwasaki /* status messages */ 74100966Siwasaki#define NONE -1 75100966Siwasaki 76100966Siwasakistruct conf_entry { 77100966Siwasaki char *log; /* Name of the log */ 78100966Siwasaki char *pid_file; /* PID file */ 79100966Siwasaki int uid; /* Owner of log */ 80100966Siwasaki int gid; /* Group of log */ 81100966Siwasaki int numlogs; /* Number of logs to keep */ 82100966Siwasaki int size; /* Size cutoff to trigger trimming the log */ 83100966Siwasaki int hours; /* Hours between log trimming */ 84100966Siwasaki int permissions; /* File permissions on the log */ 85100966Siwasaki int flags; /* Flags (CE_COMPACT & CE_BINARY) */ 86100966Siwasaki struct conf_entry *next; /* Linked list pointer */ 87100966Siwasaki}; 88100966Siwasaki 89100966Siwasakiint verbose = 0; /* Print out what's going on */ 90100966Siwasakiint needroot = 1; /* Root privs are necessary */ 91100966Siwasakiint noaction = 0; /* Don't do anything, just show it */ 92100966Siwasakichar *conf = CONF; /* Configuration file to use */ 93100966Siwasakitime_t timenow; 94100966Siwasakipid_t syslog_pid; /* read in from /etc/syslog.pid */ 95100966Siwasaki#define MIN_PID 5 96100966Siwasaki#define MAX_PID 30000 /* was 65534, see /usr/include/sys/proc.h */ 97100966Siwasakichar hostname[MAXHOSTNAMELEN+1]; /* hostname */ 98100966Siwasakichar *daytime; /* timenow in human readable form */ 99100966Siwasaki 100100966Siwasaki#ifndef OSF 101100966Siwasakichar *strdup(char *strp); 102100966Siwasaki#endif 103100966Siwasaki 104100966Siwasakistatic struct conf_entry *parse_file(); 105100966Siwasakistatic char *sob(char *p); 106100966Siwasakistatic char *son(char *p); 107100966Siwasakistatic char *missing_field(char *p,char *errline); 108100966Siwasakistatic void do_entry(struct conf_entry *ent); 109100966Siwasakistatic void PRS(int argc,char **argv); 110100966Siwasakistatic void usage(); 111100966Siwasakistatic void dotrim(char *log,char *pid_file,int numdays,int falgs,int perm, int owner_uid,int group_gid); 112100966Siwasakistatic int log_trim(char *log); 113100966Siwasakistatic void compress_log(char *log); 114100966Siwasakistatic int sizefile(char *file); 115100966Siwasakistatic int age_old_log(char *file); 116100966Siwasakistatic pid_t get_pid(char *pid_file); 117100966Siwasaki 118167802Sjkimint main(argc,argv) 119100966Siwasaki int argc; 120100966Siwasaki char **argv; 121100966Siwasaki{ 122100966Siwasaki struct conf_entry *p, *q; 123100966Siwasaki 124167802Sjkim PRS(argc,argv); 125167802Sjkim if (needroot && getuid() && geteuid()) 126167802Sjkim errx(1, "must have root privs"); 127167802Sjkim p = q = parse_file(); 128167802Sjkim 129167802Sjkim syslog_pid = needroot ? get_pid(PIDFILE) : 0; 130167802Sjkim 131167802Sjkim while (p) { 132167802Sjkim do_entry(p); 133167802Sjkim p=p->next; 134167802Sjkim free((char *) q); 135167802Sjkim q=p; 136167802Sjkim } 137167802Sjkim return(0); 138167802Sjkim} 139167802Sjkim 140167802Sjkimstatic void do_entry(ent) 141167802Sjkim struct conf_entry *ent; 142167802Sjkim 143167802Sjkim{ 144167802Sjkim int size, modtime; 145167802Sjkim 146167802Sjkim if (verbose) { 147167802Sjkim if (ent->flags & CE_COMPACT) 148167802Sjkim printf("%s <%dZ>: ",ent->log,ent->numlogs); 149167802Sjkim else 150167802Sjkim printf("%s <%d>: ",ent->log,ent->numlogs); 151167802Sjkim } 152167802Sjkim size = sizefile(ent->log); 153167802Sjkim modtime = age_old_log(ent->log); 154167802Sjkim if (size < 0) { 155167802Sjkim if (verbose) 156167802Sjkim printf("does not exist.\n"); 157167802Sjkim } else { 158100966Siwasaki if (verbose && (ent->size > 0)) 159100966Siwasaki printf("size (Kb): %d [%d] ", size, ent->size); 160100966Siwasaki if (verbose && (ent->hours > 0)) 161100966Siwasaki printf(" age (hr): %d [%d] ", modtime, ent->hours); 162100966Siwasaki if (((ent->size > 0) && (size >= ent->size)) || 163100966Siwasaki ((ent->hours > 0) && ((modtime >= ent->hours) 164100966Siwasaki || (modtime < 0)))) { 165100966Siwasaki if (verbose) 166100966Siwasaki printf("--> trimming log....\n"); 167100966Siwasaki if (noaction && !verbose) { 168100966Siwasaki if (ent->flags & CE_COMPACT) 169100966Siwasaki printf("%s <%dZ>: trimming", 170100966Siwasaki ent->log,ent->numlogs); 171100966Siwasaki else 172100966Siwasaki printf("%s <%d>: trimming", 173167802Sjkim ent->log,ent->numlogs); 174167802Sjkim } 175167802Sjkim dotrim(ent->log, ent->pid_file, ent->numlogs, 176100966Siwasaki ent->flags, ent->permissions, ent->uid, ent->gid); 177100966Siwasaki } else { 178100966Siwasaki if (verbose) 179100966Siwasaki printf("--> skipping\n"); 180167802Sjkim } 181167802Sjkim } 182167802Sjkim} 183167802Sjkim 184167802Sjkimstatic void PRS(argc,argv) 185100966Siwasaki int argc; 186100966Siwasaki char **argv; 187100966Siwasaki{ 188138287Smarks int c; 189151937Sjkim char *p; 190100966Siwasaki 191100966Siwasaki timenow = time((time_t *) 0); 192100966Siwasaki daytime = ctime(&timenow) + 4; 193151937Sjkim daytime[15] = '\0'; 194151937Sjkim 195151937Sjkim /* Let's get our hostname */ 196151937Sjkim (void) gethostname(hostname, sizeof(hostname)); 197167802Sjkim 198151937Sjkim /* Truncate domain */ 199151937Sjkim if ((p = strchr(hostname, '.'))) { 200100966Siwasaki *p = '\0'; 201151937Sjkim } 202151937Sjkim 203151937Sjkim optind = 1; /* Start options parsing */ 204151937Sjkim while ((c=getopt(argc,argv,"nrvf:t:")) != -1) 205151937Sjkim switch (c) { 206151937Sjkim case 'n': 207151937Sjkim noaction++; /* This implies needroot as off */ 208151937Sjkim /* fall through */ 209167802Sjkim case 'r': 210167802Sjkim needroot = 0; 211100966Siwasaki break; 212151937Sjkim case 'v': 213100966Siwasaki verbose++; 214100966Siwasaki break; 215151937Sjkim case 'f': 216100966Siwasaki conf = optarg; 217151937Sjkim break; 218167802Sjkim default: 219100966Siwasaki usage(); 220151937Sjkim } 221100966Siwasaki } 222100966Siwasaki 223151937Sjkimstatic void usage() 224100966Siwasaki{ 225151937Sjkim fprintf(stderr, "usage: newsyslog [-nrv] [-f config-file]\n"); 226167802Sjkim exit(1); 227167802Sjkim} 228100966Siwasaki 229151937Sjkim/* Parse a configuration file and return a linked list of all the logs 230100966Siwasaki * to process 231100966Siwasaki */ 232151937Sjkimstatic struct conf_entry *parse_file() 233100966Siwasaki{ 234151937Sjkim FILE *f; 235167802Sjkim char line[BUFSIZ], *parse, *q; 236100966Siwasaki char *errline, *group; 237151937Sjkim struct conf_entry *first = NULL; 238100966Siwasaki struct conf_entry *working = NULL; 239100966Siwasaki struct passwd *pass; 240151937Sjkim struct group *grp; 241100966Siwasaki int eol; 242151937Sjkim 243100966Siwasaki if (strcmp(conf,"-")) 244151937Sjkim f = fopen(conf,"r"); 245100966Siwasaki else 246100966Siwasaki f = stdin; 247151937Sjkim if (!f) 248100966Siwasaki err(1, "%s", conf); 249151937Sjkim while (fgets(line,BUFSIZ,f)) { 250100966Siwasaki if ((line[0]== '\n') || (line[0] == '#')) 251151937Sjkim continue; 252100966Siwasaki errline = strdup(line); 253100966Siwasaki if (!first) { 254151937Sjkim working = (struct conf_entry *) malloc(sizeof(struct conf_entry)); 255100966Siwasaki first = working; 256151937Sjkim } else { 257167802Sjkim working->next = (struct conf_entry *) malloc(sizeof(struct conf_entry)); 258167802Sjkim working = working->next; 259167802Sjkim } 260167802Sjkim 261167802Sjkim q = parse = missing_field(sob(line),errline); 262100966Siwasaki parse = son(line); 263151937Sjkim if (!*parse) 264100966Siwasaki errx(1, "malformed line (missing fields):\n%s", errline); 265100966Siwasaki *parse = '\0'; 266151937Sjkim working->log = strdup(q); 267100966Siwasaki 268151937Sjkim q = parse = missing_field(sob(++parse),errline); 269167802Sjkim parse = son(parse); 270167802Sjkim if (!*parse) 271100966Siwasaki errx(1, "malformed line (missing fields):\n%s", errline); 272151937Sjkim *parse = '\0'; 273100966Siwasaki if ((group = strchr(q, '.')) != NULL) { 274100966Siwasaki *group++ = '\0'; 275151937Sjkim if (*q) { 276100966Siwasaki if (!(isnumber(*q))) { 277151937Sjkim if ((pass = getpwnam(q)) == NULL) 278100966Siwasaki errx(1, 279151937Sjkim "error in config file; unknown user:\n%s", 280100966Siwasaki errline); 281100966Siwasaki working->uid = pass->pw_uid; 282151937Sjkim } else 283100966Siwasaki working->uid = atoi(q); 284151937Sjkim } else 285167802Sjkim working->uid = NONE; 286100966Siwasaki 287151937Sjkim q = group; 288100966Siwasaki if (*q) { 289100966Siwasaki if (!(isnumber(*q))) { 290151937Sjkim if ((grp = getgrnam(q)) == NULL) 291151937Sjkim errx(1, 292151937Sjkim "error in config file; unknown group:\n%s", 293151937Sjkim errline); 294167802Sjkim working->gid = grp->gr_gid; 295167802Sjkim } else 296100966Siwasaki working->gid = atoi(q); 297151937Sjkim } else 298100966Siwasaki working->gid = NONE; 299151937Sjkim 300151937Sjkim q = parse = missing_field(sob(++parse),errline); 301151937Sjkim parse = son(parse); 302151937Sjkim if (!*parse) 303151937Sjkim errx(1, "malformed line (missing fields):\n%s", errline); 304151937Sjkim *parse = '\0'; 305151937Sjkim } 306151937Sjkim else 307167802Sjkim working->uid = working->gid = NONE; 308167802Sjkim 309167802Sjkim if (!sscanf(q,"%o",&working->permissions)) 310167802Sjkim errx(1, "error in config file; bad permissions:\n%s", 311167802Sjkim errline); 312100966Siwasaki 313151937Sjkim q = parse = missing_field(sob(++parse),errline); 314100966Siwasaki parse = son(parse); 315100966Siwasaki if (!*parse) 316151937Sjkim errx(1, "malformed line (missing fields):\n%s", errline); 317100966Siwasaki *parse = '\0'; 318151937Sjkim if (!sscanf(q,"%d",&working->numlogs)) 319100966Siwasaki errx(1, "error in config file; bad number:\n%s", 320151937Sjkim errline); 321100966Siwasaki 322100966Siwasaki q = parse = missing_field(sob(++parse),errline); 323151937Sjkim parse = son(parse); 324100966Siwasaki if (!*parse) 325151937Sjkim errx(1, "malformed line (missing fields):\n%s", errline); 326167802Sjkim *parse = '\0'; 327167802Sjkim if (isdigit(*q)) 328167802Sjkim working->size = atoi(q); 329167802Sjkim else 330167802Sjkim working->size = -1; 331100966Siwasaki 332151937Sjkim q = parse = missing_field(sob(++parse),errline); 333100966Siwasaki parse = son(parse); 334100966Siwasaki eol = !*parse; 335151937Sjkim *parse = '\0'; 336100966Siwasaki if (isdigit(*q)) 337151937Sjkim working->hours = atoi(q); 338167802Sjkim else 339167802Sjkim working->hours = -1; 340167802Sjkim 341100966Siwasaki if (eol) 342151937Sjkim q = NULL; 343100966Siwasaki else { 344100966Siwasaki q = parse = sob(++parse); /* Optional field */ 345151937Sjkim parse = son(parse); 346167802Sjkim if (!*parse) 347167802Sjkim eol = 1; 348167802Sjkim *parse = '\0'; 349151937Sjkim } 350151937Sjkim 351151937Sjkim working->flags = 0; 352100966Siwasaki while (q && *q && !isspace(*q)) { 353151937Sjkim if ((*q == 'Z') || (*q == 'z')) 354151937Sjkim working->flags |= CE_COMPACT; 355151937Sjkim else if ((*q == 'B') || (*q == 'b')) 356151937Sjkim working->flags |= CE_BINARY; 357151937Sjkim else if (*q != '-') 358151937Sjkim errx(1, "illegal flag in config file -- %c", *q); 359151937Sjkim q++; 360151937Sjkim } 361151937Sjkim 362151937Sjkim if (eol) 363167802Sjkim q = NULL; 364167802Sjkim else { 365167802Sjkim q = parse = sob(++parse); /* Optional field */ 366167802Sjkim *(parse = son(parse)) = '\0'; 367167802Sjkim } 368167802Sjkim 369167802Sjkim working->pid_file = NULL; 370167802Sjkim if (q && *q) { 371100966Siwasaki if (*q == '/') 372151937Sjkim working->pid_file = strdup(q); 373100966Siwasaki else 374151937Sjkim errx(1, "illegal pid file in config file:\n%s", q); 375100966Siwasaki } 376151937Sjkim 377151937Sjkim free(errline); 378100966Siwasaki } 379151937Sjkim if (working) 380151937Sjkim working->next = (struct conf_entry *) NULL; 381167802Sjkim (void) fclose(f); 382167802Sjkim return(first); 383167802Sjkim} 384167802Sjkim 385167802Sjkimstatic char *missing_field(p,errline) 386151937Sjkim char *p,*errline; 387151937Sjkim{ 388151937Sjkim if (!p || !*p) 389151937Sjkim errx(1, "missing field in config file:\n%s", errline); 390151937Sjkim return(p); 391151937Sjkim} 392151937Sjkim 393151937Sjkimstatic void dotrim(log,pid_file,numdays,flags,perm,owner_uid,group_gid) 394167802Sjkim char *log; 395167802Sjkim char *pid_file; 396167802Sjkim int numdays; 397167802Sjkim int flags; 398167802Sjkim int perm; 399100966Siwasaki int owner_uid; 400151937Sjkim int group_gid; 401100966Siwasaki{ 402100966Siwasaki char file1 [MAXPATHLEN+1], file2 [MAXPATHLEN+1]; 403151937Sjkim char zfile1[MAXPATHLEN+1], zfile2[MAXPATHLEN+1]; 404100966Siwasaki int notified, need_notification, fd, _numdays; 405151937Sjkim struct stat st; 406151937Sjkim pid_t pid; 407167802Sjkim 408167802Sjkim#ifdef _IBMR2 409167802Sjkim/* AIX 3.1 has a broken fchown- if the owner_uid is -1, it will actually */ 410167802Sjkim/* change it to be owned by uid -1, instead of leaving it as is, as it is */ 411167802Sjkim/* supposed to. */ 412100966Siwasaki if (owner_uid == -1) 413151937Sjkim owner_uid = geteuid(); 414100966Siwasaki#endif 415100966Siwasaki 416151937Sjkim /* Remove oldest log */ 417100966Siwasaki (void) sprintf(file1,"%s.%d",log,numdays); 418151937Sjkim (void) strcpy(zfile1, file1); 419167802Sjkim (void) strcat(zfile1, COMPRESS_POSTFIX); 420167802Sjkim 421167802Sjkim if (noaction) { 422100966Siwasaki printf("rm -f %s\n", file1); 423100966Siwasaki printf("rm -f %s\n", zfile1); 424151937Sjkim } else { 425100966Siwasaki (void) unlink(file1); 426100966Siwasaki (void) unlink(zfile1); 427151937Sjkim } 428100966Siwasaki 429151937Sjkim /* Move down log files */ 430167802Sjkim _numdays = numdays; /* preserve */ 431167802Sjkim while (numdays--) { 432167802Sjkim (void) strcpy(file2,file1); 433167802Sjkim (void) sprintf(file1,"%s.%d",log,numdays); 434167802Sjkim (void) strcpy(zfile1, file1); 435100966Siwasaki (void) strcpy(zfile2, file2); 436151937Sjkim if (lstat(file1, &st)) { 437100966Siwasaki (void) strcat(zfile1, COMPRESS_POSTFIX); 438100966Siwasaki (void) strcat(zfile2, COMPRESS_POSTFIX); 439100966Siwasaki if (lstat(zfile1, &st)) continue; 440100966Siwasaki } 441100966Siwasaki if (noaction) { 442138287Smarks printf("mv %s %s\n",zfile1,zfile2); 443100966Siwasaki printf("chmod %o %s\n", perm, zfile2); 444151937Sjkim printf("chown %d.%d %s\n", 445100966Siwasaki owner_uid, group_gid, zfile2); 446151937Sjkim } else { 447100966Siwasaki (void) rename(zfile1, zfile2); 448167802Sjkim (void) chmod(zfile2, perm); 449167802Sjkim (void) chown(zfile2, owner_uid, group_gid); 450167802Sjkim } 451100966Siwasaki } 452151937Sjkim if (!noaction && !(flags & CE_BINARY)) 453100966Siwasaki (void) log_trim(log); /* Report the trimming to the old log */ 454167802Sjkim 455167802Sjkim if (!_numdays) { 456167802Sjkim if (noaction) 457167802Sjkim printf("rm %s\n",log); 458167802Sjkim else 459167802Sjkim (void)unlink(log); 460167802Sjkim } 461167802Sjkim else { 462100966Siwasaki if (noaction) 463151937Sjkim printf("mv %s to %s\n",log,file1); 464151937Sjkim else 465167802Sjkim (void)rename(log, file1); 466167802Sjkim } 467167802Sjkim 468167802Sjkim if (noaction) 469167802Sjkim printf("Start new log..."); 470167802Sjkim else { 471167802Sjkim fd = creat(log,perm); 472167802Sjkim if (fd < 0) 473167802Sjkim err(1, "can't start new log"); 474167802Sjkim if (fchown(fd, owner_uid, group_gid)) 475151937Sjkim err(1, "can't chmod new log file"); 476151937Sjkim (void) close(fd); 477151937Sjkim if (!(flags & CE_BINARY)) 478167802Sjkim if (log_trim(log)) /* Add status message */ 479167802Sjkim err(1, "can't add status message to log"); 480167802Sjkim } 481167802Sjkim if (noaction) 482151937Sjkim printf("chmod %o %s...",perm,log); 483151937Sjkim else 484151937Sjkim (void) chmod(log,perm); 485100966Siwasaki 486100966Siwasaki pid = 0; 487 need_notification = notified = 0; 488 if (pid_file != NULL) { 489 need_notification = 1; 490 pid = get_pid(pid_file); 491 } else if (needroot && !(flags & CE_BINARY)) { 492 need_notification = 1; 493 pid = syslog_pid; 494 } 495 496 if (pid) { 497 if (noaction) { 498 notified = 1; 499 printf("kill -HUP %d\n", (int)pid); 500 } else if (kill(pid,SIGHUP)) 501 warn("can't notify daemon, pid %d", (int)pid); 502 else { 503 notified = 1; 504 if (verbose) 505 printf("daemon pid %d notified\n", (int)pid); 506 } 507 } 508 509 if ((flags & CE_COMPACT)) { 510 if (need_notification && !notified) 511 warnx("log not compressed because daemon not notified"); 512 else if (noaction) 513 printf("Compress %s.0\n",log); 514 else { 515 if (notified) { 516 if (verbose) 517 printf("small pause to allow daemon to close log\n"); 518 sleep(3); 519 } 520 compress_log(log); 521 } 522 } 523} 524 525/* Log the fact that the logs were turned over */ 526static int log_trim(log) 527 char *log; 528{ 529 FILE *f; 530 if ((f = fopen(log,"a")) == NULL) 531 return(-1); 532 fprintf(f,"%s %s newsyslog[%d]: logfile turned over\n", 533 daytime, hostname, (int)getpid()); 534 if (fclose(f) == EOF) 535 err(1, "log_trim: fclose:"); 536 return(0); 537} 538 539/* Fork of /usr/ucb/compress to compress the old log file */ 540static void compress_log(log) 541 char *log; 542{ 543 pid_t pid; 544 char tmp[MAXPATHLEN+1]; 545 546 (void) sprintf(tmp,"%s.0",log); 547 pid = fork(); 548 if (pid < 0) 549 err(1, "fork"); 550 else if (!pid) { 551 (void) execl(COMPRESS_PATH,COMPRESS_PROG,"-f",tmp,0); 552 err(1, COMPRESS_PATH); 553 } 554} 555 556/* Return size in kilobytes of a file */ 557static int sizefile(file) 558 char *file; 559{ 560 struct stat sb; 561 562 if (stat(file,&sb) < 0) 563 return(-1); 564 return(kbytes(dbtob(sb.st_blocks))); 565} 566 567/* Return the age of old log file (file.0) */ 568static int age_old_log(file) 569 char *file; 570{ 571 struct stat sb; 572 char tmp[MAXPATHLEN+sizeof(".0")+sizeof(COMPRESS_POSTFIX)+1]; 573 574 (void) strcpy(tmp,file); 575 if (stat(strcat(tmp,".0"),&sb) < 0) 576 if (stat(strcat(tmp,COMPRESS_POSTFIX), &sb) < 0) 577 return(-1); 578 return( (int) (timenow - sb.st_mtime + 1800) / 3600); 579} 580 581static pid_t get_pid(pid_file) 582 char *pid_file; 583{ 584 FILE *f; 585 char line[BUFSIZ]; 586 pid_t pid = 0; 587 588 if ((f = fopen(pid_file,"r")) == NULL) 589 warn("can't open %s pid file to restart a daemon", 590 pid_file); 591 else { 592 if (fgets(line,BUFSIZ,f)) { 593 pid = atol(line); 594 if (pid < MIN_PID || pid > MAX_PID) { 595 warnx("preposterous process number: %d", (int)pid); 596 pid = 0; 597 } 598 } else 599 warn("can't read %s pid file to restart a daemon", 600 pid_file); 601 (void)fclose(f); 602 } 603 return pid; 604} 605 606#ifndef OSF 607/* Duplicate a string using malloc */ 608 609char *strdup(strp) 610register char *strp; 611{ 612 register char *cp; 613 614 if ((cp = malloc((unsigned) strlen(strp) + 1)) == NULL) 615 abort(); 616 return(strcpy (cp, strp)); 617} 618#endif 619 620/* Skip Over Blanks */ 621char *sob(p) 622 register char *p; 623{ 624 while (p && *p && isspace(*p)) 625 p++; 626 return(p); 627} 628 629/* Skip Over Non-Blanks */ 630char *son(p) 631 register char *p; 632{ 633 while (p && *p && !isspace(*p)) 634 p++; 635 return(p); 636} 637