Annotation of 43BSDReno/usr.sbin/syslogd/syslogd.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983, 1988 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted provided
                      6:  * that: (1) source distributions retain this entire copyright notice and
                      7:  * comment, and (2) distributions including binaries display the following
                      8:  * acknowledgement:  ``This product includes software developed by the
                      9:  * University of California, Berkeley and its contributors'' in the
                     10:  * documentation or other materials provided with the distribution and in
                     11:  * all advertising materials mentioning features or use of this software.
                     12:  * Neither the name of the University nor the names of its contributors may
                     13:  * be used to endorse or promote products derived from this software without
                     14:  * specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: char copyright[] =
                     22: "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
                     23:  All rights reserved.\n";
                     24: #endif /* not lint */
                     25: 
                     26: #ifndef lint
                     27: static char sccsid[] = "@(#)syslogd.c  5.42 (Berkeley) 6/29/90";
                     28: #endif /* not lint */
                     29: 
                     30: /*
                     31:  *  syslogd -- log system messages
                     32:  *
                     33:  * This program implements a system log. It takes a series of lines.
                     34:  * Each line may have a priority, signified as "<n>" as
                     35:  * the first characters of the line.  If this is
                     36:  * not present, a default priority is used.
                     37:  *
                     38:  * To kill syslogd, send a signal 15 (terminate).  A signal 1 (hup) will
                     39:  * cause it to reread its configuration file.
                     40:  *
                     41:  * Defined Constants:
                     42:  *
                     43:  * MAXLINE -- the maximimum line length that can be handled.
                     44:  * DEFUPRI -- the default priority for user messages
                     45:  * DEFSPRI -- the default priority for kernel messages
                     46:  *
                     47:  * Author: Eric Allman
                     48:  * extensive changes by Ralph Campbell
                     49:  * more extensive changes by Eric Allman (again)
                     50:  */
                     51: 
                     52: #define        MAXLINE         1024            /* maximum line length */
                     53: #define        MAXSVLINE       120             /* maximum saved line length */
                     54: #define DEFUPRI                (LOG_USER|LOG_NOTICE)
                     55: #define DEFSPRI                (LOG_KERN|LOG_CRIT)
                     56: #define TIMERINTVL     30              /* interval for checking flush, mark */
                     57: 
                     58: #include <sys/param.h>
                     59: #include <sys/errno.h>
                     60: #include <sys/ioctl.h>
                     61: #include <sys/stat.h>
                     62: #include <sys/wait.h>
                     63: #include <sys/socket.h>
                     64: #include <sys/file.h>
                     65: #include <sys/msgbuf.h>
                     66: #include <sys/uio.h>
                     67: #include <sys/un.h>
                     68: #include <sys/time.h>
                     69: #include <sys/resource.h>
                     70: #include <sys/signal.h>
                     71: 
                     72: #include <netinet/in.h>
                     73: #include <netdb.h>
                     74: 
                     75: #include <utmp.h>
                     76: #include <setjmp.h>
                     77: #include <stdio.h>
                     78: #include <ctype.h>
                     79: #include <string.h>
                     80: #include <unistd.h>
                     81: #include "pathnames.h"
                     82: 
                     83: #define SYSLOG_NAMES
                     84: #include <sys/syslog.h>
                     85: 
                     86: char   *LogName = _PATH_LOG;
                     87: char   *ConfFile = _PATH_LOGCONF;
                     88: char   *PidFile = _PATH_LOGPID;
                     89: char   ctty[] = _PATH_CONSOLE;
                     90: 
                     91: #define FDMASK(fd)     (1 << (fd))
                     92: 
                     93: #define        dprintf         if (Debug) printf
                     94: 
                     95: #define MAXUNAMES      20      /* maximum number of user names */
                     96: 
                     97: /*
                     98:  * Flags to logmsg().
                     99:  */
                    100: 
                    101: #define IGN_CONS       0x001   /* don't print on console */
                    102: #define SYNC_FILE      0x002   /* do fsync on file after printing */
                    103: #define ADDDATE                0x004   /* add a date to the message */
                    104: #define MARK           0x008   /* this message is a mark */
                    105: 
                    106: /*
                    107:  * This structure represents the files that will have log
                    108:  * copies printed.
                    109:  */
                    110: 
                    111: struct filed {
                    112:        struct  filed *f_next;          /* next in linked list */
                    113:        short   f_type;                 /* entry type, see below */
                    114:        short   f_file;                 /* file descriptor */
                    115:        time_t  f_time;                 /* time this was last written */
                    116:        u_char  f_pmask[LOG_NFACILITIES+1];     /* priority mask */
                    117:        union {
                    118:                char    f_uname[MAXUNAMES][UT_NAMESIZE+1];
                    119:                struct {
                    120:                        char    f_hname[MAXHOSTNAMELEN+1];
                    121:                        struct sockaddr_in      f_addr;
                    122:                } f_forw;               /* forwarding address */
                    123:                char    f_fname[MAXPATHLEN];
                    124:        } f_un;
                    125:        char    f_prevline[MAXSVLINE];          /* last message logged */
                    126:        char    f_lasttime[16];                 /* time of last occurrence */
                    127:        char    f_prevhost[MAXHOSTNAMELEN+1];   /* host from which recd. */
                    128:        int     f_prevpri;                      /* pri of f_prevline */
                    129:        int     f_prevlen;                      /* length of f_prevline */
                    130:        int     f_prevcount;                    /* repetition cnt of prevline */
                    131:        int     f_repeatcount;                  /* number of "repeated" msgs */
                    132: };
                    133: 
                    134: /*
                    135:  * Intervals at which we flush out "message repeated" messages,
                    136:  * in seconds after previous message is logged.  After each flush,
                    137:  * we move to the next interval until we reach the largest.
                    138:  */
                    139: int    repeatinterval[] = { 30, 120, 600 };    /* # of secs before flush */
                    140: #define        MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
                    141: #define        REPEATTIME(f)   ((f)->f_time + repeatinterval[(f)->f_repeatcount])
                    142: #define        BACKOFF(f)      { if (++(f)->f_repeatcount > MAXREPEAT) \
                    143:                                 (f)->f_repeatcount = MAXREPEAT; \
                    144:                        }
                    145: 
                    146: /* values for f_type */
                    147: #define F_UNUSED       0               /* unused entry */
                    148: #define F_FILE         1               /* regular file */
                    149: #define F_TTY          2               /* terminal */
                    150: #define F_CONSOLE      3               /* console terminal */
                    151: #define F_FORW         4               /* remote machine */
                    152: #define F_USERS                5               /* list of users */
                    153: #define F_WALL         6               /* everyone logged on */
                    154: 
                    155: char   *TypeNames[7] = {
                    156:        "UNUSED",       "FILE",         "TTY",          "CONSOLE",
                    157:        "FORW",         "USERS",        "WALL"
                    158: };
                    159: 
                    160: struct filed *Files;
                    161: struct filed consfile;
                    162: 
                    163: int    Debug;                  /* debug flag */
                    164: char   LocalHostName[MAXHOSTNAMELEN+1];        /* our hostname */
                    165: char   *LocalDomain;           /* our local domain name */
                    166: int    InetInuse = 0;          /* non-zero if INET sockets are being used */
                    167: int    finet;                  /* Internet datagram socket */
                    168: int    LogPort;                /* port number for INET connections */
                    169: int    Initialized = 0;        /* set when we have initialized ourselves */
                    170: int    MarkInterval = 20 * 60; /* interval between marks in seconds */
                    171: int    MarkSeq = 0;            /* mark sequence number */
                    172: 
                    173: extern int errno;
                    174: extern char *ctime(), *index(), *calloc();
                    175: 
                    176: main(argc, argv)
                    177:        int argc;
                    178:        char **argv;
                    179: {
                    180:        register int i;
                    181:        register char *p;
                    182:        int funix, inetm, fklog, klogm, len;
                    183:        struct sockaddr_un sunx, fromunix;
                    184:        struct sockaddr_in sin, frominet;
                    185:        FILE *fp;
                    186:        int ch;
                    187:        char line[MSG_BSIZE + 1];
                    188:        extern int optind;
                    189:        extern char *optarg;
                    190:        void die(), domark(), init(), reapchild();
                    191: 
                    192:        while ((ch = getopt(argc, argv, "df:m:p:")) != EOF)
                    193:                switch((char)ch) {
                    194:                case 'd':               /* debug */
                    195:                        Debug++;
                    196:                        break;
                    197:                case 'f':               /* configuration file */
                    198:                        ConfFile = optarg;
                    199:                        break;
                    200:                case 'm':               /* mark interval */
                    201:                        MarkInterval = atoi(optarg) * 60;
                    202:                        break;
                    203:                case 'p':               /* path */
                    204:                        LogName = optarg;
                    205:                        break;
                    206:                case '?':
                    207:                default:
                    208:                        usage();
                    209:                }
                    210:        if (argc -= optind)
                    211:                usage();
                    212: 
                    213:        if (!Debug)
                    214:                daemon(0, 0);
                    215:        else
                    216:                setlinebuf(stdout);
                    217: 
                    218:        consfile.f_type = F_CONSOLE;
                    219:        (void) strcpy(consfile.f_un.f_fname, ctty);
                    220:        (void) gethostname(LocalHostName, sizeof LocalHostName);
                    221:        if (p = index(LocalHostName, '.')) {
                    222:                *p++ = '\0';
                    223:                LocalDomain = p;
                    224:        }
                    225:        else
                    226:                LocalDomain = "";
                    227:        (void) signal(SIGTERM, die);
                    228:        (void) signal(SIGINT, Debug ? die : SIG_IGN);
                    229:        (void) signal(SIGQUIT, Debug ? die : SIG_IGN);
                    230:        (void) signal(SIGCHLD, reapchild);
                    231:        (void) signal(SIGALRM, domark);
                    232:        (void) alarm(TIMERINTVL);
                    233:        (void) unlink(LogName);
                    234: 
                    235:        bzero((char *)&sunx, sizeof(sunx));
                    236:        sunx.sun_family = AF_UNIX;
                    237:        (void) strncpy(sunx.sun_path, LogName, sizeof sunx.sun_path);
                    238:        funix = socket(AF_UNIX, SOCK_DGRAM, 0);
                    239:        if (funix < 0 || bind(funix, (struct sockaddr *) &sunx,
                    240:            sizeof(sunx.sun_family)+sizeof(sunx.sun_len)+
                    241:            strlen(sunx.sun_path)) < 0 ||
                    242:            chmod(LogName, 0666) < 0) {
                    243:                (void) sprintf(line, "cannot create %s", LogName);
                    244:                logerror(line);
                    245:                dprintf("cannot create %s (%d)\n", LogName, errno);
                    246:                die(0);
                    247:        }
                    248:        finet = socket(AF_INET, SOCK_DGRAM, 0);
                    249:        if (finet >= 0) {
                    250:                struct servent *sp;
                    251: 
                    252:                sp = getservbyname("syslog", "udp");
                    253:                if (sp == NULL) {
                    254:                        errno = 0;
                    255:                        logerror("syslog/udp: unknown service");
                    256:                        die(0);
                    257:                }
                    258:                sin.sin_family = AF_INET;
                    259:                sin.sin_port = LogPort = sp->s_port;
                    260:                if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
                    261:                        logerror("bind");
                    262:                        if (!Debug)
                    263:                                die(0);
                    264:                } else {
                    265:                        inetm = FDMASK(finet);
                    266:                        InetInuse = 1;
                    267:                }
                    268:        }
                    269:        if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) >= 0)
                    270:                klogm = FDMASK(fklog);
                    271:        else {
                    272:                dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
                    273:                klogm = 0;
                    274:        }
                    275: 
                    276:        /* tuck my process id away */
                    277:        fp = fopen(PidFile, "w");
                    278:        if (fp != NULL) {
                    279:                fprintf(fp, "%d\n", getpid());
                    280:                (void) fclose(fp);
                    281:        }
                    282: 
                    283:        dprintf("off & running....\n");
                    284: 
                    285:        init();
                    286:        (void) signal(SIGHUP, init);
                    287: 
                    288:        for (;;) {
                    289:                int nfds, readfds = FDMASK(funix) | inetm | klogm;
                    290: 
                    291:                errno = 0;
                    292:                dprintf("readfds = %#x\n", readfds);
                    293:                nfds = select(20, (fd_set *) &readfds, (fd_set *) NULL,
                    294:                    (fd_set *) NULL, (struct timeval *) NULL);
                    295:                if (nfds == 0)
                    296:                        continue;
                    297:                if (nfds < 0) {
                    298:                        if (errno != EINTR)
                    299:                                logerror("select");
                    300:                        continue;
                    301:                }
                    302:                dprintf("got a message (%d, %#x)\n", nfds, readfds);
                    303:                if (readfds & klogm) {
                    304:                        i = read(fklog, line, sizeof(line) - 1);
                    305:                        if (i > 0) {
                    306:                                line[i] = '\0';
                    307:                                printsys(line);
                    308:                        } else if (i < 0 && errno != EINTR) {
                    309:                                logerror("klog");
                    310:                                fklog = -1;
                    311:                                klogm = 0;
                    312:                        }
                    313:                }
                    314:                if (readfds & FDMASK(funix)) {
                    315:                        len = sizeof fromunix;
                    316:                        i = recvfrom(funix, line, MAXLINE, 0,
                    317:                            (struct sockaddr *) &fromunix, &len);
                    318:                        if (i > 0) {
                    319:                                line[i] = '\0';
                    320:                                printline(LocalHostName, line);
                    321:                        } else if (i < 0 && errno != EINTR)
                    322:                                logerror("recvfrom unix");
                    323:                }
                    324:                if (readfds & inetm) {
                    325:                        len = sizeof frominet;
                    326:                        i = recvfrom(finet, line, MAXLINE, 0,
                    327:                            (struct sockaddr *) &frominet, &len);
                    328:                        if (i > 0) {
                    329:                                extern char *cvthname();
                    330: 
                    331:                                line[i] = '\0';
                    332:                                printline(cvthname(&frominet), line);
                    333:                        } else if (i < 0 && errno != EINTR)
                    334:                                logerror("recvfrom inet");
                    335:                } 
                    336:        }
                    337: }
                    338: 
                    339: usage()
                    340: {
                    341:        (void) fprintf(stderr,
                    342:            "usage: syslogd [-d] [-f conffile] [-m markinterval] [-p path]\n");
                    343:        exit(1);
                    344: }
                    345: 
                    346: /*
                    347:  * Take a raw input line, decode the message, and print the message
                    348:  * on the appropriate log files.
                    349:  */
                    350: 
                    351: printline(hname, msg)
                    352:        char *hname;
                    353:        char *msg;
                    354: {
                    355:        register char *p, *q;
                    356:        register int c;
                    357:        char line[MAXLINE + 1];
                    358:        int pri;
                    359: 
                    360:        /* test for special codes */
                    361:        pri = DEFUPRI;
                    362:        p = msg;
                    363:        if (*p == '<') {
                    364:                pri = 0;
                    365:                while (isdigit(*++p))
                    366:                        pri = 10 * pri + (*p - '0');
                    367:                if (*p == '>')
                    368:                        ++p;
                    369:        }
                    370:        if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
                    371:                pri = DEFUPRI;
                    372: 
                    373:        /* don't allow users to log kernel messages */
                    374:        if (LOG_FAC(pri) == LOG_KERN)
                    375:                pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
                    376: 
                    377:        q = line;
                    378: 
                    379:        while ((c = *p++ & 0177) != '\0' &&
                    380:            q < &line[sizeof(line) - 1])
                    381:                if (iscntrl(c))
                    382:                        if (c == '\n')
                    383:                                *q++ = ' ';
                    384:                        else if (c == '\t')
                    385:                                *q++ = '\t';
                    386:                        else {
                    387:                                *q++ = '^';
                    388:                                *q++ = c ^ 0100;
                    389:                        }
                    390:                else
                    391:                        *q++ = c;
                    392:        *q = '\0';
                    393: 
                    394:        logmsg(pri, line, hname, 0);
                    395: }
                    396: 
                    397: /*
                    398:  * Take a raw input line from /dev/klog, split and format similar to syslog().
                    399:  */
                    400: 
                    401: printsys(msg)
                    402:        char *msg;
                    403: {
                    404:        register char *p, *q;
                    405:        register int c;
                    406:        char line[MAXLINE + 1];
                    407:        int pri, flags;
                    408:        char *lp;
                    409: 
                    410:        (void) strcpy(line, "vmunix: ");
                    411:        lp = line + strlen(line);
                    412:        for (p = msg; *p != '\0'; ) {
                    413:                flags = SYNC_FILE | ADDDATE;    /* fsync file after write */
                    414:                pri = DEFSPRI;
                    415:                if (*p == '<') {
                    416:                        pri = 0;
                    417:                        while (isdigit(*++p))
                    418:                                pri = 10 * pri + (*p - '0');
                    419:                        if (*p == '>')
                    420:                                ++p;
                    421:                } else {
                    422:                        /* kernel printf's come out on console */
                    423:                        flags |= IGN_CONS;
                    424:                }
                    425:                if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
                    426:                        pri = DEFSPRI;
                    427:                q = lp;
                    428:                while (*p != '\0' && (c = *p++) != '\n' &&
                    429:                    q < &line[MAXLINE])
                    430:                        *q++ = c;
                    431:                *q = '\0';
                    432:                logmsg(pri, line, LocalHostName, flags);
                    433:        }
                    434: }
                    435: 
                    436: time_t now;
                    437: 
                    438: /*
                    439:  * Log a message to the appropriate log files, users, etc. based on
                    440:  * the priority.
                    441:  */
                    442: 
                    443: logmsg(pri, msg, from, flags)
                    444:        int pri;
                    445:        char *msg, *from;
                    446:        int flags;
                    447: {
                    448:        register struct filed *f;
                    449:        int fac, prilev;
                    450:        int omask, msglen;
                    451:        char *timestamp;
                    452:        time_t time();
                    453: 
                    454:        dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
                    455:            pri, flags, from, msg);
                    456: 
                    457:        omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM));
                    458: 
                    459:        /*
                    460:         * Check to see if msg looks non-standard.
                    461:         */
                    462:        msglen = strlen(msg);
                    463:        if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
                    464:            msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
                    465:                flags |= ADDDATE;
                    466: 
                    467:        (void) time(&now);
                    468:        if (flags & ADDDATE)
                    469:                timestamp = ctime(&now) + 4;
                    470:        else {
                    471:                timestamp = msg;
                    472:                msg += 16;
                    473:                msglen -= 16;
                    474:        }
                    475: 
                    476:        /* extract facility and priority level */
                    477:        if (flags & MARK)
                    478:                fac = LOG_NFACILITIES;
                    479:        else
                    480:                fac = LOG_FAC(pri);
                    481:        prilev = LOG_PRI(pri);
                    482: 
                    483:        /* log the message to the particular outputs */
                    484:        if (!Initialized) {
                    485:                f = &consfile;
                    486:                f->f_file = open(ctty, O_WRONLY, 0);
                    487: 
                    488:                if (f->f_file >= 0) {
                    489:                        fprintlog(f, flags, msg);
                    490:                        (void) close(f->f_file);
                    491:                }
                    492:                (void) sigsetmask(omask);
                    493:                return;
                    494:        }
                    495:        for (f = Files; f; f = f->f_next) {
                    496:                /* skip messages that are incorrect priority */
                    497:                if (f->f_pmask[fac] < prilev ||
                    498:                    f->f_pmask[fac] == INTERNAL_NOPRI)
                    499:                        continue;
                    500: 
                    501:                if (f->f_type == F_CONSOLE && (flags & IGN_CONS))
                    502:                        continue;
                    503: 
                    504:                /* don't output marks to recently written files */
                    505:                if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
                    506:                        continue;
                    507: 
                    508:                /*
                    509:                 * suppress duplicate lines to this file
                    510:                 */
                    511:                if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
                    512:                    !strcmp(msg, f->f_prevline) &&
                    513:                    !strcmp(from, f->f_prevhost)) {
                    514:                        (void) strncpy(f->f_lasttime, timestamp, 15);
                    515:                        f->f_prevcount++;
                    516:                        dprintf("msg repeated %d times, %ld sec of %d\n",
                    517:                            f->f_prevcount, now - f->f_time,
                    518:                            repeatinterval[f->f_repeatcount]);
                    519:                        /*
                    520:                         * If domark would have logged this by now,
                    521:                         * flush it now (so we don't hold isolated messages),
                    522:                         * but back off so we'll flush less often
                    523:                         * in the future.
                    524:                         */
                    525:                        if (now > REPEATTIME(f)) {
                    526:                                fprintlog(f, flags, (char *)NULL);
                    527:                                BACKOFF(f);
                    528:                        }
                    529:                } else {
                    530:                        /* new line, save it */
                    531:                        if (f->f_prevcount)
                    532:                                fprintlog(f, 0, (char *)NULL);
                    533:                        f->f_repeatcount = 0;
                    534:                        (void) strncpy(f->f_lasttime, timestamp, 15);
                    535:                        (void) strncpy(f->f_prevhost, from,
                    536:                                        sizeof(f->f_prevhost));
                    537:                        if (msglen < MAXSVLINE) {
                    538:                                f->f_prevlen = msglen;
                    539:                                f->f_prevpri = pri;
                    540:                                (void) strcpy(f->f_prevline, msg);
                    541:                                fprintlog(f, flags, (char *)NULL);
                    542:                        } else {
                    543:                                f->f_prevline[0] = 0;
                    544:                                f->f_prevlen = 0;
                    545:                                fprintlog(f, flags, msg);
                    546:                        }
                    547:                }
                    548:        }
                    549:        (void) sigsetmask(omask);
                    550: }
                    551: 
                    552: fprintlog(f, flags, msg)
                    553:        register struct filed *f;
                    554:        int flags;
                    555:        char *msg;
                    556: {
                    557:        struct iovec iov[6];
                    558:        register struct iovec *v;
                    559:        register int l;
                    560:        char line[MAXLINE + 1], repbuf[80], greetings[200];
                    561: 
                    562:        v = iov;
                    563:        if (f->f_type == F_WALL) {
                    564:                v->iov_base = greetings;
                    565:                v->iov_len = sprintf(greetings,
                    566:                    "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
                    567:                    f->f_prevhost, ctime(&now));
                    568:                v++;
                    569:                v->iov_base = "";
                    570:                v->iov_len = 0;
                    571:                v++;
                    572:        } else {
                    573:                v->iov_base = f->f_lasttime;
                    574:                v->iov_len = 15;
                    575:                v++;
                    576:                v->iov_base = " ";
                    577:                v->iov_len = 1;
                    578:                v++;
                    579:        }
                    580:        v->iov_base = f->f_prevhost;
                    581:        v->iov_len = strlen(v->iov_base);
                    582:        v++;
                    583:        v->iov_base = " ";
                    584:        v->iov_len = 1;
                    585:        v++;
                    586: 
                    587:        if (msg) {
                    588:                v->iov_base = msg;
                    589:                v->iov_len = strlen(msg);
                    590:        } else if (f->f_prevcount > 1) {
                    591:                v->iov_base = repbuf;
                    592:                v->iov_len = sprintf(repbuf, "last message repeated %d times",
                    593:                    f->f_prevcount);
                    594:        } else {
                    595:                v->iov_base = f->f_prevline;
                    596:                v->iov_len = f->f_prevlen;
                    597:        }
                    598:        v++;
                    599: 
                    600:        dprintf("Logging to %s", TypeNames[f->f_type]);
                    601:        f->f_time = now;
                    602: 
                    603:        switch (f->f_type) {
                    604:        case F_UNUSED:
                    605:                dprintf("\n");
                    606:                break;
                    607: 
                    608:        case F_FORW:
                    609:                dprintf(" %s\n", f->f_un.f_forw.f_hname);
                    610:                l = sprintf(line, "<%d>%.15s %s", f->f_prevpri,
                    611:                    iov[0].iov_base, iov[4].iov_base);
                    612:                if (l > MAXLINE)
                    613:                        l = MAXLINE;
                    614:                if (sendto(finet, line, l, 0, &f->f_un.f_forw.f_addr,
                    615:                    sizeof f->f_un.f_forw.f_addr) != l) {
                    616:                        int e = errno;
                    617:                        (void) close(f->f_file);
                    618:                        f->f_type = F_UNUSED;
                    619:                        errno = e;
                    620:                        logerror("sendto");
                    621:                }
                    622:                break;
                    623: 
                    624:        case F_CONSOLE:
                    625:                if (flags & IGN_CONS) {
                    626:                        dprintf(" (ignored)\n");
                    627:                        break;
                    628:                }
                    629:                /* FALLTHROUGH */
                    630: 
                    631:        case F_TTY:
                    632:        case F_FILE:
                    633:                dprintf(" %s\n", f->f_un.f_fname);
                    634:                if (f->f_type != F_FILE) {
                    635:                        v->iov_base = "\r\n";
                    636:                        v->iov_len = 2;
                    637:                } else {
                    638:                        v->iov_base = "\n";
                    639:                        v->iov_len = 1;
                    640:                }
                    641:        again:
                    642:                if (writev(f->f_file, iov, 6) < 0) {
                    643:                        int e = errno;
                    644:                        (void) close(f->f_file);
                    645:                        /*
                    646:                         * Check for errors on TTY's due to loss of tty
                    647:                         */
                    648:                        if ((e == EIO || e == EBADF) && f->f_type != F_FILE) {
                    649:                                f->f_file = open(f->f_un.f_fname,
                    650:                                    O_WRONLY|O_APPEND, 0);
                    651:                                if (f->f_file < 0) {
                    652:                                        f->f_type = F_UNUSED;
                    653:                                        logerror(f->f_un.f_fname);
                    654:                                } else
                    655:                                        goto again;
                    656:                        } else {
                    657:                                f->f_type = F_UNUSED;
                    658:                                errno = e;
                    659:                                logerror(f->f_un.f_fname);
                    660:                        }
                    661:                } else if (flags & SYNC_FILE)
                    662:                        (void) fsync(f->f_file);
                    663:                break;
                    664: 
                    665:        case F_USERS:
                    666:        case F_WALL:
                    667:                dprintf("\n");
                    668:                v->iov_base = "\r\n";
                    669:                v->iov_len = 2;
                    670:                wallmsg(f, iov);
                    671:                break;
                    672:        }
                    673:        f->f_prevcount = 0;
                    674: }
                    675: 
                    676: /*
                    677:  *  WALLMSG -- Write a message to the world at large
                    678:  *
                    679:  *     Write the specified message to either the entire
                    680:  *     world, or a list of approved users.
                    681:  */
                    682: 
                    683: wallmsg(f, iov)
                    684:        register struct filed *f;
                    685:        struct iovec *iov;
                    686: {
                    687:        static int reenter;                     /* avoid calling ourselves */
                    688:        register FILE *uf;
                    689:        register int i;
                    690:        struct utmp ut;
                    691:        char *p, *ttymsg();
                    692: 
                    693:        if (reenter++)
                    694:                return;
                    695:        if ((uf = fopen(_PATH_UTMP, "r")) == NULL) {
                    696:                logerror(_PATH_UTMP);
                    697:                reenter = 0;
                    698:                return;
                    699:        }
                    700:        /* NOSTRICT */
                    701:        while (fread((char *) &ut, sizeof ut, 1, uf) == 1) {
                    702:                if (ut.ut_name[0] == '\0')
                    703:                        continue;
                    704:                if (f->f_type == F_WALL) {
                    705:                        if (p = ttymsg(iov, 6, ut.ut_line, 1)) {
                    706:                                errno = 0;      /* already in msg */
                    707:                                logerror(p);
                    708:                        }
                    709:                        continue;
                    710:                }
                    711:                /* should we send the message to this user? */
                    712:                for (i = 0; i < MAXUNAMES; i++) {
                    713:                        if (!f->f_un.f_uname[i][0])
                    714:                                break;
                    715:                        if (!strncmp(f->f_un.f_uname[i], ut.ut_name,
                    716:                            UT_NAMESIZE)) {
                    717:                                if (p = ttymsg(iov, 6, ut.ut_line, 1)) {
                    718:                                        errno = 0;      /* already in msg */
                    719:                                        logerror(p);
                    720:                                }
                    721:                                break;
                    722:                        }
                    723:                }
                    724:        }
                    725:        (void) fclose(uf);
                    726:        reenter = 0;
                    727: }
                    728: 
                    729: void
                    730: reapchild()
                    731: {
                    732:        union wait status;
                    733: 
                    734:        while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
                    735:                ;
                    736: }
                    737: 
                    738: /*
                    739:  * Return a printable representation of a host address.
                    740:  */
                    741: char *
                    742: cvthname(f)
                    743:        struct sockaddr_in *f;
                    744: {
                    745:        struct hostent *hp;
                    746:        register char *p;
                    747:        extern char *inet_ntoa();
                    748: 
                    749:        dprintf("cvthname(%s)\n", inet_ntoa(f->sin_addr));
                    750: 
                    751:        if (f->sin_family != AF_INET) {
                    752:                dprintf("Malformed from address\n");
                    753:                return ("???");
                    754:        }
                    755:        hp = gethostbyaddr(&f->sin_addr, sizeof(struct in_addr), f->sin_family);
                    756:        if (hp == 0) {
                    757:                dprintf("Host name for your address (%s) unknown\n",
                    758:                        inet_ntoa(f->sin_addr));
                    759:                return (inet_ntoa(f->sin_addr));
                    760:        }
                    761:        if ((p = index(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0)
                    762:                *p = '\0';
                    763:        return (hp->h_name);
                    764: }
                    765: 
                    766: void
                    767: domark()
                    768: {
                    769:        register struct filed *f;
                    770:        time_t time();
                    771: 
                    772:        now = time((time_t *)NULL);
                    773:        MarkSeq += TIMERINTVL;
                    774:        if (MarkSeq >= MarkInterval) {
                    775:                logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK);
                    776:                MarkSeq = 0;
                    777:        }
                    778: 
                    779:        for (f = Files; f; f = f->f_next) {
                    780:                if (f->f_prevcount && now >= REPEATTIME(f)) {
                    781:                        dprintf("flush %s: repeated %d times, %d sec.\n",
                    782:                            TypeNames[f->f_type], f->f_prevcount,
                    783:                            repeatinterval[f->f_repeatcount]);
                    784:                        fprintlog(f, 0, (char *)NULL);
                    785:                        BACKOFF(f);
                    786:                }
                    787:        }
                    788:        (void) alarm(TIMERINTVL);
                    789: }
                    790: 
                    791: /*
                    792:  * Print syslogd errors some place.
                    793:  */
                    794: logerror(type)
                    795:        char *type;
                    796: {
                    797:        char buf[100], *strerror();
                    798: 
                    799:        if (errno)
                    800:                (void) sprintf(buf, "syslogd: %s: %s", type, strerror(errno));
                    801:        else
                    802:                (void) sprintf(buf, "syslogd: %s", type);
                    803:        errno = 0;
                    804:        dprintf("%s\n", buf);
                    805:        logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
                    806: }
                    807: 
                    808: void
                    809: die(sig)
                    810: {
                    811:        register struct filed *f;
                    812:        char buf[100];
                    813: 
                    814:        for (f = Files; f != NULL; f = f->f_next) {
                    815:                /* flush any pending output */
                    816:                if (f->f_prevcount)
                    817:                        fprintlog(f, 0, (char *)NULL);
                    818:        }
                    819:        if (sig) {
                    820:                dprintf("syslogd: exiting on signal %d\n", sig);
                    821:                (void) sprintf(buf, "exiting on signal %d", sig);
                    822:                errno = 0;
                    823:                logerror(buf);
                    824:        }
                    825:        (void) unlink(LogName);
                    826:        exit(0);
                    827: }
                    828: 
                    829: /*
                    830:  *  INIT -- Initialize syslogd from configuration table
                    831:  */
                    832: 
                    833: void
                    834: init()
                    835: {
                    836:        register int i;
                    837:        register FILE *cf;
                    838:        register struct filed *f, *next, **nextp;
                    839:        register char *p;
                    840:        char cline[BUFSIZ];
                    841: 
                    842:        dprintf("init\n");
                    843: 
                    844:        /*
                    845:         *  Close all open log files.
                    846:         */
                    847:        Initialized = 0;
                    848:        for (f = Files; f != NULL; f = next) {
                    849:                /* flush any pending output */
                    850:                if (f->f_prevcount)
                    851:                        fprintlog(f, 0, (char *)NULL);
                    852: 
                    853:                switch (f->f_type) {
                    854:                  case F_FILE:
                    855:                  case F_TTY:
                    856:                  case F_CONSOLE:
                    857:                  case F_FORW:
                    858:                        (void) close(f->f_file);
                    859:                        break;
                    860:                }
                    861:                next = f->f_next;
                    862:                free((char *) f);
                    863:        }
                    864:        Files = NULL;
                    865:        nextp = &Files;
                    866: 
                    867:        /* open the configuration file */
                    868:        if ((cf = fopen(ConfFile, "r")) == NULL) {
                    869:                dprintf("cannot open %s\n", ConfFile);
                    870:                *nextp = (struct filed *)calloc(1, sizeof(*f));
                    871:                cfline("*.ERR\t/dev/console", *nextp);
                    872:                (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f));
                    873:                cfline("*.PANIC\t*", (*nextp)->f_next);
                    874:                Initialized = 1;
                    875:                return;
                    876:        }
                    877: 
                    878:        /*
                    879:         *  Foreach line in the conf table, open that file.
                    880:         */
                    881:        f = NULL;
                    882:        while (fgets(cline, sizeof cline, cf) != NULL) {
                    883:                /*
                    884:                 * check for end-of-section, comments, strip off trailing
                    885:                 * spaces and newline character.
                    886:                 */
                    887:                for (p = cline; isspace(*p); ++p);
                    888:                if (*p == NULL || *p == '#')
                    889:                        continue;
                    890:                for (p = index(cline, '\0'); isspace(*--p););
                    891:                *++p = '\0';
                    892:                f = (struct filed *)calloc(1, sizeof(*f));
                    893:                *nextp = f;
                    894:                nextp = &f->f_next;
                    895:                cfline(cline, f);
                    896:        }
                    897: 
                    898:        /* close the configuration file */
                    899:        (void) fclose(cf);
                    900: 
                    901:        Initialized = 1;
                    902: 
                    903:        if (Debug) {
                    904:                for (f = Files; f; f = f->f_next) {
                    905:                        for (i = 0; i <= LOG_NFACILITIES; i++)
                    906:                                if (f->f_pmask[i] == INTERNAL_NOPRI)
                    907:                                        printf("X ");
                    908:                                else
                    909:                                        printf("%d ", f->f_pmask[i]);
                    910:                        printf("%s: ", TypeNames[f->f_type]);
                    911:                        switch (f->f_type) {
                    912:                        case F_FILE:
                    913:                        case F_TTY:
                    914:                        case F_CONSOLE:
                    915:                                printf("%s", f->f_un.f_fname);
                    916:                                break;
                    917: 
                    918:                        case F_FORW:
                    919:                                printf("%s", f->f_un.f_forw.f_hname);
                    920:                                break;
                    921: 
                    922:                        case F_USERS:
                    923:                                for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++)
                    924:                                        printf("%s, ", f->f_un.f_uname[i]);
                    925:                                break;
                    926:                        }
                    927:                        printf("\n");
                    928:                }
                    929:        }
                    930: 
                    931:        logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
                    932:        dprintf("syslogd: restarted\n");
                    933: }
                    934: 
                    935: /*
                    936:  * Crack a configuration file line
                    937:  */
                    938: 
                    939: cfline(line, f)
                    940:        char *line;
                    941:        register struct filed *f;
                    942: {
                    943:        register char *p;
                    944:        register char *q;
                    945:        register int i;
                    946:        char *bp;
                    947:        int pri;
                    948:        struct hostent *hp;
                    949:        char buf[MAXLINE];
                    950: 
                    951:        dprintf("cfline(%s)\n", line);
                    952: 
                    953:        errno = 0;      /* keep strerror() stuff out of logerror messages */
                    954: 
                    955:        /* clear out file entry */
                    956:        bzero((char *) f, sizeof *f);
                    957:        for (i = 0; i <= LOG_NFACILITIES; i++)
                    958:                f->f_pmask[i] = INTERNAL_NOPRI;
                    959: 
                    960:        /* scan through the list of selectors */
                    961:        for (p = line; *p && *p != '\t';) {
                    962: 
                    963:                /* find the end of this facility name list */
                    964:                for (q = p; *q && *q != '\t' && *q++ != '.'; )
                    965:                        continue;
                    966: 
                    967:                /* collect priority name */
                    968:                for (bp = buf; *q && !index("\t,;", *q); )
                    969:                        *bp++ = *q++;
                    970:                *bp = '\0';
                    971: 
                    972:                /* skip cruft */
                    973:                while (index(", ;", *q))
                    974:                        q++;
                    975: 
                    976:                /* decode priority name */
                    977:                pri = decode(buf, prioritynames);
                    978:                if (pri < 0) {
                    979:                        char xbuf[200];
                    980: 
                    981:                        (void) sprintf(xbuf, "unknown priority name \"%s\"",
                    982:                            buf);
                    983:                        logerror(xbuf);
                    984:                        return;
                    985:                }
                    986: 
                    987:                /* scan facilities */
                    988:                while (*p && !index("\t.;", *p)) {
                    989:                        for (bp = buf; *p && !index("\t,;.", *p); )
                    990:                                *bp++ = *p++;
                    991:                        *bp = '\0';
                    992:                        if (*buf == '*')
                    993:                                for (i = 0; i < LOG_NFACILITIES; i++)
                    994:                                        f->f_pmask[i] = pri;
                    995:                        else {
                    996:                                i = decode(buf, facilitynames);
                    997:                                if (i < 0) {
                    998:                                        char xbuf[200];
                    999: 
                   1000:                                        (void) sprintf(xbuf,
                   1001:                                            "unknown facility name \"%s\"",
                   1002:                                            buf);
                   1003:                                        logerror(xbuf);
                   1004:                                        return;
                   1005:                                }
                   1006:                                f->f_pmask[i >> 3] = pri;
                   1007:                        }
                   1008:                        while (*p == ',' || *p == ' ')
                   1009:                                p++;
                   1010:                }
                   1011: 
                   1012:                p = q;
                   1013:        }
                   1014: 
                   1015:        /* skip to action part */
                   1016:        while (*p == '\t')
                   1017:                p++;
                   1018: 
                   1019:        switch (*p)
                   1020:        {
                   1021:        case '@':
                   1022:                if (!InetInuse)
                   1023:                        break;
                   1024:                (void) strcpy(f->f_un.f_forw.f_hname, ++p);
                   1025:                hp = gethostbyname(p);
                   1026:                if (hp == NULL) {
                   1027:                        extern int h_errno, h_nerr;
                   1028:                        extern char **h_errlist;
                   1029: 
                   1030:                        logerror((u_int)h_errno < h_nerr ?
                   1031:                            h_errlist[h_errno] : "Unknown error");
                   1032:                        break;
                   1033:                }
                   1034:                bzero((char *) &f->f_un.f_forw.f_addr,
                   1035:                         sizeof f->f_un.f_forw.f_addr);
                   1036:                f->f_un.f_forw.f_addr.sin_family = AF_INET;
                   1037:                f->f_un.f_forw.f_addr.sin_port = LogPort;
                   1038:                bcopy(hp->h_addr, (char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_length);
                   1039:                f->f_type = F_FORW;
                   1040:                break;
                   1041: 
                   1042:        case '/':
                   1043:                (void) strcpy(f->f_un.f_fname, p);
                   1044:                if ((f->f_file = open(p, O_WRONLY|O_APPEND, 0)) < 0) {
                   1045:                        f->f_file = F_UNUSED;
                   1046:                        logerror(p);
                   1047:                        break;
                   1048:                }
                   1049:                if (isatty(f->f_file))
                   1050:                        f->f_type = F_TTY;
                   1051:                else
                   1052:                        f->f_type = F_FILE;
                   1053:                if (strcmp(p, ctty) == 0)
                   1054:                        f->f_type = F_CONSOLE;
                   1055:                break;
                   1056: 
                   1057:        case '*':
                   1058:                f->f_type = F_WALL;
                   1059:                break;
                   1060: 
                   1061:        default:
                   1062:                for (i = 0; i < MAXUNAMES && *p; i++) {
                   1063:                        for (q = p; *q && *q != ','; )
                   1064:                                q++;
                   1065:                        (void) strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE);
                   1066:                        if ((q - p) > UT_NAMESIZE)
                   1067:                                f->f_un.f_uname[i][UT_NAMESIZE] = '\0';
                   1068:                        else
                   1069:                                f->f_un.f_uname[i][q - p] = '\0';
                   1070:                        while (*q == ',' || *q == ' ')
                   1071:                                q++;
                   1072:                        p = q;
                   1073:                }
                   1074:                f->f_type = F_USERS;
                   1075:                break;
                   1076:        }
                   1077: }
                   1078: 
                   1079: 
                   1080: /*
                   1081:  *  Decode a symbolic name to a numeric value
                   1082:  */
                   1083: 
                   1084: decode(name, codetab)
                   1085:        char *name;
                   1086:        CODE *codetab;
                   1087: {
                   1088:        register CODE *c;
                   1089:        register char *p;
                   1090:        char buf[40];
                   1091: 
                   1092:        if (isdigit(*name))
                   1093:                return (atoi(name));
                   1094: 
                   1095:        (void) strcpy(buf, name);
                   1096:        for (p = buf; *p; p++)
                   1097:                if (isupper(*p))
                   1098:                        *p = tolower(*p);
                   1099:        for (c = codetab; c->c_name; c++)
                   1100:                if (!strcmp(buf, c->c_name))
                   1101:                        return (c->c_val);
                   1102: 
                   1103:        return (-1);
                   1104: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.