[BACK]Return to newsyslog.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / newsyslog

Annotation of src/usr.bin/newsyslog/newsyslog.c, Revision 1.10

1.10    ! downsj      1: /*     $OpenBSD: newsyslog.c,v 1.9 1997/04/27 13:48:55 downsj Exp $    */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1997, Jason Downs.  All rights reserved.
        !             5:  *
        !             6:  * Redistribution and use in source and binary forms, with or without
        !             7:  * modification, are permitted provided that the following conditions
        !             8:  * are met:
        !             9:  * 1. Redistributions of source code must retain the above copyright
        !            10:  *    notice, this list of conditions and the following disclaimer.
        !            11:  * 2. Redistributions in binary form must reproduce the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer in the
        !            13:  *    documentation and/or other materials provided with the distribution.
        !            14:  * 3. All advertising materials mentioning features or use of this software
        !            15:  *    must display the following acknowledgement:
        !            16:  *      This product includes software developed by Jason Downs for the
        !            17:  *      OpenBSD system.
        !            18:  * 4. Neither the name(s) of the author(s) nor the name OpenBSD
        !            19:  *    may be used to endorse or promote products derived from this software
        !            20:  *    without specific prior written permission.
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
        !            23:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            24:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            25:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
        !            26:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            27:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            28:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
        !            29:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            32:  * SUCH DAMAGE.
        !            33:  */
1.3       deraadt    34:
1.1       deraadt    35: /*
                     36:  * This file contains changes from the Open Software Foundation.
                     37:  */
                     38:
                     39: /*
                     40:
                     41: Copyright 1988, 1989 by the Massachusetts Institute of Technology
                     42:
                     43: Permission to use, copy, modify, and distribute this software
                     44: and its documentation for any purpose and without fee is
                     45: hereby granted, provided that the above copyright notice
                     46: appear in all copies and that both that copyright notice and
                     47: this permission notice appear in supporting documentation,
                     48: and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
                     49: used in advertising or publicity pertaining to distribution
                     50: of the software without specific, written prior permission.
                     51: M.I.T. and the M.I.T. S.I.P.B. make no representations about
                     52: the suitability of this software for any purpose.  It is
                     53: provided "as is" without express or implied warranty.
                     54:
                     55: */
                     56:
                     57: /*
                     58:  *      newsyslog - roll over selected logs at the appropriate time,
                     59:  *              keeping the a specified number of backup files around.
                     60:  *
                     61:  */
                     62:
                     63: #ifndef lint
1.10    ! downsj     64: static char rcsid[] = "$OpenBSD: newsyslog.c,v 1.9 1997/04/27 13:48:55 downsj Exp $";
1.1       deraadt    65: #endif /* not lint */
                     66:
                     67: #ifndef CONF
                     68: #define CONF "/etc/athena/newsyslog.conf" /* Configuration file */
                     69: #endif
                     70: #ifndef PIDFILE
                     71: #define PIDFILE "/etc/syslog.pid"
                     72: #endif
                     73: #ifndef COMPRESS
                     74: #define COMPRESS "/usr/ucb/compress" /* File compression program */
                     75: #endif
                     76: #ifndef COMPRESS_POSTFIX
                     77: #define COMPRESS_POSTFIX ".Z"
                     78: #endif
1.10    ! downsj     79: #ifndef STATS_DIR
        !            80: #define STATS_DIR "/etc"
        !            81: #endif
        !            82: #ifndef SENDMAIL
        !            83: #define SENDMAIL "/usr/lib/sendmail"
        !            84: #endif
1.1       deraadt    85:
                     86: #include <stdio.h>
1.9       downsj     87: #include <sys/types.h>
                     88: #include <sys/time.h>
                     89: #include <sys/stat.h>
                     90: #include <sys/param.h>
                     91: #include <sys/wait.h>
1.1       deraadt    92: #include <stdlib.h>
                     93: #include <string.h>
                     94: #include <ctype.h>
                     95: #include <signal.h>
1.9       downsj     96: #include <fcntl.h>
1.1       deraadt    97: #include <pwd.h>
                     98: #include <grp.h>
1.9       downsj     99: #include <unistd.h>
1.1       deraadt   100:
                    101: #define kbytes(size)  (((size) + 1023) >> 10)
                    102:
1.10    ! downsj    103: #define CE_COMPACT     0x01            /* Compact the achived log files */
        !           104: #define CE_BINARY      0x02            /* Logfile is in binary, don't add */
        !           105:                                        /* status messages */
        !           106: #define CE_MONITOR     0x04            /* Monitory for changes */
1.1       deraadt   107: #define NONE -1
                    108:
                    109: struct conf_entry {
                    110:         char    *log;           /* Name of the log */
                    111:         int     uid;            /* Owner of log */
                    112:         int     gid;            /* Group of log */
                    113:         int     numlogs;        /* Number of logs to keep */
                    114:         int     size;           /* Size cutoff to trigger trimming the log */
                    115:         int     hours;          /* Hours between log trimming */
                    116:         int     permissions;    /* File permissions on the log */
                    117:         int     flags;          /* Flags (CE_COMPACT & CE_BINARY)  */
1.10    ! downsj    118:        char    *whom;          /* Whom to notify if logfile changes */
1.1       deraadt   119:         struct conf_entry       *next; /* Linked list pointer */
                    120: };
                    121:
                    122: char    *progname;              /* contains argv[0] */
                    123: int     verbose = 0;            /* Print out what's going on */
                    124: int     needroot = 1;           /* Root privs are necessary */
                    125: int     noaction = 0;           /* Don't do anything, just show it */
1.10    ! downsj    126: int    monitor = 0;            /* Don't do monitoring by default */
1.1       deraadt   127: char    *conf = CONF;           /* Configuration file to use */
                    128: time_t  timenow;
                    129: int     syslog_pid;             /* read in from /etc/syslog.pid */
                    130: #define MIN_PID                3
                    131: #define MAX_PID                65534
1.7       deraadt   132: char    hostname[MAXHOSTNAMELEN]; /* hostname */
1.1       deraadt   133: char    *daytime;               /* timenow in human readable form */
                    134:
                    135:
1.9       downsj    136: void do_entry __P((struct conf_entry *));
                    137: void PRS __P((int, char **));
                    138: void usage __P((void));
                    139: struct conf_entry *parse_file __P((void));
                    140: char *missing_field __P((char *, char *));
                    141: void dotrim __P((char *, int, int, int, int, int));
                    142: int log_trim __P((char *));
                    143: void compress_log __P((char *));
                    144: int sizefile __P((char *));
                    145: int age_old_log __P((char *));
                    146: char *sob __P((char *));
                    147: char *son __P((char *));
1.10    ! downsj    148: int isnumberstr __P((char *));
        !           149: void domonitor __P((char *, char *));
        !           150: FILE *openmail __P((void));
        !           151: void closemail __P((FILE *));
1.1       deraadt   152:
1.9       downsj    153: int main(argc, argv)
1.1       deraadt   154:         int argc;
                    155:         char **argv;
                    156: {
                    157:         struct conf_entry *p, *q;
                    158:
                    159:         PRS(argc,argv);
                    160:         if (needroot && getuid() && geteuid()) {
                    161:                 fprintf(stderr,"%s: must have root privs\n",progname);
                    162:                 exit(1);
                    163:         }
                    164:         p = q = parse_file();
                    165:         while (p) {
                    166:                 do_entry(p);
                    167:                 p=p->next;
                    168:                 free((char *) q);
                    169:                 q=p;
                    170:         }
                    171:         exit(0);
                    172: }
                    173:
1.9       downsj    174: void do_entry(ent)
1.1       deraadt   175:         struct conf_entry       *ent;
                    176:
                    177: {
                    178:         int     size, modtime;
                    179:
                    180:         if (verbose) {
                    181:                 if (ent->flags & CE_COMPACT)
                    182:                         printf("%s <%dZ>: ",ent->log,ent->numlogs);
                    183:                 else
                    184:                         printf("%s <%d>: ",ent->log,ent->numlogs);
                    185:         }
                    186:         size = sizefile(ent->log);
                    187:         modtime = age_old_log(ent->log);
                    188:         if (size < 0) {
                    189:                 if (verbose)
                    190:                         printf("does not exist.\n");
                    191:         } else {
                    192:                 if (verbose && (ent->size > 0))
                    193:                         printf("size (Kb): %d [%d] ", size, ent->size);
                    194:                 if (verbose && (ent->hours > 0))
                    195:                         printf(" age (hr): %d [%d] ", modtime, ent->hours);
1.10    ! downsj    196:                if (monitor && ent->flags & CE_MONITOR)
        !           197:                        domonitor(ent->log, ent->whom);
        !           198:                 if (!monitor && ((ent->size > 0) && (size >= ent->size)) ||
1.1       deraadt   199:                     ((ent->hours > 0) && ((modtime >= ent->hours)
                    200:                                         || (modtime < 0)))) {
                    201:                         if (verbose)
                    202:                                 printf("--> trimming log....\n");
                    203:                         if (noaction && !verbose) {
                    204:                                 if (ent->flags & CE_COMPACT)
                    205:                                         printf("%s <%dZ>: trimming",
                    206:                                                ent->log,ent->numlogs);
                    207:                                 else
                    208:                                         printf("%s <%d>: trimming",
                    209:                                                ent->log,ent->numlogs);
                    210:                         }
                    211:                         dotrim(ent->log, ent->numlogs, ent->flags,
                    212:                                ent->permissions, ent->uid, ent->gid);
                    213:                 } else {
                    214:                         if (verbose)
                    215:                                 printf("--> skipping\n");
                    216:                 }
                    217:         }
                    218: }
                    219:
1.9       downsj    220: void PRS(argc, argv)
1.1       deraadt   221:         int argc;
                    222:         char **argv;
                    223: {
                    224:         int     c;
                    225:         FILE    *f;
                    226:         char    line[BUFSIZ];
                    227:        char    *p;
                    228:
                    229:         progname = argv[0];
                    230:         timenow = time((time_t *) 0);
                    231:         daytime = ctime(&timenow) + 4;
1.2       deraadt   232:         daytime[15] = '\0';
1.1       deraadt   233:
                    234:         /* Let's find the pid of syslogd */
                    235:         syslog_pid = 0;
                    236:         f = fopen(PIDFILE,"r");
                    237:         if (f && fgets(line,BUFSIZ,f))
                    238:                 syslog_pid = atoi(line);
                    239:        if (f)
                    240:                (void)fclose(f);
                    241:
                    242:         /* Let's get our hostname */
                    243:         (void) gethostname(hostname, sizeof(hostname));
                    244:
                    245:        /* Truncate domain */
1.9       downsj    246:        p = strchr(hostname, '.');
                    247:        if (p)
1.1       deraadt   248:                *p = '\0';
                    249:
                    250:         optind = 1;             /* Start options parsing */
1.10    ! downsj    251:         while ((c = getopt(argc,argv,"nrvmf:t:")) != -1) {
1.1       deraadt   252:                 switch (c) {
                    253:                 case 'n':
                    254:                         noaction++; /* This implies needroot as off */
                    255:                         /* fall through */
                    256:                 case 'r':
                    257:                         needroot = 0;
                    258:                         break;
                    259:                 case 'v':
                    260:                         verbose++;
                    261:                         break;
                    262:                 case 'f':
                    263:                         conf = optarg;
                    264:                         break;
1.10    ! downsj    265:                case 'm':
        !           266:                        monitor++;
        !           267:                        break;
1.1       deraadt   268:                 default:
                    269:                         usage();
                    270:                 }
                    271:         }
1.9       downsj    272: }
1.1       deraadt   273:
1.9       downsj    274: void usage()
1.1       deraadt   275: {
                    276:         fprintf(stderr,
                    277:                 "Usage: %s <-nrv> <-f config-file>\n", progname);
                    278:         exit(1);
                    279: }
                    280:
                    281: /* Parse a configuration file and return a linked list of all the logs
                    282:  * to process
                    283:  */
                    284: struct conf_entry *parse_file()
                    285: {
                    286:         FILE    *f;
                    287:         char    line[BUFSIZ], *parse, *q;
                    288:         char    *errline, *group;
                    289:         struct conf_entry *first = NULL;
                    290:         struct conf_entry *working;
                    291:         struct passwd *pass;
                    292:         struct group *grp;
                    293:
                    294:         if (strcmp(conf,"-"))
                    295:                 f = fopen(conf,"r");
                    296:         else
                    297:                 f = stdin;
                    298:         if (!f) {
                    299:                 (void) fprintf(stderr,"%s: ",progname);
                    300:                 perror(conf);
                    301:                 exit(1);
                    302:         }
                    303:         while (fgets(line,BUFSIZ,f)) {
                    304:                 if ((line[0]== '\n') || (line[0] == '#'))
                    305:                         continue;
                    306:                 errline = strdup(line);
1.10    ! downsj    307:                if (errline == NULL) {
        !           308:                        (void) fprintf(stderr,"%s: ",progname);
        !           309:                        perror("strdup()");
        !           310:                        exit(1);
        !           311:                }
1.1       deraadt   312:                 if (!first) {
                    313:                         working = (struct conf_entry *) malloc(sizeof(struct conf_entry));
1.10    ! downsj    314:                        if (working == NULL) {
        !           315:                                (void) fprintf(stderr,"%s: ",progname);
        !           316:                                perror("malloc()");
        !           317:                                exit(1);
        !           318:                        }
1.1       deraadt   319:                         first = working;
                    320:                 } else {
                    321:                         working->next = (struct conf_entry *) malloc(sizeof(struct conf_entry));
1.10    ! downsj    322:                        if (working->next == NULL) {
        !           323:                                (void) fprintf(stderr,"%s: ",progname);
        !           324:                                perror("malloc()");
        !           325:                                exit(1);
        !           326:                        }
1.1       deraadt   327:                         working = working->next;
                    328:                 }
                    329:
                    330:                 q = parse = missing_field(sob(line),errline);
                    331:                 *(parse = son(line)) = '\0';
                    332:                 working->log = strdup(q);
1.10    ! downsj    333:                if (working->log == NULL) {
        !           334:                        (void) fprintf(stderr,"%s: ",progname);
        !           335:                        perror("strdup()");
        !           336:                        exit(1);
        !           337:                }
1.1       deraadt   338:
                    339:                 q = parse = missing_field(sob(++parse),errline);
                    340:                 *(parse = son(parse)) = '\0';
                    341:                 if ((group = strchr(q, '.')) != NULL) {
                    342:                     *group++ = '\0';
                    343:                     if (*q) {
1.10    ! downsj    344:                         if (!(isnumberstr(q))) {
1.1       deraadt   345:                             if ((pass = getpwnam(q)) == NULL) {
                    346:                                 fprintf(stderr,
                    347:                                     "Error in config file; unknown user:\n");
                    348:                                 fputs(errline,stderr);
                    349:                                 exit(1);
                    350:                             }
                    351:                             working->uid = pass->pw_uid;
                    352:                         } else
                    353:                             working->uid = atoi(q);
                    354:                     } else
                    355:                         working->uid = NONE;
                    356:
                    357:                     q = group;
                    358:                     if (*q) {
1.10    ! downsj    359:                         if (!(isnumberstr(q))) {
1.1       deraadt   360:                             if ((grp = getgrnam(q)) == NULL) {
                    361:                                 fprintf(stderr,
                    362:                                     "Error in config file; unknown group:\n");
                    363:                                 fputs(errline,stderr);
                    364:                                 exit(1);
                    365:                             }
                    366:                             working->gid = grp->gr_gid;
                    367:                         } else
                    368:                             working->gid = atoi(q);
                    369:                     } else
                    370:                         working->gid = NONE;
                    371:
                    372:                     q = parse = missing_field(sob(++parse),errline);
                    373:                     *(parse = son(parse)) = '\0';
                    374:                 }
                    375:                 else
                    376:                     working->uid = working->gid = NONE;
                    377:
                    378:                 if (!sscanf(q,"%o",&working->permissions)) {
                    379:                         fprintf(stderr,
                    380:                                 "Error in config file; bad permissions:\n");
                    381:                         fputs(errline,stderr);
                    382:                         exit(1);
                    383:                 }
                    384:
                    385:                 q = parse = missing_field(sob(++parse),errline);
                    386:                 *(parse = son(parse)) = '\0';
                    387:                 if (!sscanf(q,"%d",&working->numlogs)) {
                    388:                         fprintf(stderr,
                    389:                                 "Error in config file; bad number:\n");
                    390:                         fputs(errline,stderr);
                    391:                         exit(1);
                    392:                 }
                    393:
                    394:                 q = parse = missing_field(sob(++parse),errline);
                    395:                 *(parse = son(parse)) = '\0';
                    396:                 if (isdigit(*q))
                    397:                         working->size = atoi(q);
                    398:                 else
                    399:                         working->size = -1;
                    400:
                    401:                 q = parse = missing_field(sob(++parse),errline);
                    402:                 *(parse = son(parse)) = '\0';
                    403:                 if (isdigit(*q))
                    404:                         working->hours = atoi(q);
                    405:                 else
                    406:                         working->hours = -1;
                    407:
                    408:                 q = parse = sob(++parse); /* Optional field */
                    409:                 *(parse = son(parse)) = '\0';
                    410:                 working->flags = 0;
                    411:                 while (q && *q && !isspace(*q)) {
                    412:                         if ((*q == 'Z') || (*q == 'z'))
                    413:                                 working->flags |= CE_COMPACT;
                    414:                         else if ((*q == 'B') || (*q == 'b'))
                    415:                                 working->flags |= CE_BINARY;
1.10    ! downsj    416:                        else if ((*q == 'M') || (*q == 'm'))
        !           417:                                working->flags |= CE_MONITOR;
1.1       deraadt   418:                         else {
                    419:                                 fprintf(stderr,
                    420:                                         "Illegal flag in config file -- %c\n",
                    421:                                         *q);
                    422:                                 exit(1);
                    423:                         }
                    424:                         q++;
                    425:                 }
1.10    ! downsj    426:
        !           427:                working->whom = NULL;
        !           428:                if (working->flags & CE_MONITOR) {      /* Optional field */
        !           429:                        q = parse = sob(++parse);
        !           430:                        *(parse = son(parse)) = '\0';
        !           431:
        !           432:                        working->whom = strdup(q);
        !           433:                        if (working->log == NULL) {
        !           434:                                (void) fprintf(stderr,"%s: ",progname);
        !           435:                                perror("strdup()");
        !           436:                                exit(1);
        !           437:                        }
        !           438:                }
1.1       deraadt   439:
                    440:                 free(errline);
                    441:         }
                    442:         if (working)
                    443:                 working->next = (struct conf_entry *) NULL;
                    444:         (void) fclose(f);
                    445:         return(first);
                    446: }
                    447:
1.9       downsj    448: char *missing_field(p, errline)
1.1       deraadt   449:         char    *p,*errline;
                    450: {
                    451:         if (!p || !*p) {
                    452:                 fprintf(stderr,"Missing field in config file:\n");
                    453:                 fputs(errline,stderr);
                    454:                 exit(1);
                    455:         }
                    456:         return(p);
                    457: }
                    458:
1.9       downsj    459: void dotrim(log, numdays, flags, perm, owner_uid, group_gid)
1.1       deraadt   460:         char    *log;
                    461:         int     numdays;
                    462:         int     flags;
                    463:         int     perm;
                    464:         int     owner_uid;
                    465:         int     group_gid;
                    466: {
1.7       deraadt   467:         char    file1[MAXPATHLEN], file2[MAXPATHLEN];
                    468:         char    zfile1[MAXPATHLEN], zfile2[MAXPATHLEN];
1.1       deraadt   469:         int     fd;
                    470:         struct  stat st;
1.6       tholo     471:        int     days = numdays;
1.1       deraadt   472:
                    473:         /* Remove oldest log */
                    474:         (void) sprintf(file1,"%s.%d",log,numdays);
                    475:         (void) strcpy(zfile1, file1);
                    476:         (void) strcat(zfile1, COMPRESS_POSTFIX);
                    477:
                    478:         if (noaction) {
                    479:                 printf("rm -f %s\n", file1);
                    480:                 printf("rm -f %s\n", zfile1);
                    481:         } else {
                    482:                 (void) unlink(file1);
                    483:                 (void) unlink(zfile1);
                    484:         }
                    485:
                    486:         /* Move down log files */
                    487:         while (numdays--) {
                    488:                 (void) strcpy(file2,file1);
                    489:                 (void) sprintf(file1,"%s.%d",log,numdays);
                    490:                 (void) strcpy(zfile1, file1);
                    491:                 (void) strcpy(zfile2, file2);
                    492:                 if (lstat(file1, &st)) {
                    493:                         (void) strcat(zfile1, COMPRESS_POSTFIX);
                    494:                         (void) strcat(zfile2, COMPRESS_POSTFIX);
                    495:                         if (lstat(zfile1, &st)) continue;
                    496:                 }
                    497:                 if (noaction) {
                    498:                         printf("mv %s %s\n",zfile1,zfile2);
                    499:                         printf("chmod %o %s\n", perm, zfile2);
                    500:                         printf("chown %d.%d %s\n",
                    501:                                owner_uid, group_gid, zfile2);
                    502:                 } else {
                    503:                         (void) rename(zfile1, zfile2);
                    504:                         (void) chmod(zfile2, perm);
                    505:                         (void) chown(zfile2, owner_uid, group_gid);
                    506:                 }
                    507:         }
                    508:         if (!noaction && !(flags & CE_BINARY))
                    509:                 (void) log_trim(log);  /* Report the trimming to the old log */
                    510:
1.6       tholo     511:        if (days == 0) {
1.5       deraadt   512:                if (noaction)
                    513:                        printf("rm %s\n",log);
                    514:                else
                    515:                        (void) unlink(log);
                    516:        } else {
                    517:                if (noaction)
                    518:                        printf("mv %s to %s\n",log,file1);
                    519:                else
                    520:                        (void) rename(log,file1);
                    521:        }
                    522:
1.1       deraadt   523:         if (noaction)
                    524:                 printf("Start new log...");
                    525:         else {
                    526:                 fd = creat(log,perm);
                    527:                 if (fd < 0) {
                    528:                         perror("can't start new log");
                    529:                         exit(1);
                    530:                 }
                    531:                 if (fchown(fd, owner_uid, group_gid)) {
                    532:                         perror("can't chmod new log file");
                    533:                         exit(1);
                    534:                 }
                    535:                 (void) close(fd);
                    536:                 if (!(flags & CE_BINARY))
                    537:                         if (log_trim(log)) {    /* Add status message */
                    538:                                 perror("can't add status message to log");
                    539:                                 exit(1);
                    540:                         }
                    541:         }
                    542:         if (noaction)
                    543:                 printf("chmod %o %s...",perm,log);
                    544:         else
                    545:                 (void) chmod(log,perm);
                    546:         if (noaction)
                    547:                 printf("kill -HUP %d (syslogd)\n",syslog_pid);
                    548:         else
                    549:        if (syslog_pid < MIN_PID || syslog_pid > MAX_PID) {
                    550:                fprintf(stderr,"%s: preposterous process number: %d\n",
                    551:                                progname, syslog_pid);
                    552:         } else if (kill(syslog_pid,SIGHUP)) {
                    553:                         fprintf(stderr,"%s: ",progname);
                    554:                         perror("warning - could not restart syslogd");
                    555:                 }
                    556:         if (flags & CE_COMPACT) {
                    557:                 if (noaction)
                    558:                         printf("Compress %s.0\n",log);
                    559:                 else
                    560:                         compress_log(log);
                    561:         }
                    562: }
                    563:
                    564: /* Log the fact that the logs were turned over */
1.9       downsj    565: int log_trim(log)
1.1       deraadt   566:         char    *log;
                    567: {
                    568:         FILE    *f;
                    569:         if ((f = fopen(log,"a")) == NULL)
                    570:                 return(-1);
                    571:         fprintf(f,"%s %s newsyslog[%d]: logfile turned over\n",
                    572:                 daytime, hostname, getpid());
                    573:         if (fclose(f) == EOF) {
                    574:                 perror("log_trim: fclose:");
                    575:                 exit(1);
                    576:         }
                    577:         return(0);
                    578: }
                    579:
                    580: /* Fork of /usr/ucb/compress to compress the old log file */
1.9       downsj    581: void compress_log(log)
1.1       deraadt   582:         char    *log;
                    583: {
                    584:         int     pid;
1.7       deraadt   585:         char    tmp[MAXPATHLEN];
1.1       deraadt   586:
                    587:         pid = fork();
                    588:         (void) sprintf(tmp,"%s.0",log);
                    589:         if (pid < 0) {
                    590:                 fprintf(stderr,"%s: ",progname);
                    591:                 perror("fork");
                    592:                 exit(1);
                    593:         } else if (!pid) {
                    594:                 (void) execl(COMPRESS,"compress","-f",tmp,0);
                    595:                 fprintf(stderr,"%s: ",progname);
                    596:                 perror(COMPRESS);
                    597:                 exit(1);
                    598:         }
                    599: }
                    600:
                    601: /* Return size in kilobytes of a file */
                    602: int sizefile(file)
                    603:         char    *file;
                    604: {
                    605:         struct stat sb;
                    606:
                    607:         if (stat(file,&sb) < 0)
                    608:                 return(-1);
                    609:         return(kbytes(dbtob(sb.st_blocks)));
                    610: }
                    611:
                    612: /* Return the age of old log file (file.0) */
                    613: int age_old_log(file)
                    614:         char    *file;
                    615: {
                    616:         struct stat sb;
1.7       deraadt   617:         char tmp[MAXPATHLEN];
1.1       deraadt   618:
                    619:         (void) strcpy(tmp,file);
                    620:         if (stat(strcat(tmp,".0"),&sb) < 0)
                    621:             if (stat(strcat(tmp,COMPRESS_POSTFIX), &sb) < 0)
                    622:                 return(-1);
                    623:         return( (int) (timenow - sb.st_mtime + 1800) / 3600);
                    624: }
                    625:
                    626: /* Skip Over Blanks */
                    627: char *sob(p)
                    628:         register char   *p;
                    629: {
                    630:         while (p && *p && isspace(*p))
                    631:                 p++;
                    632:         return(p);
                    633: }
                    634:
                    635: /* Skip Over Non-Blanks */
                    636: char *son(p)
                    637:         register char   *p;
                    638: {
                    639:         while (p && *p && !isspace(*p))
                    640:                 p++;
                    641:         return(p);
                    642: }
                    643:
                    644:
                    645: /* Check if string is actually a number */
                    646:
1.10    ! downsj    647: int isnumberstr(string)
        !           648:        char *string;
1.1       deraadt   649: {
                    650:         while (*string != '\0') {
1.9       downsj    651:             if (!isdigit(*string++))
                    652:                return(0);
1.1       deraadt   653:         }
                    654:         return(1);
1.10    ! downsj    655: }
        !           656:
        !           657: void domonitor(log, whom)
        !           658:        char *log, *whom;
        !           659: {
        !           660:        struct stat sb, tsb;
        !           661:        char *fname, *flog, *p, *rb = NULL;
        !           662:        FILE *fp;
        !           663:        off_t osize;
        !           664:        int rd;
        !           665:
        !           666:        if (stat(log, &sb) < 0)
        !           667:                return;
        !           668:
        !           669:        flog = strdup(log);
        !           670:        if (flog == NULL) {
        !           671:                (void) fprintf(stderr,"%s: ",progname);
        !           672:                perror("strdup()");
        !           673:                exit(1);
        !           674:        }
        !           675:        for (p = flog; *p != '\0'; p++) {
        !           676:                if (*p == '/')
        !           677:                        *p = '_';
        !           678:        }
        !           679:        fname = (char *) malloc(strlen(STATS_DIR) + strlen(flog) + 17);
        !           680:        if (fname == NULL) {
        !           681:                (void) fprintf(stderr,"%s: ",progname);
        !           682:                perror("malloc()");
        !           683:                exit(1);
        !           684:        }
        !           685:        sprintf(fname, "%s/newsyslog.%s.size", STATS_DIR, flog);
        !           686:
        !           687:        /* ..if it doesn't exist, simply record the current size. */
        !           688:        if ((sb.st_size == 0) || stat(fname, &tsb) < 0)
        !           689:                goto update;
        !           690:
        !           691:        fp = fopen(fname, "r");
        !           692:        if (fp == NULL) {
        !           693:                (void) fprintf(stderr,"%s: ",progname);
        !           694:                perror(fname);
        !           695:                goto cleanup;
        !           696:        }
        !           697: #ifdef QUAD_OFF_T
        !           698:        if (fscanf(fp, "%qd\n", &osize) != 1) {
        !           699: #else
        !           700:        if (fscanf(fp, "%ld\n", &osize) != 1) {
        !           701: #endif /* QUAD_OFF_T */
        !           702:                fclose(fp);
        !           703:                goto update;
        !           704:        }
        !           705:
        !           706:        fclose(fp);
        !           707:
        !           708:        /* If the file is smaller, mark the entire thing as changed. */
        !           709:        if (sb.st_size < osize)
        !           710:                osize = 0;
        !           711:
        !           712:        /* Now see if current size is larger. */
        !           713:        if (sb.st_size > osize) {
        !           714:                rb = (char *) malloc(sb.st_size - osize);
        !           715:                if (rb == NULL) {
        !           716:                        (void) fprintf(stderr,"%s: ",progname);
        !           717:                        perror("malloc()");
        !           718:                        exit(1);
        !           719:                }
        !           720:
        !           721:                /* Open logfile, seek. */
        !           722:                fp = fopen(log, "r");
        !           723:                if (fp == NULL) {
        !           724:                        (void) fprintf(stderr,"%s: ",progname);
        !           725:                        perror(log);
        !           726:                        goto cleanup;
        !           727:                }
        !           728:                fseek(fp, osize, SEEK_SET);
        !           729:                rd = fread(rb, 1, sb.st_size - osize, fp);
        !           730:                if (rd < 1) {
        !           731:                        (void) fprintf(stderr,"%s: ",progname);
        !           732:                        perror("fread()");
        !           733:                        fclose(fp);
        !           734:                        goto cleanup;
        !           735:                }
        !           736:
        !           737:                /* Send message. */
        !           738:                fclose(fp);
        !           739:
        !           740:                fp = openmail();
        !           741:                if (fp == NULL) {
        !           742:                        (void) fprintf(stderr,"%s: ",progname);
        !           743:                        perror("openmail()");
        !           744:                        goto cleanup;
        !           745:                }
        !           746:                fprintf(fp, "To: %s\nSubject: LOGFILE NOTIFICATION: %s\n\n\n",
        !           747:                    whom, log);
        !           748:                fwrite(rb, 1, rd, fp);
        !           749:                fputs("\n\n", fp);
        !           750:
        !           751:                closemail(fp);
        !           752:        }
        !           753: update:
        !           754:        /* Reopen for writing and update file. */
        !           755:        fp = fopen(fname, "w");
        !           756:        if (fp == NULL) {
        !           757:                (void) fprintf(stderr,"%s: ",progname);
        !           758:                perror(fname);
        !           759:                goto cleanup;
        !           760:        }
        !           761: #ifdef QUAD_OFF_T
        !           762:        fprintf(fp, "%qd\n", sb.st_size);
        !           763: #else
        !           764:        fprintf(fp, "%ld\n", sb.st_size);
        !           765: #endif /* QUAD_OFF_T */
        !           766:        fclose(fp);
        !           767:
        !           768: cleanup:
        !           769:        free(flog);
        !           770:        free(fname);
        !           771:        if (rb != NULL)
        !           772:                free(rb);
        !           773: }
        !           774:
        !           775: FILE *openmail()
        !           776: {
        !           777:        char *cmdbuf;
        !           778:        FILE *ret;
        !           779:
        !           780:        cmdbuf = (char *) malloc(strlen(SENDMAIL) + 3);
        !           781:        if (cmdbuf == NULL)
        !           782:                return(NULL);
        !           783:
        !           784:        sprintf(cmdbuf, "%s -t", SENDMAIL);
        !           785:        ret = popen(cmdbuf, "w");
        !           786:
        !           787:        free(cmdbuf);
        !           788:        return(ret);
        !           789: }
        !           790:
        !           791: void closemail(pfp)
        !           792:        FILE *pfp;
        !           793: {
        !           794:        pclose(pfp);
1.1       deraadt   795: }