home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / syslog2b.zip / syslogd.c < prev    next >
Text File  |  1996-12-02  |  33KB  |  967 lines

  1. /*  
  2. **  Modified by Jochen Friedrich <jochen@audio.pfalz.de> for OS/2.
  3. */
  4. /*  $Revision: 1.9 $
  5. **  This file has been modified to get it to compile more easily
  6. **  on pre-4.4BSD (e.g., SysVr4 :-) systems.  Rich $alz, June 1991.
  7. */
  8.  
  9. #define WAITVALUE       int
  10.  
  11. /*
  12.  * Copyright (c) 1983, 1988 Regents of the University of California.
  13.  * All rights reserved.
  14.  *
  15.  * Redistribution and use in source and binary forms, with or without
  16.  * modification, are permitted provided that the following conditions
  17.  * are met:
  18.  * 1. Redistributions of source code must retain the above copyright
  19.  *    notice, this list of conditions and the following disclaimer.
  20.  * 2. Redistributions in binary form must reproduce the above copyright
  21.  *    notice, this list of conditions and the following disclaimer in the
  22.  *    documentation and/or other materials provided with the distribution.
  23.  * 3. All advertising materials mentioning features or use of this software
  24.  *    must display the following acknowledgement:
  25.  *    This product includes software developed by the University of
  26.  *    California, Berkeley and its contributors.
  27.  * 4. Neither the name of the University nor the names of its contributors
  28.  *    may be used to endorse or promote products derived from this software
  29.  *    without specific prior written permission.
  30.  *
  31.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  32.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  35.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  39.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  40.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  41.  * SUCH DAMAGE.
  42.  *
  43.  * Wed Sep 14 21:56:59 1994: Applied patches from Alan Modra
  44.  * (alan@spri.levels.unisa.edu.au):
  45.  * 1) Add O_CREAT to open flags so that syslogd doesn't complain about
  46.  *    non-existent files
  47.  * 2) Modified f_pmask initialisation and testing to allow logging of
  48.  *    messages at a particular priority level, rather that all messages
  49.  *    at or above a given priority level.
  50.  *
  51.  * Sat Jun 3 12:48:16 1995: Applied patches from
  52.  * Jochen.Hein@informatik.tu-clausthal.de to allow spaces *AND* tabs to
  53.  * separate the selector from the action. This means that no whitespace is
  54.  * allowed inside the selector.
  55.  * */
  56.  
  57. /*
  58.  *  syslogd -- log system messages
  59.  *
  60.  * This program implements a system log. It takes a series of lines.
  61.  * Each line may have a priority, signified as "<n>" as
  62.  * the first characters of the line.  If this is
  63.  * not present, a default priority is used.
  64.  *
  65.  * To kill syslogd, send a signal 15 (terminate).  A signal 1 (hup) will
  66.  * cause it to reread its configuration file.
  67.  *
  68.  * Defined Constants:
  69.  *
  70.  * MAXLINE -- the maximimum line length that can be handled.
  71.  * DEFUPRI -- the default priority for user messages
  72.  * DEFSPRI -- the default priority for kernel messages
  73.  *
  74.  * Author: Eric Allman
  75.  * extensive changes by Ralph Campbell
  76.  * more extensive changes by Eric Allman (again)
  77.  */
  78.  
  79. #define MAXLINE         1024            /* maximum line length */
  80. #define MAXSVLINE       120             /* maximum saved line length */
  81. #define DEFUPRI         (LOG_USER|LOG_NOTICE)
  82. #define DEFSPRI         (LOG_KERN|LOG_CRIT)
  83. #define TIMERINTVL      30              /* interval for checking flush, mark */
  84.  
  85. #define INCL_DOS
  86. #include <os2.h>
  87.  
  88. #include <errno.h>
  89. #include <signal.h>
  90. #include <process.h>
  91. #include <sys/stat.h>
  92. #include <sys/socket.h>
  93. #include <sys/time.h>
  94. #include <netinet/in.h>
  95. #include <netdb.h>
  96. #include <stdio.h>
  97. #include <io.h>
  98. #include <stdlib.h>
  99. #include <ctype.h>
  100. #include <string.h>
  101. #include <types.h>
  102. #include "getopt.h"
  103. #include "fix_env.h"
  104.  
  105. #define MSG_BSIZE       4096
  106.  
  107.  
  108. #define SYSLOG_NAMES
  109. #include "syslog.h"
  110.  
  111. #define UT_NAMESIZE     8
  112.  
  113. char    ConfFile[512]="c:\\etc\\syslog.cnf";
  114. char    PidFile[512]="c:\\etc\\syslog.pid";
  115.  
  116. #define dprintf         if (Debug) printf
  117.  
  118. #define MAXUNAMES       20      /* maximum number of user names */
  119.  
  120. #include <fcntl.h>
  121.  
  122. void setlinebuf(FILE *f)
  123. {
  124.     setbuf(f, (char *)NULL);
  125. }
  126.  
  127. int our_writev(int fd, struct iovec iov[], int vcount)
  128. {
  129.   int i;
  130.   for (i=0;i<vcount ;i++) 
  131.   {
  132.     write(fd,iov[i].iov_base,iov[i].iov_len);
  133.   } /* endfor */
  134. }
  135.  
  136. /*
  137.  * Flags to logmsg().
  138.  */
  139.  
  140. #define IGN_CONS        0x001   /* don't print on console */
  141. #define SYNC_FILE       0x002   /* do fsync on file after printing */
  142. #define ADDDATE         0x004   /* add a date to the message */
  143. #define MARK            0x008   /* this message is a mark */
  144.  
  145. /*
  146.  * This structure represents the files that will have log
  147.  * copies printed.
  148.  */
  149.  
  150. struct filed {
  151.         struct  filed *f_nextone;       /* next in linked list */
  152.         short   f_type;                 /* entry type, see below */
  153.         short   f_file;                 /* file descriptor */
  154.         time_t  f_time;                 /* time this was last written */
  155.         char    f_pmask[LOG_NFACILITIES+1];     /* priority mask */
  156.         union {
  157.                 char    f_uname[MAXUNAMES][UT_NAMESIZE+1];
  158.                 struct {
  159.                         char    f_hname[MAXHOSTNAMELEN+1];
  160.                         struct sockaddr_in      f_addr;
  161.                 } f_forw;               /* forwarding address */
  162.                 char    f_fname[MAXPATHLEN];
  163.         } f_un;
  164.         char    f_prevline[MAXSVLINE];          /* last message logged */
  165.         char    f_lasttime[16];                 /* time of last occurrence */
  166.         char    f_prevhost[MAXHOSTNAMELEN+1];   /* host from which recd. */
  167.         int     f_prevpri;                      /* pri of f_prevline */
  168.         int     f_prevlen;                      /* length of f_prevline */
  169.         int     f_prevcount;                    /* repetition cnt of prevline */
  170.         int     f_repeatcount;                  /* number of "repeated" msgs */
  171. };
  172.  
  173. /*
  174.  * Intervals at which we flush out "message repeated" messages,
  175.  * in seconds after previous message is logged.  After each flush,
  176.  * we move to the next interval until we reach the largest.
  177.  */
  178. int     repeatinterval[] = { 30, 120, 600 };    /* # of secs before flush */
  179. #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
  180. #define REPEATTIME(f)   ((f)->f_time + repeatinterval[(f)->f_repeatcount])
  181. #define BACKOFF(f)      { if (++(f)->f_repeatcount > MAXREPEAT) \
  182.                                  (f)->f_repeatcount = MAXREPEAT; \
  183.                         }
  184.  
  185. /* values for f_type */
  186. #define F_UNUSED        0               /* unused entry */
  187. #define F_FILE          1               /* regular file */
  188. #define F_TTY           2               /* terminal */
  189. #define F_CONSOLE       3               /* console terminal */
  190. #define F_FORW          4               /* remote machine */
  191.  
  192. char    *TypeNames[5] = {
  193.         "UNUSED",       "FILE",         "TTY",          "CONSOLE",
  194.         "FORW"
  195. };
  196.  
  197. struct  filed *Files;
  198. struct  filed consfile;
  199.  
  200. int     Debug;                  /* debug flag */
  201. char    LocalHostName[MAXHOSTNAMELEN+1];        /* our hostname */
  202. char    *LocalDomain;           /* our local domain name */
  203. int     InetInuse = 0;          /* non-zero if INET sockets are being used */
  204. int     finet;                  /* Internet datagram socket */
  205. int     LogPort;                /* port number for INET connections */
  206. int     Initialized = 0;        /* set when we have initialized ourselves */
  207. int     MarkInterval = 20 * 60; /* interval between marks in seconds */
  208. int     MarkSeq = 0;            /* mark sequence number */
  209.  
  210. void init(int);
  211. void die(int);
  212. void domark(void *v);
  213. void usage(void);
  214. void logerror(char *);
  215.  
  216. int main(int argc, char **argv)
  217. {
  218.         register int i;
  219.         register char *p;
  220.         int len;
  221.         struct sockaddr_in sin, frominet;
  222.         FILE *fp;
  223.         int ch;
  224.         char line[MSG_BSIZE + 1];
  225.         extern int optind;
  226.         extern char *optarg;
  227.  
  228.         fix_env(PidFile,"ETC");
  229.         fix_env(ConfFile,"ETC");
  230.  
  231.         if (sock_init()) exit(-1);
  232.  
  233.         while ((ch = getopt(argc, argv, "df:m:")) != EOF)
  234.                 switch((char)ch) {
  235.                 case 'd':               /* debug */
  236.                         Debug++;
  237.                         break;
  238.                 case 'f':               /* configuration file */
  239.                         strcpy(ConfFile,optarg);
  240.                         break;
  241.                 case 'm':               /* mark interval */
  242.                         MarkInterval = atoi(optarg) * 60;
  243.                         break;
  244.                 case '?':
  245.                 default:
  246.                         usage();
  247.                 }
  248.         if (argc -= optind)
  249.                 usage();
  250.  
  251.         setlinebuf(stdout);
  252.  
  253.         consfile.f_type = F_CONSOLE;
  254.         (void) strcpy(consfile.f_un.f_fname, "CON");
  255.         strcpy(LocalHostName,getenv("HOSTNAME"));
  256.         if (p = strchr(LocalHostName, '.')) {
  257.                 *p++ = '\0';
  258.                 LocalDomain = p;
  259.         }
  260.         else
  261.                 LocalDomain = "";
  262.         (void) signal(SIGTERM, die);
  263.  
  264.         finet = socket(AF_INET, SOCK_DGRAM, 0);
  265.         if (finet >= 0) {
  266.                 struct servent * sp;
  267.  
  268.                 sp = getservbyname("syslog", "udp");
  269.                 if (sp == NULL) {
  270.                         errno = 0;
  271.                         logerror("syslog/udp: unknown service");
  272.                         die(0);
  273.                 }
  274.                 bzero((char *)&sin, sizeof(sin)); /* added uunet!rbj */
  275.                 sin.sin_family = AF_INET;
  276.                 sin.sin_addr.s_addr = INADDR_ANY;
  277.                 sin.sin_port = LogPort = htons(sp->s_port);
  278.                 if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
  279.                         logerror("bind");
  280.                         if (!Debug)
  281.                                 die(0);
  282.                 } else {
  283.                         InetInuse = 1;
  284.                 }
  285.         }
  286.  
  287.         /* tuck my process id away */
  288.         fp = fopen(PidFile, "w");
  289.         if (fp != NULL) {
  290.                 fprintf(fp, "%d\n", getpid());
  291.                 (void) fclose(fp);
  292.         }
  293.  
  294.         i= _beginthread(domark, NULL, 8192, NULL);
  295.  
  296.         dprintf("thread 2 started TID=%d...\n",i);
  297.  
  298.         dprintf("off & running....\n");
  299.  
  300.         init(0);
  301.  
  302.         for (;;) {
  303.                 errno = 0;
  304.                 len = sizeof frominet;
  305.                 i = recvfrom(finet, line, MAXLINE, 0,
  306.                     (struct sockaddr * ) &frominet, &len);
  307.                 if (i > 0) {
  308.                         extern char *cvthname();
  309.  
  310.                         line[i] = '\0';
  311.                         printmulti(cvthname(&frominet), line,i);
  312.         } else if (i < 0 && errno != EINTR)
  313.             logerror("recvfrom inet");
  314.         }
  315. }
  316.  
  317. void usage(void)
  318. {
  319.         (void) fprintf(stderr,
  320.             "usage: syslogd [-d] [-f conffile] [-m markinterval]\n");
  321.         exit(1);
  322. }
  323.  
  324. /*
  325.  * Break up null terminated lines for printline.
  326.  */
  327.  
  328. printmulti(char *hname, char *msg, int len)
  329. {
  330.         int  i;
  331.         char *pt;
  332.  
  333.         dprintf("strlen = %d, len = %d\n", strlen(msg), len );
  334.         for (pt = msg, i = 0; i <= len; i++) {
  335.                 if (msg[i] == '\0') {
  336.                         printline(hname,pt);
  337.                         pt = &msg[i+1];
  338.                 }
  339.         }
  340. }
  341.  
  342. /*
  343.  * Take a raw input line, decode the message, and print the message
  344.  * on the appropriate log files.
  345.  */
  346.  
  347. printline(char *hname, char *msg)
  348. {
  349.         register char *p, *q;
  350.         register int c;
  351.         char line[MAXLINE + 1];
  352.         int pri;
  353.  
  354.         /* test for special codes */
  355.         pri = DEFUPRI;
  356.         p = msg;
  357.         if (*p == '<') {
  358.                 pri = 0;
  359.                 while (isdigit(*++p))
  360.                         pri = 10 * pri + (*p - '0');
  361.                 if (*p == '>')
  362.                         ++p;
  363.         }
  364.         if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
  365.                 pri = DEFUPRI;
  366.  
  367.         /* don't allow users to log kernel messages */
  368.         if (LOG_FAC(pri) == LOG_KERN)
  369.                 pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
  370.  
  371.         q = line;
  372.  
  373.         while ((c = *p++ & 0177) != '\0' &&
  374.             q < &line[sizeof(line) - 1])
  375.                 if (iscntrl(c))
  376.                         if (c == '\n')
  377.                                 *q++ = ' ';
  378.                         else if (c == '\r')
  379.                                 *q++ = ' ';
  380.                         else if (c == '\t')
  381.                                 *q++ = '\t';
  382.                         else {
  383.                                 *q++ = '^';
  384.                                 *q++ = c ^ 0100;
  385.                         }
  386.                 else
  387.                         *q++ = c;
  388.         *q = '\0';
  389.  
  390.         logmsg(pri, line, hname, 0);
  391. }
  392.  
  393. time_t  now;
  394.  
  395. /*
  396.  * Log a message to the appropriate log files, users, etc. based on
  397.  * the priority.
  398.  */
  399.  
  400. logmsg(int pri, char *msg, char *from, int flags)
  401. {
  402.         register struct filed *f;
  403.         int fac, prilev;
  404.         int omask, msglen;
  405.         char *timestamp;
  406.         time_t time();
  407.  
  408.         dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", pri, flags, from, msg);
  409.  
  410.         /*
  411.          * Check to see if msg looks non-standard.
  412.          */
  413.         msglen = strlen(msg);
  414.         if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
  415.             msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
  416.                 flags |= ADDDATE;
  417.  
  418.         (void) time(&now);
  419.         if (flags & ADDDATE)
  420.                 timestamp = (char*)((int)ctime(&now) + 4);
  421.         else {
  422.                 timestamp = msg;
  423.                 msg += 16;
  424.                 msglen -= 16;
  425.         }
  426.  
  427.         /* extract facility and priority level */
  428.         if (flags & MARK)
  429.                 fac = LOG_NFACILITIES;
  430.         else
  431.                 fac = LOG_FAC(pri);
  432.         prilev = 1 << (LOG_PRIMASK - LOG_PRI(pri));
  433.  
  434.         /* log the message to the particular outputs */
  435.         if (!Initialized) {
  436.                 f = &consfile;
  437.                 f->f_file = _open("CON", O_WRONLY, 0);
  438.  
  439.                 if (f->f_file >= 0) {
  440.                         fprintlog(f, flags, msg);
  441.                         (void) _close(f->f_file);
  442.                 }
  443.                 return;
  444.         }
  445.         for (f = Files; f; f = f->f_nextone) {
  446.                 /* skip messages that are incorrect priority */
  447.                 if (!(f->f_pmask[fac] & prilev))
  448.                         continue;
  449.  
  450.                 if (f->f_type == F_CONSOLE && (flags & IGN_CONS))
  451.                         continue;
  452.  
  453.                 /* don't output marks to recently written files */
  454.                 if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
  455.                         continue;
  456.  
  457.                 /*
  458.                  * suppress duplicate lines to this file
  459.                  */
  460.                 if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
  461.                     !strcmp(msg, f->f_prevline) &&
  462.                     !strcmp(from, f->f_prevhost)) {
  463.                         (void) strncpy(f->f_lasttime, timestamp, 15);
  464.                         f->f_prevcount++;
  465.                         dprintf("msg repeated %d times, %ld sec of %d\n",
  466.                             f->f_prevcount, now - f->f_time,
  467.                             repeatinterval[f->f_repeatcount]);
  468.                         /*
  469.                          * If domark would have logged this by now,
  470.                          * flush it now (so we don't hold isolated messages),
  471.                          * but back off so we'll flush less often
  472.                          * in the future.
  473.                          */
  474.                         if (now > REPEATTIME(f)) {
  475.                                 fprintlog(f, flags, (char *)NULL);
  476.                                 BACKOFF(f);
  477.                         }
  478.                 } else {
  479.                         /* new line, save it */
  480.                         if (f->f_prevcount)
  481.                                 fprintlog(f, 0, (char *)NULL);
  482.                         f->f_repeatcount = 0;
  483.                         (void) strncpy(f->f_lasttime, timestamp, 15);
  484.                         (void) strncpy(f->f_prevhost, from,
  485.                                         sizeof(f->f_prevhost));
  486.                         if (msglen < MAXSVLINE) {
  487.                                 f->f_prevlen = msglen;
  488.                                 f->f_prevpri = pri;
  489.                                 (void) strcpy(f->f_prevline, msg);
  490.                                 fprintlog(f, flags, (char *)NULL);
  491.                         } else {
  492.                                 f->f_prevline[0] = 0;
  493.                                 f->f_prevlen = 0;
  494.                                 fprintlog(f, flags, msg);
  495.                         }
  496.                 }
  497.         }
  498. }
  499.  
  500. fprintlog(struct filed *f, int flags, char *msg)
  501. {
  502.         struct iovec iov[6];
  503.         register struct iovec *v;
  504.         register int l;
  505.         char line[MAXLINE + 1], repbuf[80], greetings[200];
  506.  
  507.         v = iov;
  508.         v->iov_base = f->f_lasttime;
  509.         v->iov_len = 15;
  510.         v++;
  511.         v->iov_base = " ";
  512.         v->iov_len = 1;
  513.         v++;
  514.         v->iov_base = f->f_prevhost;
  515.         v->iov_len = strlen(v->iov_base);
  516.         v++;
  517.         v->iov_base = " ";
  518.         v->iov_len = 1;
  519.         v++;
  520.  
  521.         if (msg) {
  522.                 v->iov_base = msg;
  523.                 v->iov_len = strlen(msg);
  524.         } else if (f->f_prevcount > 1) {
  525.                 v->iov_base = repbuf;
  526.                 sprintf(repbuf, "last message repeated %d times",
  527.                     f->f_prevcount);
  528.                 v->iov_len = strlen(repbuf);
  529.         } else {
  530.                 v->iov_base = f->f_prevline;
  531.                 v->iov_len = f->f_prevlen;
  532.         }
  533.         v++;
  534.  
  535.         dprintf("Logging to %s", TypeNames[f->f_type]);
  536.         f->f_time = now;
  537.  
  538.         switch (f->f_type) {
  539.         case F_UNUSED:
  540.                 dprintf("\n");
  541.                 break;
  542.  
  543.         case F_FORW:
  544.                 dprintf(" %s\n", f->f_un.f_forw.f_hname);
  545.                 l = sprintf(line, "<%d>%.15s %s", f->f_prevpri,
  546.                     (char *)iov[0].iov_base, 
  547.                     (char *)iov[4].iov_base);
  548.                 if (l > MAXLINE)
  549.                         l = MAXLINE;
  550.                 if (errno=sendto(finet, line, l, 0, (struct sockaddr*)(&f->f_un.f_forw.f_addr),
  551.                     sizeof f->f_un.f_forw.f_addr) != l) {
  552.                         int e = errno;
  553.                         (void) soclose(f->f_file);
  554.                         f->f_type = F_UNUSED;
  555.                         errno = e;
  556.                         logerror("sendto");
  557.                 }
  558.                 break;
  559.  
  560.         case F_CONSOLE:
  561.                 if (flags & IGN_CONS) {
  562.                         dprintf(" (ignored)\n");
  563.                         break;
  564.                 }
  565.                 /* FALLTHROUGH */
  566.  
  567.         case F_TTY:
  568.         case F_FILE:
  569.                 dprintf(" %s\n", f->f_un.f_fname);
  570.                 if (f->f_type != F_FILE) {
  571.                         v->iov_base = "\r\n";
  572.                         v->iov_len = 2;
  573.                 } else {
  574.                         v->iov_base = "\n";
  575.                         v->iov_len = 1;
  576.                 }
  577.         again:
  578.                 if (our_writev(f->f_file, iov, 6) < 0) {
  579.                         int e = errno;
  580.                         (void) _close(f->f_file);
  581.                         /*
  582.                          * Check for errors on TTY's due to loss of tty
  583.                          */
  584.                         f->f_type = F_UNUSED;
  585.                         errno = e;
  586.                         logerror(f->f_un.f_fname);
  587.                 }
  588. /*                fsync(f->f_file); */
  589.                 break;
  590.  
  591.         }
  592.         f->f_prevcount = 0;
  593. }
  594.  
  595. /*
  596.  * Return a printable representation of a host address.
  597.  */
  598. char * cvthname(struct sockaddr_in *f)
  599. {
  600.         struct hostent * hp;
  601.         register char *p;
  602.  
  603.         dprintf("cvthname(%s)\n", (char *) inet_ntoa(f->sin_addr));
  604.  
  605.         if (f->sin_family != AF_INET) {
  606.                 dprintf("Malformed from address\n");
  607.                 return ("???");
  608.         }
  609.         hp = gethostbyaddr((char *)&(f->sin_addr), sizeof(struct in_addr), f->sin_family);
  610.         if (hp == 0) {
  611.                 dprintf("Host name for your address (%s) unknown\n",
  612.                         (char *) inet_ntoa(f->sin_addr));
  613.                 return (inet_ntoa(f->sin_addr));
  614.         }
  615.         if ((p = strchr(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0)
  616.                 *p = '\0';
  617.         return (hp->h_name);
  618. }
  619.  
  620. void domark(void *v)
  621. {
  622.         for (;;) {
  623.                 register struct filed *f;
  624.  
  625.                 DosSleep(TIMERINTVL*1000);
  626.  
  627.                 now = time((time_t *)NULL);
  628.                 MarkSeq += TIMERINTVL;
  629.                 if (MarkSeq >= MarkInterval) {
  630.                         logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK);
  631.                         MarkSeq = 0;
  632.                 }
  633.  
  634.                 for (f = Files; f; f = f->f_nextone) {
  635.                         if (f->f_prevcount && now >= REPEATTIME(f)) {
  636.                                 dprintf("flush %s: repeated %d times, %d sec.\n",
  637.                                     TypeNames[f->f_type], f->f_prevcount,
  638.                                     repeatinterval[f->f_repeatcount]);
  639.                                 fprintlog(f, 0, (char *)NULL);
  640.                                 BACKOFF(f);
  641.                         }
  642.                 }
  643.         } /* endfor */
  644. }
  645.  
  646. /*
  647.  * Print syslogd errors some place.
  648.  */
  649. void logerror(char *type)
  650. {
  651.         char buf[100];
  652.  
  653.         if (errno)
  654.                 (void) sprintf(buf, "syslogd: %s: %s", type, strerror(errno));
  655.         else
  656.                 (void) sprintf(buf, "syslogd: %s", type);
  657.         errno = 0;
  658.         dprintf("%s\n", buf);
  659.         logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
  660. }
  661.  
  662. void die(int sig)
  663. {
  664.         register struct filed *f;
  665.         char buf[100];
  666.  
  667.         for (f = Files; f != NULL; f = f->f_nextone) {
  668.                 /* flush any pending output */
  669.                 if (f->f_prevcount)
  670.                         fprintlog(f, 0, (char *)NULL);
  671.         }
  672.         if (sig) {
  673.                 dprintf("syslogd: exiting on signal %d\n", sig);
  674.                 (void) sprintf(buf, "exiting on signal %d", sig);
  675.                 errno = 0;
  676.                 logerror(buf);
  677.         }
  678.         exit(0);
  679. }
  680.  
  681. /*
  682.  *  INIT -- Initialize syslogd from configuration table
  683.  */
  684.  
  685. void init(int x)
  686. {
  687.         register int i;
  688.         register FILE *cf;
  689.         register struct filed *f, *next, **nextp;
  690.         register char *p;
  691.         char cline[BUFSIZ];
  692.  
  693.         dprintf("init\n");
  694.  
  695.         /*
  696.          *  Close all open log files.
  697.          */
  698.         Initialized = 0;
  699.         for (f = Files; f != NULL; f = next) {
  700.                 /* flush any pending output */
  701.                 if (f->f_prevcount)
  702.                         fprintlog(f, 0, (char *)NULL);
  703.  
  704.                 switch (f->f_type) {
  705.                   case F_FILE:
  706.                   case F_TTY:
  707.                   case F_CONSOLE:
  708.                         (void) _close(f->f_file);
  709.                         break;
  710.                   case F_FORW:
  711.                         soclose(f->f_file);
  712.                         break;
  713.                 }
  714.                 next = f->f_nextone;
  715.                 free((char *) f);
  716.         }
  717.         Files = NULL;
  718.         nextp = &Files;
  719.  
  720.         /* open the configuration file */
  721.         if ((cf = fopen(ConfFile, "r")) == NULL) {
  722.                 dprintf("cannot open %s\n", ConfFile);
  723.                 *nextp = (struct filed *)malloc(sizeof(*f));
  724.                 cfline("*.ERR\tCON", *nextp);
  725.                 (*nextp)->f_nextone = (struct filed *)malloc(sizeof(*f));
  726.                 cfline("*.PANIC\t*", (*nextp)->f_nextone);
  727.                 Initialized = 1;
  728.                 return;
  729.         }
  730.  
  731.         /*
  732.          *  Foreach line in the conf table, open that file.
  733.          */
  734.         f = NULL;
  735.         while (fgets(cline, sizeof cline, cf) != NULL) {
  736.                 /*
  737.                  * check for end-of-section, comments, strip off trailing
  738.                  * spaces and newline character.
  739.                  */
  740.                 for (p = cline; isspace(*p); ++p);
  741.                 if (*p == '\0' || *p == '#')
  742.                         continue;
  743.                 for (p = strchr(cline, '\0'); isspace(*--p););
  744.                 *++p = '\0';
  745.                 f = (struct filed *)malloc(sizeof(*f));
  746.                 *nextp = f;
  747.                 nextp = &f->f_nextone;
  748.                 cfline(cline, f);
  749.         }
  750.  
  751.         /* close the configuration file */
  752.         (void) fclose(cf);
  753.  
  754.         Initialized = 1;
  755.  
  756.         if (Debug) {
  757.                 for (f = Files; f; f = f->f_nextone) {
  758.                         for (i = 0; i <= LOG_NFACILITIES; i++)
  759.                                 if (f->f_pmask[i] == 0)
  760.                                         printf("X ");
  761.                                 else
  762.                                         printf("0x%02x ", f->f_pmask[i]);
  763.                         printf("%s: ", TypeNames[f->f_type]);
  764.                         switch (f->f_type) {
  765.                         case F_FILE:
  766.                         case F_TTY:
  767.                         case F_CONSOLE:
  768.                                 printf("%s", f->f_un.f_fname);
  769.                                 break;
  770.  
  771.                         case F_FORW:
  772.                                 printf("%s", f->f_un.f_forw.f_hname);
  773.                                 break;
  774.  
  775.                         }
  776.                         printf("\n");
  777.                 }
  778.         }
  779.  
  780.         if (Debug) {
  781.             (void) signal(SIGINT, die);
  782.         }
  783.         else {
  784.             (void) signal(SIGINT, init);
  785.         }
  786.  
  787.  
  788.         logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
  789.         dprintf("syslogd: restarted\n");
  790. }
  791.  
  792. /*
  793.  * Crack a configuration file line
  794.  */
  795.  
  796. cfline(line, f)
  797.         char *line;
  798.         register struct filed *f;
  799. {
  800.         register char *p;
  801.         register char *q;
  802.         register int i;
  803.         char *bp;
  804.         int pri;
  805.         struct hostent *hp;
  806.         char buf[MAXLINE], ebuf[100];
  807.  
  808.         dprintf("cfline(%s)\n", line);
  809.  
  810.         errno = 0;      /* keep strerror() stuff out of logerror messages */
  811.  
  812.         /* clear out file entry */
  813.         bzero((char *) f, sizeof *f);
  814.         for (i = 0; i <= LOG_NFACILITIES; i++)
  815.                 f->f_pmask[i] = 0;
  816.  
  817.         /* scan through the list of selectors */
  818.         for (p = line; *p && *p != '\t' && *p != ' ';) {
  819.  
  820.                 /* find the end of this facility name list */
  821.                 for (q = p; *q && *q != '\t' && *q != ' ' && *q++ != '.'; )
  822.                         continue;
  823.  
  824.                 /* collect priority name */
  825.                 for (bp = buf; *q && !index("\t,; ", *q); )
  826.                         *bp++ = *q++;
  827.                 *bp = '\0';
  828.  
  829.                 /* skip cruft */
  830.                 while (index(",;", *q)) /* spaces no longer allowed! */
  831.                         q++;
  832.  
  833.                 /* decode priority name */
  834.                 if (*buf == '*')
  835.                         pri = -1;
  836.                 else {
  837.                         pri = decode(*buf == '=' ? buf+1 : buf, prioritynames);
  838.                         if (pri == INTERNAL_NOPRI)
  839.                                 pri = 0;
  840.                         else if (pri < 0 || pri > LOG_PRIMASK) {
  841.                                 (void) sprintf(ebuf, "unknown priority name \"%s\"", buf);
  842.                                 logerror(ebuf);
  843.                                 return;
  844.                         }
  845.                         else
  846.                                 pri = (*buf == '=' ? 1 : -1) << (LOG_PRIMASK - pri);
  847.                   
  848.                 }
  849.  
  850.  
  851.                 /* scan facilities */
  852.                 while (*p && !index("\t.; ", *p)) {
  853.                         for (bp = buf; *p && !index("\t,;. ", *p); )
  854.                                 *bp++ = *p++;
  855.                         *bp = '\0';
  856.                         if (*buf == '*')
  857.                                 for (i = 0; i < LOG_NFACILITIES; i++)
  858.                                         if (pri == 0)
  859.                                                 f->f_pmask[i] = pri;
  860.                                         else
  861.                                                 f->f_pmask[i] |= pri;
  862.                         else {
  863.                                 i = decode(buf, facilitynames);
  864.                                 if (i < 0) {
  865.                                         (void) sprintf(ebuf,
  866.                                             "unknown facility name \"%s\"",
  867.                                             buf);
  868.                                         logerror(ebuf);
  869.                                         return;
  870.                                 }
  871.                                 if (pri == 0)
  872.                                         f->f_pmask[i >> 3] = pri;
  873.                                 else
  874.                                        f->f_pmask[i >> 3] |= pri;
  875.                         }
  876.                         while (*p == ',' || *p == ' ')
  877.                                 p++;
  878.                 }
  879.  
  880.                 p = q;
  881.         }
  882.  
  883.         /* skip to action part */
  884.         while (*p == '\t' || *p == ' ')
  885.                 p++;
  886.  
  887.         switch (*p)
  888.         {
  889.         case '@':
  890.                 if (!InetInuse)
  891.                         break;
  892.                 (void) strcpy(f->f_un.f_forw.f_hname, ++p);
  893.                 hp = gethostbyname(p);
  894.                 if (hp == NULL) {
  895.                         logerror("hostname lookup error");
  896.                         break;
  897.                 }
  898.                 bzero((char *) &f->f_un.f_forw.f_addr,
  899.                          sizeof f->f_un.f_forw.f_addr);
  900.                 f->f_un.f_forw.f_addr.sin_family = AF_INET;
  901.                 f->f_un.f_forw.f_addr.sin_port = LogPort;
  902.                 bcopy(hp->h_addr, (char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_length);
  903.                 f->f_type = F_FORW;
  904.                 break;
  905.  
  906.         default:
  907.                 if ( memcmp(p, "COM",3) == 0)
  908.                         {
  909.                         if ((f->f_file = _open(p, O_WRONLY|O_APPEND, 0)) < 0)
  910.                                 {
  911.                                 f->f_file = F_UNUSED;
  912.                                 logerror(p);
  913.                                 break;
  914.                                 }
  915.                         f->f_type = F_TTY;
  916.                         break;
  917.                         }
  918.                 if (strcmp(p, "CON") == 0)
  919.                         {
  920.                         if ((f->f_file = _open(p, O_WRONLY|O_APPEND,0)) < 0)
  921.                                 {
  922.                                 f->f_file = F_UNUSED;
  923.                                 logerror(p);
  924.                                 break;
  925.                                 }
  926.                         f->f_type = F_CONSOLE;
  927.                         break;
  928.                         }
  929.                 (void) strcpy(f->f_un.f_fname, p);
  930.                 if ((f->f_file = _open(p, O_WRONLY|O_APPEND|O_CREAT, S_IWRITE|S_IREAD)) < 0) {
  931.                         f->f_file = F_UNUSED;
  932.                         logerror(p);
  933.                         break;
  934.                 }
  935.                 f->f_type = F_FILE;
  936.                 break;
  937.         }
  938. }
  939.  
  940. /*
  941.  *  Decode a symbolic name to a numeric value
  942.  */
  943.  
  944. decode(name, codetab)
  945.         char *name;
  946.         CODE *codetab;
  947. {
  948.         register CODE *c;
  949.         register char *p;
  950.         char buf[40];
  951.  
  952.         if (isdigit(*name))
  953.                 return (atoi(name));
  954.  
  955.         (void) strcpy(buf, name);
  956.         for (p = buf; *p; p++)
  957.                 if (isupper(*p))
  958.                         *p = tolower(*p);
  959.         for (c = codetab; c->c_name; c++)
  960.                 if (!strcmp(buf, c->c_name))
  961.                         return (c->c_val);
  962.  
  963.         return (-1);
  964. }
  965.  
  966.  
  967.