Annotation of 43BSD/etc/syslogd.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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