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

unix.superglobalmegacorp.com

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