Annotation of 43BSD/etc/syslogd.c, revision 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.