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

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

unix.superglobalmegacorp.com

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