# 2.11BSD#431 - /usr/src/usr.sbin/syslogd/syslogd.c

##### Functions

    cfline            X
    cvthname          X
    decode            X
    die               X
    domark            X
    flushmsg          X
    init              X
    logerror          X
    logmsg            X
    main              X
    printline         X
    printsys          X
    reapchild         X
    untty             X
    usage             X
    wallmsg           X

##### Variables

    ConfFile          X
    Debug             X
    FacNames          X
    Files             X
    InetInuse         X
    Initialized       X
    LocalDomain       X
    LocalHostName     X
    LogName           X
    LogPort           X
    MarkInterval      X
    MarkSeq           X
    PidFile           X
    PrevCount         X
    PrevFlags         X
    PrevHost          X
    PrevLine          X
    PrevPri           X
    PriNames          X
    TypeNames         X
    copyright         X
    ctty              X

##### Macros

    ADDDATE           X
    DEFSPRI           X
    DEFUPRI           X
    FDMASK            X
    F_CONSOLE         X
    F_FILE            X
    F_FORW            X
    F_TTY             X
    F_UNUSED          X
    F_USERS           X
    F_WALL            X
    IGN_CONS          X
    LOG_MARK          X
    MARK              X
    MARKCOUNT         X
    MAXFNAME          X
    MAXLINE           X
    MAXUNAMES         X
    NLOGS             X
    NOCOPY            X
    NOPRI             X
    SYNC_FILE         X
    UNAMESZ           X
    dprintf           X

##### struct's

    code              X
    filed             X

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

#### Defined functions

cfline defined in line 938; used 3 times

- in line 836-837(2), 855

cvthname defined in line 723; used 2 times

- in line 334-337(2)

decode defined in line 1082; used 2 times

- in line 974, 992

die defined in line 785; used 5 times

- in line 160, 204, 249, 259, 266

domark defined in line 748; used 2 times

- in line 160, 215

flushmsg defined in line 757; used 5 times

- in line 482, 490, 754, 791, 816

init defined in line 804; used 3 times

- in line 160, 212, 288

logerror defined in line 771; used 17 times

- in line 247, 258, 264, 306, 315, 328, 339, 570, 600-605(2), 650, 793, 979, 997, 1023, 1033, 1042

logmsg defined in line 455; used 6 times

- in line 406, 446, 752, 764, 782, 891

main defined in line 145; never used
printline defined in line 368; used 2 times

- in line 326, 337

printsys defined in line 413; used 1 times

- in line 313

reapchild defined in line 712; used 2 times

- in line 160, 200

untty defined in line 350; used 2 times

- in line 537, 1047

usage defined in line 344; used 2 times

- in line 165, 187

wallmsg defined in line 632; used 1 times

- in line 616

#### Defined variables

ConfFile defined in line 69; used 3 times

- in line 169, 834-835(2)

Debug defined in line 130; used 7 times

- in line 75, 173, 207, 218, 265, 354, 863

FacNames defined in line 917; used 1 times

- in line 992

Files defined in line 128; used 10 times

- in line 540(2), 821(2), 836-837(2), 844-845(2), 864(2)

InetInuse defined in line 133; used 2 times

- in line 269, 1016

Initialized defined in line 140; used 2 times

- in line 528, 861

LocalDomain defined in line 132; used 3 times

- in line 233-236(2), 743

LocalHostName defined in line 131; used 8 times

- in line 230-231(3), 326, 446, 752, 782, 891

LogName defined in line 68; used 7 times

- in line 178, 238-248(5), 795

LogPort defined in line 134; used 2 times

- in line 262, 1029

MarkInterval defined in line 141; used 4 times

- in line 183, 224-226(2), 546

MarkSeq defined in line 142; used 1 times

- in line 751

PidFile defined in line 70; used 1 times

- in line 280

PrevCount defined in line 139; used 5 times

- in line 486, 759-763(4)

PrevFlags defined in line 137; used 2 times

- in line 493, 764

PrevHost defined in line 136; used 2 times

- in line 492, 764

PrevLine defined in line 135; used 6 times

- in line 483-485(2), 491, 762-765(3)

PrevPri defined in line 138; used 2 times

- in line 494, 764

PriNames defined in line 904; used 1 times

- in line 974

TypeNames defined in line 123; used 2 times

- in line 549, 870

block_set defined in line 143; used 6 times

- in line 192-198(5), 471

copyright defined in line 8; never used
ctty defined in line 71; used 2 times

- in line 529, 1051

sccsid defined in line 12; never used

#### Defined struct's

code defined in line 899; used 8 times

- in line 904(2), 917(2), 1084-1086(4)

filed defined in line 99; used 10 times

- in line 128(2), 460(2), 633(2), 809(2), 940(2)

#### Defined macros

ADDDATE defined in line 91; used 7 times

- in line 478-481(2), 499, 514, 752, 782, 891

DEFSPRI defined in line 40; used 2 times

- in line 428, 436

DEFUPRI defined in line 39; used 2 times

- in line 378, 387

FDMASK defined in line 73; used 4 times

- in line 268-273(2), 295, 320

F_CONSOLE defined in line 118; used 1 times

- in line 1052

F_FILE defined in line 116; used 3 times

- in line 583, 596, 1050

F_FORW defined in line 119; used 1 times

- in line 1036

F_TTY defined in line 117; used 1 times

- in line 1046

F_UNUSED defined in line 115; used 4 times

- in line 568, 599-603(2), 830

F_USERS defined in line 120; used 2 times

- in line 668, 1072

F_WALL defined in line 121; used 2 times

- in line 693, 1056

IGN_CONS defined in line 88; used 2 times

- in line 439, 575

LOG_MARK defined in line 82; used 1 times

- in line 923

MARK defined in line 92; used 4 times

- in line 481, 523, 546, 752

MARKCOUNT defined in line 41; used 3 times

- in line 224-226(2), 751

MAXFNAME defined in line 79; used 1 times

- in line 110

MAXLINE defined in line 38; used 10 times

- in line 135, 322, 332, 374, 418, 443, 467, 561-562(2), 948

MAXUNAMES defined in line 78; used 6 times

- in line 105, 669-671(2), 678, 883, 1060

NLOGS defined in line 37; used 5 times

- in line 128, 540, 821, 845, 864

NOCOPY defined in line 90; used 2 times

- in line 480, 764

NOPRI defined in line 81; used 4 times

- in line 542, 866, 913, 955

SYNC_FILE defined in line 89; used 2 times

- in line 427, 607

UNAMESZ defined in line 77; used 7 times

- in line 105, 675, 689-691(2), 1063-1065(3)

dprintf defined in line 75; used 21 times

- in line 248, 275, 286, 298-301(2), 469, 549-557(3), 576, 582, 613, 731-739(3), 781, 790, 813, 835, 892, 950

Last modified: 1999-06-19 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 4258 |