]> Zhao Yanbai Git Server - minix.git/commitdiff
Kick out usyslogd in favour of syslogd Giovanni's syslogd port
authorBen Gras <ben@minix3.org>
Mon, 3 Apr 2006 13:07:42 +0000 (13:07 +0000)
committerBen Gras <ben@minix3.org>
Mon, 3 Apr 2006 13:07:42 +0000 (13:07 +0000)
commands/simple/Makefile
commands/simple/usyslogd.c [deleted file]
commands/syslogd/.depend [new file with mode: 0644]
commands/syslogd/CHANGELOG [new file with mode: 0644]
commands/syslogd/Makefile [new file with mode: 0644]
commands/syslogd/README [new file with mode: 0644]
commands/syslogd/README.minix [new file with mode: 0644]
commands/syslogd/logger.c [new file with mode: 0644]
commands/syslogd/syslog.c [new file with mode: 0644]
commands/syslogd/syslog_test.c [new file with mode: 0644]
commands/syslogd/syslogd.c [new file with mode: 0644]

index 97299da3fd50b1a56c125a507fb31986ddf9dbb0..d90344463d393a4da61df793f864bb77cef86ae8 100755 (executable)
@@ -203,7 +203,6 @@ ALL = \
        update \
        uud \
        uue \
-       usyslogd \
        vol \
        wc \
        which \
@@ -864,10 +863,6 @@ uud:       uud.c
        $(CCLD) -o $@ $?
        @install -S 4kw $@
 
-usyslogd:      usyslogd.c
-       $(CCLD) -o $@ $?
-       @install -S 4kw $@
-
 uue:   uue.c
        $(CCLD) -o $@ $?
        @install -S 4kw $@
@@ -1101,7 +1096,6 @@ install:  \
                /usr/bin/uudecode \
        /usr/bin/uue \
                /usr/bin/uuencode \
-       /usr/bin/usyslogd \
        /usr/bin/vol \
        /usr/bin/wc \
        /usr/bin/which \
@@ -1670,9 +1664,6 @@ install:  \
 /usr/bin/uudecode:     /usr/bin/uud
        install -l $? $@
 
-/usr/bin/usyslogd:     usyslogd
-       install -cs -o bin $? $@
-
 /usr/bin/uue:  uue
        install -cs -o bin $? $@
 
diff --git a/commands/simple/usyslogd.c b/commands/simple/usyslogd.c
deleted file mode 100644 (file)
index edc3bab..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Microsyslogd that does basic syslogging.
- */
-
-#include <stdio.h>
-#include <sys/select.h>
-#include <sys/utsname.h>
-#include <sys/types.h>
-#include <time.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-
-char *nodename;
-
-void logline(FILE *outfp, char *proc, char *line)
-{
-       time_t now;
-       struct tm *tm;
-       char *d, *s;
-       time(&now);
-       tm = localtime(&now);
-       d=asctime(tm);
-
-       /* Trim off year and newline. */
-       if((s=strrchr(d, ' ')))
-               *s = '\0';
-       if(s=strchr(d, ' ')) d = s+1;
-       fprintf(outfp, "%s %s: %s\n", d, nodename, line);
-}
-
-void copy(int in_fd, FILE *outfp)
-{
-       static char linebuf[5*1024];
-       int l, acc = 0;
-       while((l=read(in_fd, linebuf, sizeof(linebuf)-2)) > 0) {
-               char *b, *eol;
-               int i;
-               acc += l;
-               for(i = 0; i < l; i++)
-                       if(linebuf[i] == '\0')
-                               linebuf[i] = ' ';
-               if(linebuf[l-1] == '\n') l--;
-               linebuf[l] = '\n';
-               linebuf[l+1] = '\0';
-               b = linebuf;
-               while(eol = strchr(b, '\n')) {
-                       *eol = '\0';
-                       logline(outfp, "kernel", b);
-                       b = eol+1;
-               }
-       }
-
-       /* Nothing sensible happened? Avoid busy-looping. */
-       if(!acc) sleep(1);
-
-       return;
-}
-
-int
-main(int argc, char *argv[])
-{
-       int config_fd, klog_fd, n, maxfd;
-       char *nn;
-       FILE *logfp;
-       struct utsname utsname;
-
-       if(uname(&utsname) < 0) {
-               perror("uname");
-               return 1;
-       }
-
-       nodename = utsname.nodename;
-       if((nn=strchr(nodename, '.')))
-               *nn = '\0';
-
-       if((klog_fd = open("/dev/klog", O_NONBLOCK | O_RDONLY)) < 0) {
-               perror("/dev/klog");
-               return 1;
-       }
-
-       if(!(logfp = fopen("/usr/log/messages", "a"))) {
-               return 1;
-       }
-
-       maxfd = klog_fd;
-
-       while(1) {
-               fd_set fds;
-               FD_ZERO(&fds);
-               FD_SET(klog_fd, &fds);
-               n = select(maxfd+1, &fds, NULL, NULL, NULL);
-               if(n <= 0) {
-                       sleep(1);
-                       continue;
-               }
-               if(FD_ISSET(klog_fd, &fds)) {
-                       copy(klog_fd, logfp);
-               }
-               fflush(logfp);
-               sync();
-       }
-
-       return 0;
-}
-
diff --git a/commands/syslogd/.depend b/commands/syslogd/.depend
new file mode 100644 (file)
index 0000000..5678f4d
--- /dev/null
@@ -0,0 +1,94 @@
+
+logger.o:      /usr/include/ansi.h
+logger.o:      /usr/include/ctype.h
+logger.o:      /usr/include/errno.h
+logger.o:      /usr/include/minix/sys_config.h
+logger.o:      /usr/include/minix/type.h
+logger.o:      /usr/include/stdio.h
+logger.o:      /usr/include/stdlib.h
+logger.o:      /usr/include/string.h
+logger.o:      /usr/include/sys/dir.h
+logger.o:      /usr/include/sys/types.h
+logger.o:      /usr/include/syslog.h
+logger.o:      /usr/include/unistd.h
+logger.o:      logger.c
+
+syslog.o:      /usr/include/ansi.h
+syslog.o:      /usr/include/errno.h
+syslog.o:      /usr/include/fcntl.h
+syslog.o:      /usr/include/minix/ioctl.h
+syslog.o:      /usr/include/minix/sys_config.h
+syslog.o:      /usr/include/minix/type.h
+syslog.o:      /usr/include/net/gen/in.h
+syslog.o:      /usr/include/net/gen/inet.h
+syslog.o:      /usr/include/net/gen/netdb.h
+syslog.o:      /usr/include/net/gen/udp.h
+syslog.o:      /usr/include/net/gen/udp_io.h
+syslog.o:      /usr/include/net/hton.h
+syslog.o:      /usr/include/net/ioctl.h
+syslog.o:      /usr/include/net/netlib.h
+syslog.o:      /usr/include/stdarg.h
+syslog.o:      /usr/include/stdio.h
+syslog.o:      /usr/include/stdlib.h
+syslog.o:      /usr/include/string.h
+syslog.o:      /usr/include/sys/dir.h
+syslog.o:      /usr/include/sys/ioc_cmos.h
+syslog.o:      /usr/include/sys/ioc_disk.h
+syslog.o:      /usr/include/sys/ioc_file.h
+syslog.o:      /usr/include/sys/ioc_memory.h
+syslog.o:      /usr/include/sys/ioc_scsi.h
+syslog.o:      /usr/include/sys/ioc_sound.h
+syslog.o:      /usr/include/sys/ioc_tape.h
+syslog.o:      /usr/include/sys/ioc_tty.h
+syslog.o:      /usr/include/sys/ioctl.h
+syslog.o:      /usr/include/sys/types.h
+syslog.o:      /usr/include/syslog.h
+syslog.o:      /usr/include/time.h
+syslog.o:      /usr/include/unistd.h
+syslog.o:      syslog.c
+
+syslog_test.o: /usr/include/ansi.h
+syslog_test.o: /usr/include/minix/sys_config.h
+syslog_test.o: /usr/include/minix/type.h
+syslog_test.o: /usr/include/sys/types.h
+syslog_test.o: /usr/include/syslog.h
+syslog_test.o: /usr/include/unistd.h
+syslog_test.o: syslog_test.c
+
+syslogd.o:     /usr/include/ansi.h
+syslogd.o:     /usr/include/ctype.h
+syslogd.o:     /usr/include/errno.h
+syslogd.o:     /usr/include/fcntl.h
+syslogd.o:     /usr/include/limits.h
+syslogd.o:     /usr/include/minix/ioctl.h
+syslogd.o:     /usr/include/minix/sys_config.h
+syslogd.o:     /usr/include/minix/type.h
+syslogd.o:     /usr/include/net/gen/in.h
+syslogd.o:     /usr/include/net/gen/netdb.h
+syslogd.o:     /usr/include/net/gen/udp.h
+syslogd.o:     /usr/include/net/gen/udp_io.h
+syslogd.o:     /usr/include/net/hton.h
+syslogd.o:     /usr/include/net/ioctl.h
+syslogd.o:     /usr/include/net/netlib.h
+syslogd.o:     /usr/include/signal.h
+syslogd.o:     /usr/include/stdio.h
+syslogd.o:     /usr/include/stdlib.h
+syslogd.o:     /usr/include/string.h
+syslogd.o:     /usr/include/sys/dir.h
+syslogd.o:     /usr/include/sys/ioc_cmos.h
+syslogd.o:     /usr/include/sys/ioc_disk.h
+syslogd.o:     /usr/include/sys/ioc_file.h
+syslogd.o:     /usr/include/sys/ioc_memory.h
+syslogd.o:     /usr/include/sys/ioc_scsi.h
+syslogd.o:     /usr/include/sys/ioc_sound.h
+syslogd.o:     /usr/include/sys/ioc_tape.h
+syslogd.o:     /usr/include/sys/ioc_tty.h
+syslogd.o:     /usr/include/sys/ioctl.h
+syslogd.o:     /usr/include/sys/select.h
+syslogd.o:     /usr/include/sys/time.h
+syslogd.o:     /usr/include/sys/types.h
+syslogd.o:     /usr/include/sys/wait.h
+syslogd.o:     /usr/include/syslog.h
+syslogd.o:     /usr/include/time.h
+syslogd.o:     /usr/include/unistd.h
+syslogd.o:     syslogd.c
diff --git a/commands/syslogd/CHANGELOG b/commands/syslogd/CHANGELOG
new file mode 100644 (file)
index 0000000..a5455f5
--- /dev/null
@@ -0,0 +1,17 @@
+Version 1.1    Oct. 28, 2000
+  -    first release for testing.
+
+Version 1.2    Jan. 23, 2001
+  -    Changed pidfile directory to '/usr/spool/locks'
+       so at boot old file is deleted.
+  -    Changed the 'debug' variable to 'DbgOpt' so 'debug'
+       can be a preprocessor define from Makefile.
+
+Version 1.3
+  -    Changes for Minix 3.0
+  -    Changed pidfile to /var/run/syslogd.pid and added code
+       for setting pathname from Makefile
+  -    Merged code from usyslogd.c to handle kernel messages.
+  -    Reworked Makefile to make a correct installation
+
+$Id$
diff --git a/commands/syslogd/Makefile b/commands/syslogd/Makefile
new file mode 100644 (file)
index 0000000..385fab4
--- /dev/null
@@ -0,0 +1,50 @@
+##
+##  @(#)Makefile       1.00    Jan. 11, 2000
+##
+##  Makefile for syslogd/klogd
+##  $Id$
+
+BINDIR = /usr/bin
+
+CC     = exec cc
+RM     = rm -f
+EXTRA  = -DPIDFILE=\"/var/run/syslogd.pid\"
+CPPFLAGS= -D_MINIX -D_POSIX_SOURCE -Ddebug=0 $(EXTRA) -I.
+CFLAGS = -m -O $(CPPFLAGS)
+MKDEP  = mkdep "$(CC) -E $(CPPFLAGS)"
+LDFLAGS = -i -o $@
+TARGETS = logger syslogd
+
+SRCS = logger.c syslog.c syslog_test.c syslogd.c
+OBJS = logger.o syslog.o syslog_test.o syslogd.o
+
+all: $(TARGETS)        
+
+syslogd:       syslogd.o
+       $(CC) $? $(LDFLAGS)
+       @install -S 8kw $@
+
+syslog_test: syslog_test.o syslog.o
+       $(CC) syslog_test.o syslog.o $(LDFLAGS)
+       @install -S 2kw $@
+
+logger: logger.o syslog.o
+       $(CC) logger.o syslog.o $(LDFLAGS)
+       @install -S 2kw $@
+
+clean:
+       $(RM) $(OBJS) $(TARGETS) syslog_test *.BAK core
+
+install:       install-bin install-sys
+
+install-bin:   $(BINDIR)/logger $(BINDIR)/syslog_test $(BINDIR)/syslogd
+$(BINDIR)/logger:      logger
+       install -cs -m 755 -o bin -g operator $? $@
+$(BINDIR)/syslog_test: syslog_test
+       install -cs -m 755 -o bin -g operator $? $@
+$(BINDIR)/syslogd:     syslogd
+       install -cs -m 700 -o root -g operator $? $@
+install-sys: /etc/syslog.conf
+/etc/syslog.conf:      syslog.conf
+       install -c -m 644 -o root -g operator $? $@
+
diff --git a/commands/syslogd/README b/commands/syslogd/README
new file mode 100644 (file)
index 0000000..8c34903
--- /dev/null
@@ -0,0 +1,69 @@
+This is just syslogd and the test programs now. syslog() is in libc 4.2
+syslogd has been changed to use /proc/kmsg for kernel messages. It also
+avoids making any terminal it opens its controlling terminal. Otherwise
+we have a dodgy race condition between processes connecting to terminals
+which can result in the terminal having the wrong group at the wrong time.
+The syslog() in libc 4.2 needs changing to use O_NOCTTY on its opens as
+well.
+
+Mike Jagdis    Internet: jaggy@purplet.demon.co.uk
+               FidoNet:  Mike Jagdis, 2:252/305
+
+---------------------------------------------------------------------------
+
+                           Syslogd and Syslog.o
+
+These are the syslogd and syslog ported from 4.3BSD (that's the new one with
+the *very* flexible config file).  
+
+Syslogd is essentially unchanged from the 4.3BSD, with the exception that
+*nothing* is ever logged to the console (BAD thing to do on a UNIXpc).  You
+can configure it (via /etc/syslog.conf) to log messages in different
+logfiles (depending upon the sender's facility code and the priority), log
+to users' terminals (same dependancies), and if things get real bad, it can
+do a wall (write-all; same dependancies).
+
+Syslog is really only modified in that it uses UDP datagrams because I had
+no luck at all using UNIX domain sockets on the 3B1.  See syslog.h for
+facility codes and priorities that can be used.
+
+
+BUGS:
+Messages from facilities LOG_KERN, LOG_USER, and LOG_PRT never can be
+wall-ed, no matter how high the priority.  I'm still trying to decide if
+this is a bug or a feature. :-)
+
+
+ALSO INCLUDED:
+
+Syslog_test, sendlog (to use from shell scripts) and logger (for use in
+shell script also).
+
+NEEDED:
+
+The resolver routines in libresolv.a are not needed, but allow you to log to
+hosts not present in /etc/hosts and to accept logging from same.
+
+-----------------------------------------------------------------------
+
+Fixed up UNIX domain socket code, added Linux specific code to read messages
+from the kernel.
+
+The #ifdefs are now :-
+
+SYSLOG_INET    listen on a UDP socket (syslogd)
+               log via UDP (syslog library call)
+
+SYSLOG_UNIXAF  listen on a UNIX domain socker (syslogd)
+               log via UNIX domain (syslogd library)
+
+SYSLOG_KERNEL  fork a second copy to read kernel messages using
+               syslog system call.
+
+syslogd should be built with one or more of these flags, libsyslog.a should
+be built with SYSLOG_INET or SYSLOG_UNIXAF, SYSLOG_INET is used in preference
+to SYSLOG_UNIXAF.
+
+readlog is a program which reads from the kernel and records the messages
+it finds in syslogd via the normal library call interface, it can be run
+instead of building syslogd with SYSLOG_KERNEL.
diff --git a/commands/syslogd/README.minix b/commands/syslogd/README.minix
new file mode 100644 (file)
index 0000000..2fcba23
--- /dev/null
@@ -0,0 +1,28 @@
+
+
+   This is the porting to Minix of the "syslogd" facility
+   available on many other *nix systems.
+
+   Since I' m still using an old 286 machine for my Minix
+   environment, I choosed to start from an old implementation
+   which has only the basic features. The result is a smaller
+   program, more suitable for 16 bits machines.
+
+   The file syslog.c should be included in C compiler library
+   (libc.a) or directly linked with prorams requiring syslog.
+
+   If you choose the former solution, you must recreate the 
+   library.  After having copied the file syslog.c to the 
+   directory '/usr/src/libs/other' you have to modify the 
+   Makefile in this directory adding syslog.c.
+
+   Then issue a 'make' command in the '/usr/src/libs' and wait 
+   a while.  Then issue 'make install' to install the new object.
+
+   NOTE:   The network must be configured, up and running for
+          the package to work
+
+   Giovanni Falzoni <gfalzoni@inwind.it>
+
+   $Id$
+
diff --git a/commands/syslogd/logger.c b/commands/syslogd/logger.c
new file mode 100644 (file)
index 0000000..da26df8
--- /dev/null
@@ -0,0 +1,188 @@
+/* Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * #ifndef lint
+ * char copyright[] =
+ * "@(#) Copyright (c) 1983 Regents of the University of California.\n\
+ *  All rights reserved.\n";
+ * #endif
+ *
+ * #ifndef lint
+ * static char sccsid[] = "@(#)logger.c        6.8 (Berkeley) 6/29/88";
+ * #endif
+ *
+ * Porting to Minix by G. Falzoni <gfalzoni@inwind.it>
+ * $Id$
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+**     LOGGER -- read and log utility
+**
+**     This program reads from an input and arranges to write the
+**     result on the system log, along with a useful tag.
+*/
+
+#define  SYSLOG_NAMES
+#include <syslog.h>
+
+/*
+**     Name:           void bailout(char *msg, char *arg);
+**     Function:       Handles error exit.
+*/
+void bailout(const char *msg, const char *arg)
+{
+
+  fprintf(stderr, "logger: %s %s\n", msg, arg);
+  exit(EXIT_FAILURE);
+}
+
+/*
+**     Name:           int decode(char *name, struct code * codetab);
+**     Function:       Decodes a name to the equivalent priority/facility.
+*/
+int decode(char *name, const struct _code * codetab)
+{
+  const struct _code *c;
+
+  if (isdigit(*name)) return(atoi(name));
+
+  for (c = codetab; c->c_name; c++)
+       if (!strcasecmp(name, c->c_name)) return(c->c_val);
+
+  return(-1);
+}
+
+/*
+**     Name:           int pencode(char *s);
+**     Function:       Decode a symbolic name (facility/priority)
+**                     to a numeric value.
+*/
+int pencode(char *s)
+{
+  char *save;
+  int fac, lev;
+
+  for (save = s; *s && *s != '.'; ++s);
+  if (*s) {
+       *s = '\0';
+       fac = decode(save, FacNames);
+       if (fac < 0) bailout("unknown facility name:", save);
+       *s++ = '.';
+  } else {
+       fac = 0;
+       s = save;
+  }
+  lev = decode(s, PriNames);
+  if (lev < 0) bailout("unknown priority name:", save);
+  return((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
+}
+
+/*
+**     Name:           int main(int argc, char **argv);
+**     Function:       Main entry for logger.
+*/
+int main(int argc, char **argv)
+{
+  int pri = LOG_NOTICE;
+  int ch, logflags = 0;
+  char *tag, buf[200];
+  static const char usage[] =
+  "[-i] [-f file] [-p pri] [-t tag] [ message ... ]";
+
+  tag = NULL;
+  while ((ch = getopt(argc, argv, "f:ip:t:")) != EOF) {
+       switch ((char) ch) {
+           case 'f':           /* file to log */
+               if (freopen(optarg, "r", stdin) == NULL) {
+                       bailout(strerror(errno), optarg);
+               }
+               break;
+           case 'i':           /* log process id also */
+               logflags |= LOG_PID;
+               break;
+           case 'p':           /* priority */
+               pri = pencode(optarg);
+               break;
+           case 't':           /* tag */
+               tag = optarg;
+               break;
+           case '?':
+           default:    bailout(usage, "");     break;
+       }
+  }
+  argc -= optind;
+  argv += optind;
+
+  /* Setup for logging */
+  openlog(tag ? tag : getlogin(), logflags, 0);
+  fclose(stdout);
+
+  if (argc > 0) {              /* Log input line if appropriate */
+       char *p, *endp;
+       int len;
+
+       for (p = buf, endp = buf + sizeof(buf) - 1;;) {
+               len = strlen(*argv);
+               if (p + len < endp && p > buf) {
+                       *--p = '\0';
+                       syslog(pri, buf);
+                       p = buf;
+               }
+               if (len > sizeof(buf) - 1) {
+                       syslog(pri, *argv++);
+                       if (!--argc) break;
+               } else {
+                       memcpy(p, *argv++, len);
+                       p += len;
+                       if (!--argc) break;
+                       *p++ = ' ';
+                       *--p = '\0';
+               }
+       }
+       if (p != buf) {
+               *p = '\0';
+               syslog(pri, buf);
+       }
+  } else                       /* Main loop */
+       while (fgets(buf, sizeof(buf), stdin) != NULL) syslog(pri, buf);
+
+  return EXIT_SUCCESS;
+}
+
+/** logger.c **/
diff --git a/commands/syslogd/syslog.c b/commands/syslogd/syslog.c
new file mode 100644 (file)
index 0000000..caf2120
--- /dev/null
@@ -0,0 +1,167 @@
+/* Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * #if defined(LIBC_SCCS) && !defined(lint)
+ * static char sccsid[] = "@(#)syslog.c    8.4 (Berkeley) 3/18/94";
+ * #endif
+ *
+ * Author: Eric Allman
+ * Modified to use UNIX domain IPC by Ralph Campbell
+ * Patched March 12, 1996 by A. Ian Vogelesang <vogelesang@hdshq.com>
+ * Rewritten by Martin Mares <mj@atrey.karlin.mff.cuni.cz> on May 14, 1997
+ * Rewritten by G. Falzoni <gfalzoni@inwind.it> for porting to Minix
+ *
+ * $Id$
+ */
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <sys/ioctl.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+#include <net/gen/netdb.h>
+#include <errno.h>
+#include <net/gen/inet.h>
+
+static int LogPid = (-1);
+static int nfd = (-1);
+static int LogFacility = LOG_USER;
+static int LogFlags = 0;
+static char TagBuffer[40] = "syslog";
+
+/*
+** OPENLOG -- open system log
+**     - establishes a channel to syslogd using UDP device
+**       (port 514 is used _ syslog/udp)
+**     - stores program tag (if not NULL) and other options
+**       for use by syslog
+*/
+void openlog(const char *ident, int option, int facility)
+{
+  struct nwio_udpopt udpopt;
+
+  /* Stores logging flags */
+  LogFlags = option & (LOG_PID | LOG_PERROR | LOG_CONS);
+  /* Stores process id. if LOG_PID was specified */
+  if (option & LOG_PID) LogPid = getpid();
+  /* Stores the requested facility */
+  LogFacility = facility;
+  /* Stores log tag if supplied */
+  if (ident != NULL && *ident != '0' && ident != TagBuffer) {
+       strncpy(TagBuffer, ident, sizeof(TagBuffer));
+       TagBuffer[sizeof(TagBuffer) - 1] = '0';
+  }
+
+  /* Opens channel to syslog daemon via UDP device */
+  /* Static values used to minimize code */
+  if (option & LOG_NDELAY) {
+       /* Opens UDP device */
+       if ((nfd = open(UDP_DEVICE, O_RDWR)) < 0) {
+                /* Report error */ ;
+       }
+       /* Sets options for UDP device */
+       udpopt.nwuo_flags = NWUO_SHARED | NWUO_LP_SET | NWUO_DI_LOC |
+               NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET |
+               NWUO_RWDATONLY | NWUO_DI_IPOPT;
+       udpopt.nwuo_locaddr = udpopt.nwuo_remaddr = htonl(0x7F000001L);
+       udpopt.nwuo_locport = udpopt.nwuo_remport = htons(514);
+       if (ioctl(nfd, NWIOSUDPOPT, &udpopt) < 0 ||
+           ioctl(nfd, NWIOGUDPOPT, &udpopt) < 0) {
+                /* Report error */ ;
+       }
+  }
+  return;
+}
+
+/*
+**  SYSLOG -- print message on log file
+**
+**  This routine looks a lot like printf, except that it outputs to the
+**  log file instead of the standard output.  Also:
+**     - adds a timestamp,
+**     - prints the module name in front of the message,
+**     - has some other formatting types (or will sometime),
+**     - adds a newline on the end of the message.
+**
+** The output of this routine is intended to be read by syslogd(8).
+*/
+void syslog(int lprty, const char *msg,...)
+{
+  time_t now;
+  char buff[512];
+  int len, rc;
+  va_list ap;
+
+  /* First log message open chnnel to syslog */
+  if (nfd < 0) openlog(TagBuffer, LogFlags | LOG_NDELAY, LogFacility);
+  time(&now);
+  len = sprintf(buff, "<%d>%.15s %s: ",
+               LogFacility | lprty, ctime(&now) + 4, TagBuffer);
+  if (LogFlags & LOG_PID) {
+       len -= 2;
+       len += sprintf(buff + len, "[%d]: ", LogPid);
+  }
+  va_start(ap, msg);
+  len += vsprintf(buff + len, msg, ap);
+  va_end(ap);
+  rc = write(nfd, buff, len);
+  if ((rc != len && LogFlags & LOG_CONS) || LogFlags & LOG_PERROR) {
+       write(STDERR_FILENO, buff, len);
+       write(STDERR_FILENO, "\n", 1);
+  }
+  return;
+}
+
+/*
+**  CLOSELOG -- close access to syslogd
+**     - closes UDP channel
+**     - restores default values
+*/
+void closelog(void)
+{
+
+  close(nfd);
+  LogPid = nfd = -1;
+  LogFacility = LOG_USER;
+  LogFlags = 0;
+  return;
+}
+
+/** syslog.c **/
diff --git a/commands/syslogd/syslog_test.c b/commands/syslogd/syslog_test.c
new file mode 100644 (file)
index 0000000..9a5bced
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+**     syslog_test
+**
+**     Author:         Giovanni Falzoni <gfalzoni@inwind.it>
+**     $Id$
+*/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <syslog.h>
+
+/*
+**     SYSLOG TEST
+**     Very simple utility to test syslog facility.
+*/
+void main(void)
+{
+  int ix;
+
+  openlog("syslog_test", LOG_PID | LOG_NDELAY | LOG_PERROR | LOG_CONS, LOG_DAEMON);
+
+  for (ix = LOG_EMERG; ix <= LOG_DEBUG; ix += 1) {
+       sleep(2);
+       syslog(ix, "message from test program - log level %d", ix);
+  }
+  closelog();
+  return;
+}
+
+/** syslog_test.c **/
diff --git a/commands/syslogd/syslogd.c b/commands/syslogd/syslogd.c
new file mode 100644 (file)
index 0000000..a17afba
--- /dev/null
@@ -0,0 +1,924 @@
+/*
+**  Copyright (c) 1983, 1988
+**  The Regents of the University of California.  All rights reserved.
+**
+**  Redistribution and use in source and binary forms, with or without
+**  modification, are permitted provided that the following conditions
+**  are met:
+**  1. Redistributions of source code must retain the above copyright
+**     notice, this list of conditions and the following disclaimer.
+**  2. Redistributions in binary form must reproduce the above copyright
+**     notice, this list of conditions and the following disclaimer in the
+**     documentation and/or other materials provided with the distribution.
+**  3. All advertising materials mentioning features or use of this software
+**     must display the following acknowledgement:
+**       This product includes software developed by the University of
+**       California, Berkeley and its contributors.
+**  4. Neither the name of the University nor the names of its contributors
+**     may be used to endorse or promote products derived from this software
+**     without specific prior written permission.
+**
+**  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+**  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+**  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+**  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+**  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+**  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+**  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+**  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+**  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+**  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+**  SUCH DAMAGE.
+**
+**  #ifndef lint
+**  char copyright2[] =
+**  "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
+**   All rights reserved.\n";
+**  #endif
+**
+**  #ifndef lint
+**  static char sccsid[] = "@(#)syslogd.c      5.27 (Berkeley) 10/10/88";
+**  #endif
+**
+**  -----------------------------------------------------------------------
+**
+**  SYSLOGD -- log system messages
+**     This program implements a system log.
+**     It takes a series of lines and outputs them according to the setup
+**     defined in the configuration file.
+**     Each line may have a priority, signified as "<n>" as
+**     the first characters of the line.  If this is
+**     not present, a default priority is used.
+**
+**     To kill syslogd, send a signal 15 (terminate).
+**     A signal 1 (hup) will cause it to reread its configuration file.
+**
+**  Defined Constants:
+**     MAXLINE   -- the maximimum line length that can be handled.
+**     MAXSVLINE -- the length of saved messages (for filtering)
+**     DEFUPRI   -- the default priority for user messages
+**     DEFSPRI   -- the default priority for kernel messages
+**
+**  Author: Eric Allman
+**  extensive changes by Ralph Campbell
+**  more extensive changes by Eric Allman (again)
+**  changes by Steve Lord
+**
+**  Extensive rewriting by G. Falzoni <gfalzoni@inwind.it> for porting to Minix
+** 
+**  $Log$
+**  Revision 1.1  2006/04/03 13:07:42  beng
+**  Kick out usyslogd in favour of syslogd Giovanni's syslogd port
+**
+**  Revision 1.3  2005/09/16 10:10:12  lsodgf0
+**  Rework for Minix 3.  Adds kernel logs from /dev/klogd
+**
+**  $Id$
+*/
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
+#include <net/gen/netdb.h>
+
+#define SYSLOG_NAMES
+#include <syslog.h>
+#define KLOGD 1
+/** Define following values to your requirements **/
+#define        MAXLINE         512     /* maximum line length */
+#define        MAXSVLINE       256     /* maximum saved line length */
+
+#define DEFUPRI                (LOG_USER|LOG_NOTICE)
+#define DEFSPRI        (LOG_KERN|LOG_CRIT)
+
+/* Flags to logmsg() */
+#define IGN_CONS       0x001   /* don't print on console */
+#define SYNC_FILE      0x002   /* do fsync on file after printing */
+#define ADDDATE                0x004   /* add a date to the message */
+#define MARK           0x008   /* this message is a mark */
+
+#define        CTTY            "/dev/log"      /* Minix log device (console) */
+
+#define        dprintf if(DbgOpt!=0)printf
+#if debug == 0
+#define DEBUG(statement)
+#else
+#define DEBUG(statement) statement
+#endif
+#if !defined PIDFILE
+#define PIDFILE        "/var/run/syslogd.pid"
+#endif
+
+#define UNAMESZ                8       /* length of a login name */
+#define MAXUNAMES      20      /* maximum number of user names */
+#define MAXFNAME       200     /* max file pathname length */
+#define MAXHOSTNAMELEN         64      /* max length of FQDN host name */
+
+/* Intervals at which we flush out "message repeated" messages,
+ * in seconds after previous message is logged.  After each flush,
+ * we move to the next interval until we reach the largest.  */
+#define TIMERINTVL     30      /* interval for checking flush, mark */
+#define INTERVAL1      30
+#define INTERVAL2      60
+#define        MAXREPEAT ((sizeof(repeatinterval)/sizeof(repeatinterval[0]))-1)
+#define        REPEATTIME(f) ((f)->f_time+repeatinterval[(f)->f_repeatcount])
+#define        BACKOFF(f) {if(++(f)->f_repeatcount>MAXREPEAT)(f)->f_repeatcount=MAXREPEAT;}
+
+/* Values for f_type */
+#define F_UNUSED       0       /* unused entry */
+#define F_FILE                 1       /* regular file */
+#define F_TTY          2       /* terminal */
+#define F_CONSOLE      3       /* console terminal */
+#define F_FORW                 4       /* remote machine */
+#define F_USERS        5       /* list of users */
+#define F_WALL                 6       /* everyone logged on */
+
+#define max(a,b) ((a)>=(b)?(a):(b))
+
+/* This structure represents the files that will have log copies printed */
+struct filed {
+  struct filed *f_next;                /* next in linked list */
+  short f_type;                        /* entry type, see below */
+  short f_file;                        /* file descriptor */
+  time_t f_time;               /* time this was last written */
+  char f_pmask[LOG_NFACILITIES + 1];   /* priority mask */
+  union {
+       char f_uname[MAXUNAMES][UNAMESZ + 1];
+       char f_fname[MAXFNAME];
+  } f_un;
+  char f_prevline[MAXSVLINE];  /* last message logged */
+  char f_lasttime[16];         /* time of last occurrence */
+  char f_prevhost[MAXHOSTNAMELEN + 1]; /* host from which recd. */
+  int f_prevpri;               /* pri of f_prevline */
+  int f_prevlen;               /* length of f_prevline */
+  int f_prevcount;             /* repetition cnt of prevline */
+  int f_repeatcount;           /* number of "repeated" msgs */
+  int f_flags;                 /* store some additional flags */
+};
+
+static const char *const TypeNames[] =
+{
+ "UNUSED", "FILE", "TTY", "CONSOLE", "FORW", "USERS", "WALL", NULL,
+};
+
+static struct filed *Files = NULL;
+static struct filed consfile;
+static int DbgOpt = 0;         /* debug flag */
+static char LocalHostName[MAXHOSTNAMELEN + 1]; /* our hostname */
+static int Initialized = 0;    /* set when we have initialized ourselves */
+static int MarkInterval = 20 * 60;     /* interval between marks in seconds */
+static int MarkSeq = 0;                /* mark sequence number */
+static time_t now;
+
+static const char *ConfFile = "/etc/syslog.conf";
+static const char *PidFile = PIDFILE;  /* "/var/run/syslogd.pid" */
+static const char ctty[] = CTTY;
+
+static const char ProgName[] = "syslogd:";
+static const char version[] = "1.3 (Minix)";
+static const char usage[] =
+ /* */ "usage:\tsyslogd [-d] [-m markinterval] [-f conf-file]\n"
+       "\t\t[-p listeningport] [-v] [-?]\n" ;
+static const int repeatinterval[] =
+ /* */ {INTERVAL1, INTERVAL2,};        /* # of secs before flush */
+
+/*
+**  Name:      void wallmsg(struct filed *fLog, char *message);
+**  Function:  Write the specified message to either the entire
+**             world, or a list of approved users.
+*/
+void wallmsg(struct filed * fLog, char *message)
+{
+
+  return;
+}
+
+/*
+**  Name:      void fprintlog(struct filed *fLog, int flags, char *message);
+**  Function:
+*/
+void fprintlog(struct filed * fLog, int flags, char *message)
+{
+  int len;
+  char line[MAXLINE + 1];
+  char repbuf[80];
+
+  if (message == NULL) {
+       if (fLog->f_prevcount > 1) {
+               sprintf(repbuf, "last message repeated %d times", fLog->f_prevcount);
+               message = repbuf;
+       } else
+               message = fLog->f_prevline;
+  }
+  sprintf(line, "%s %s %s", fLog->f_lasttime, fLog->f_prevhost, message);
+  DEBUG(dprintf("Logging to %s", TypeNames[fLog->f_type]);)
+  fLog->f_time = now;
+  switch (fLog->f_type) {
+      case F_UNUSED:           /* */
+       DEBUG(dprintf("\n");)
+       break;
+      case F_CONSOLE:
+       if (flags & IGN_CONS) {
+      case F_FORW:             /* */
+               DEBUG(dprintf(" (ignored)\n");)
+               break;
+       }                       /* else Fall Through */
+      case F_TTY:
+      case F_FILE:
+       DEBUG(dprintf(" %s\n", fLog->f_un.f_fname);)
+       strcat(line, fLog->f_type != F_FILE ? "\r\n" : "\n");
+       len = strlen(line);
+       if (write(fLog->f_file, line, len) != len) {
+                /* Handle errors */ ;
+       } else if (flags & SYNC_FILE)
+               sync();
+       break;
+      case F_USERS:
+      case F_WALL:
+       DEBUG(dprintf("\n");)
+       strcat(line, "\r\n");
+       wallmsg(fLog, line);
+       break;
+  }
+  fLog->f_prevcount = 0;
+  return;
+}
+
+/*
+**  Name:      void logmsg(int pri, char *msg, char *from, int flags);
+**  Function:  Log a message to the appropriate log files, users, etc.
+**             based on the priority.
+*/
+void logmsg(int pri, char *msg, char *from, int flags)
+{
+  struct filed *f;
+  int fac, prilev;
+  int omask, msglen;
+  char *timestamp;
+
+  DEBUG(dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", pri, flags, from, msg);)
+/*
+  omask = sigblock(__sigmask(SIGHUP) | __sigmask(SIGALRM));
+*/
+  /* Check to see if msg looks non-standard. */
+  msglen = strlen(msg);
+  if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
+      msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
+       flags |= ADDDATE;
+
+  time(&now);
+  if (flags & ADDDATE)
+       timestamp = ctime(&now) + 4;
+  else {
+       timestamp = msg;
+       msg += 16;
+       msglen -= 16;
+  }
+
+  /* Extract facility and priority level */
+  fac = (flags & MARK) ? LOG_NFACILITIES : LOG_FAC(pri);
+  prilev = LOG_PRI(pri);
+
+  /* Log the message to the particular outputs */
+  if (!Initialized) {
+       /* Not yet initialized. Every message goes to console */
+       f = &consfile;
+       f->f_file = open(ctty, O_WRONLY | O_NOCTTY);
+       if (f->f_file >= 0) {
+               if (!DbgOpt) setsid();
+               fprintlog(f, flags, msg);
+               close(f->f_file);
+       }
+  } else {
+       for (f = Files; f; f = f->f_next) {
+
+               /* Skip messages that are incorrect priority */
+               if (f->f_pmask[fac] < prilev || f->f_pmask[fac] == INTERNAL_NOPRI)
+                       continue;
+
+               if (f->f_type == F_CONSOLE && (flags & IGN_CONS)) continue;
+
+               /* Don't output marks to recently written files */
+               if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
+                       continue;
+
+               /* Suppress duplicate lines to this file */
+               if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
+                   !strcmp(msg, f->f_prevline) &&
+                   !strcmp(from, f->f_prevhost)) {
+                       strncpy(f->f_lasttime, timestamp, 15);
+                       f->f_prevcount += 1;
+                       DEBUG(dprintf("msg repeated %d times, %ld sec of %d\n",
+                               f->f_prevcount, now - f->f_time,
+                               repeatinterval[f->f_repeatcount]);)
+                       /* If domark would have logged this by now,
+                        * flush it now (so we don't hold isolated
+                        * messages), but back off so we'll flush
+                        * less often in the future. */
+                       if (now > REPEATTIME(f)) {
+                               fprintlog(f, flags, (char *) NULL);
+                               BACKOFF(f);
+                       }
+               } else {
+                       /* New line, save it */
+                       if (f->f_prevcount) fprintlog(f, 0, (char *) NULL);
+                       f->f_repeatcount = 0;
+                       strncpy(f->f_lasttime, timestamp, 15);
+                       strncpy(f->f_prevhost, from, sizeof(f->f_prevhost));
+                       if (msglen < MAXSVLINE) {
+                               f->f_prevlen = msglen;
+                               f->f_prevpri = pri;
+                               strcpy(f->f_prevline, msg);
+                               fprintlog(f, flags, (char *) NULL);
+                       } else {
+                               f->f_prevline[0] = 0;
+                               f->f_prevlen = 0;
+                               fprintlog(f, flags, msg);
+                       }
+               }
+       }
+  }
+
+/*
+  sigsetmask(omask);
+*/
+  return;
+}
+
+/*
+**  Name:      void logerror(char *type);
+**  Function:  Prints syslogd errors in some place.
+*/
+void logerror(char *type)
+{
+  char buf[100];
+
+  if (errno == 0) sprintf(buf, "%s %s", ProgName, type);
+
+  else if (errno >= _NERROR)
+       sprintf(buf, "%s %s - error %d", ProgName, type, errno);
+
+  else
+       sprintf(buf, "%s %s - %s", ProgName, type, strerror(errno));
+
+  errno = 0;
+  dprintf("%s\n", buf);
+  logmsg(LOG_SYSLOG | LOG_ERR, buf, LocalHostName, ADDDATE);
+  return;
+}
+
+/*
+**  Name:      void die(int sig);
+**  Function:  Signal handler for kill signals.
+*/
+void die(int sig)
+{
+  struct filed *f;
+  char buf[100];
+
+  for (f = Files; f != NULL; f = f->f_next) {
+       /* Flush any pending output */
+       if (f->f_prevcount) fprintlog(f, 0, NULL);
+  }
+  if (sig >= 0) {
+       DEBUG(dprintf("%s exiting on signal %d\n", ProgName, sig);)
+       sprintf(buf, "exiting on signal %d", sig);
+       errno = 0;
+       logerror(buf);
+  }
+  unlink(PidFile);
+  exit(sig == (-1) ? EXIT_FAILURE : EXIT_SUCCESS);
+}
+
+/*
+**  Name:      void domark(int sig);
+**  Function:  Signal handler for alarm.
+**             Used for messages filtering and mark facility.
+*/
+void domark(int sig)
+{
+  struct filed *f;
+
+  now = time(NULL);
+  MarkSeq += TIMERINTVL;
+  if (MarkSeq >= MarkInterval) {
+       logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE | MARK);
+       MarkSeq = 0;
+  }
+  for (f = Files; f; f = f->f_next) {
+       if (f->f_prevcount && now >= REPEATTIME(f)) {
+               DEBUG(dprintf("flush %s: repeated %d times, %d sec.\n",
+                       TypeNames[f->f_type], f->f_prevcount,
+                       repeatinterval[f->f_repeatcount]);)
+               fprintlog(f, 0, NULL);
+               BACKOFF(f);
+       }
+  }
+  signal(SIGALRM, domark);
+  alarm(TIMERINTVL);
+  return;
+}
+
+/*
+**  Name:      int decode(char *name, struct _code *codetab);
+**  Function:  Decode a symbolic name to a numeric value
+*/
+int decode(char *name, const struct _code *codetab)
+{
+  const struct _code *c;
+  char *p;
+  char buf[40];
+
+  DEBUG(dprintf("symbolic name: %s", name);)
+  if (isdigit(*name)) return (atoi(name));
+
+  strcpy(buf, name);
+  for (p = buf; *p; p += 1) {
+       if (isupper(*p)) *p = tolower(*p);
+  }
+  for (c = codetab; c->c_name; c += 1) {
+       if (!strcmp(buf, c->c_name)) {
+               DEBUG(dprintf(" ==> %d\n", c->c_val);)
+               return (c->c_val);
+       }
+  }
+  return (-1);
+}
+
+/*
+**  Name:      void cfline(char *line, struct filed *f);
+**  Function:  Parse a configuration file line
+*/
+void cfline(char *line, struct filed * fLog)
+{
+  char *p, *q, *bp;
+  int ix, pri;
+  char buf[MAXLINE];
+  char xbuf[200];
+
+  DEBUG(dprintf("cfline(%s)\n", line);)
+
+  /* Keep sys_errlist stuff out of logerror messages */
+  errno = 0;
+
+  /* Clear out file entry */
+  memset(fLog, 0, sizeof(*fLog));
+  for (ix = 0; ix <= LOG_NFACILITIES; ix += 1) /* */
+       fLog->f_pmask[ix] = INTERNAL_NOPRI;
+
+  /* Scan through the list of selectors */
+  for (p = line; *p && *p != '\t';) {
+
+       /* Find the end of this facility name list */
+       for (q = p; *q && *q != '\t' && *q++ != '.';) continue;
+
+       /* Collect priority name */
+       for (bp = buf; *q && !strchr("\t,;", *q);) *bp++ = *q++;
+       *bp = '\0';
+
+       /* Skip cruft */
+       while (strchr(", ;", *q)) q++;
+
+       /* Decode priority name */
+       pri = decode(buf, PriNames);
+       if (pri < 0) {
+               sprintf(xbuf, "unknown priority name \"%s\"", buf);
+               logerror(xbuf);
+               return;
+       }
+
+       /* Scan facilities */
+       while (*p && !strchr("\t.;", *p)) {
+               for (bp = buf; *p && !strchr("\t,;.", *p);) *bp++ = *p++;
+               *bp = '\0';
+               if (*buf == '*') {
+                       for (ix = 0; ix <= LOG_NFACILITIES; ix += 1)
+                               if ((fLog->f_pmask[ix] < pri) ||
+                                   (fLog->f_pmask[ix] == INTERNAL_NOPRI)) {
+                                       fLog->f_pmask[ix] = pri;
+                               }
+               } else {
+                       ix = decode(buf, FacNames);
+                       if (ix < 0) {
+                               sprintf(xbuf, "unknown facility name \"%s\"", buf);
+                               logerror(xbuf);
+                               return;
+                       }
+                       if ((fLog->f_pmask[ix >> 3] < pri) ||
+                       (fLog->f_pmask[ix >> 3] == INTERNAL_NOPRI)) {
+                               fLog->f_pmask[ix >> 3] = pri;
+                       }
+               }
+               while (*p == ',' || *p == ' ') p++;
+       }
+       p = q;
+  }
+
+  /* Skip to action part */
+  while (*p == '\t' || *p == ' ') p++;
+
+  DEBUG(dprintf("leading char in action: %c\n", *p);)
+  switch (*p) {
+      case '@':                        /* Logging to a remote host */
+       break;                  /* NOT IMPLEMENTED */
+
+      case '/':                        /* Logging to a local file/device */
+       strcpy(fLog->f_un.f_fname, p);
+       DEBUG(dprintf("filename: %s\n", p);     /* ASP */)
+       if ((fLog->f_file = open(p, O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY, 0644)) < 0) {
+               fLog->f_file = F_UNUSED;
+               sprintf(xbuf, "unknown file/device (%s)", p);
+               logerror(xbuf);
+               break;
+       }
+       if (isatty(fLog->f_file)) {
+               if (!DbgOpt) setsid();
+               fLog->f_type = F_TTY;
+       } else
+               fLog->f_type = F_FILE;
+       if (strcmp(p, ctty) == 0) fLog->f_type = F_CONSOLE;
+       break;
+
+      case '*':                        /* Logging to all users */
+       DEBUG(dprintf("write-all\n");)
+       fLog->f_type = F_WALL;
+       break;
+
+      default:                 /* Logging to selected users */
+       DEBUG(dprintf("users: %s\n", p);        /* ASP */)
+       for (ix = 0; ix < MAXUNAMES && *p; ix += 1) {
+               for (q = p; *q && *q != ',';) q += 1;
+               strncpy(fLog->f_un.f_uname[ix], p, UNAMESZ);
+               if ((q - p) > UNAMESZ)
+                       fLog->f_un.f_uname[ix][UNAMESZ] = '\0';
+               else
+                       fLog->f_un.f_uname[ix][q - p] = '\0';
+               while (*q == ',' || *q == ' ') q++;
+               p = q;
+       }
+       fLog->f_type = F_USERS;
+       break;
+  }
+}
+
+/*
+**  Name:      void printline(char *hname, char *msg);
+**  Function:  Takes a raw input line, decodes the message and
+**             prints the message on the appropriate log files.
+*/
+void printline(char *hname, char *msg)
+{
+  char line[MAXLINE + 1];
+  char *p = msg, *q = line;
+  int ch, pri = DEFUPRI;
+
+  /* Test for special codes */
+  if (*p == '<') {
+       pri = 0;
+       while (isdigit(*++p)) {
+               if ((*p - '0') < 8) {
+                       /* Only 3 bits allocated for pri -- ASP */
+                       pri = 10 * pri + (*p - '0');
+               } else
+                       pri = 10 * pri + 7;
+       }
+       if (*p == '>') ++p;
+  }
+  if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) pri = DEFUPRI;
+
+  /* Does not allow users to log kernel messages */
+  if (LOG_FAC(pri) == LOG_KERN) pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
+
+  /* Copies message to local buffer, translating control characters */
+  while ((ch = *p++ & 0177) != '\0' && q < &line[sizeof(line) - 1]) {
+       if (ch == '\n')         /* Removes newlines */
+               *q++ = ' ';
+       else if (iscntrl(ch)) { /* Translates control characters */
+               *q++ = '^';
+               *q++ = ch ^ 0100;
+       } else
+               *q++ = ch;
+  }
+  *q = '\0';
+
+  logmsg(pri, line, hname, 0);
+  return;
+}
+
+/*
+**  Name:      void printkline(char *hname, char *msg);
+**  Function:  Takes a raw input line from kernel and 
+**             prints the message on the appropriate log files.
+*/
+void printkline(char *hname, char *msg)
+{
+  char line[MAXLINE + 1];
+  char *p = msg, *q = line;
+  int ch, pri = DEFUPRI;
+
+  /* Copies message to local buffer, adding source program tag */
+  sprintf(line, "kernel: %s", msg);
+
+  logmsg(LOG_KERN | LOG_INFO, line, hname, ADDDATE);
+  return;
+}
+
+/*
+**  Name:      void init(int sig);
+**  Function:  Initialize syslogd from configuration file.
+**             Used at startup or after a SIGHUP signal.
+*/
+void init(int sig)
+{
+  int i;
+  FILE *cf;
+  struct filed *fLog, *next, **nextp;
+  char *p;
+  char cline[BUFSIZ];
+
+  DEBUG(dprintf("init\n");)
+
+  /* Close all open log files. */
+  Initialized = 0;
+  for (fLog = Files; fLog != NULL; fLog = next) {
+
+       /* Flush any pending output */
+       if (fLog->f_prevcount) fprintlog(fLog, 0, NULL);
+
+       switch (fLog->f_type) {
+           case F_FILE:
+           case F_TTY:
+           case F_CONSOLE:     close(fLog->f_file);    break;
+       }
+       next = fLog->f_next;
+       free((char *) fLog);
+  }
+  Files = NULL;
+  nextp = &Files;
+
+  /* Open the configuration file */
+  if ((cf = fopen(ConfFile, "r")) != NULL) {
+       /* Foreach line in the configuration table, open that file. */
+       fLog = NULL;
+       while (fgets(cline, sizeof(cline), cf) != NULL) {
+               /* Check for end-of-section, comments, strip off
+                * trailing spaces and newline character. */
+               for (p = cline; isspace(*p); p += 1);
+               if (*p == '\0' || *p == '#') continue;
+               for (p = strchr(cline, '\0'); isspace(*--p););
+               *++p = '\0';
+               fLog = (struct filed *) calloc(1, sizeof(*fLog));
+               *nextp = fLog;
+               nextp = &fLog->f_next;
+               cfline(cline, fLog);
+       }
+
+       /* Close the configuration file */
+       fclose(cf);
+       Initialized = 1;
+DEBUG (
+       if (DbgOpt) {
+               for (fLog = Files; fLog; fLog = fLog->f_next) {
+                       for (i = 0; i <= LOG_NFACILITIES; i += 1)
+                               if (fLog->f_pmask[i] == INTERNAL_NOPRI)
+                                       printf("X ");
+                               else
+                                       printf("%d ", fLog->f_pmask[i]);
+                       printf("%s: ", TypeNames[fLog->f_type]);
+                       switch (fLog->f_type) {
+                           case F_FILE:
+                           case F_TTY:
+                           case F_CONSOLE:
+                               printf("%s", fLog->f_un.f_fname);
+                               break;
+                           case F_FORW:
+                               break;
+                           case F_USERS:
+                               for (i = 0; i < MAXUNAMES && *fLog->f_un.f_uname[i]; i += 1)
+                                       printf("%s, ", fLog->f_un.f_uname[i]);
+                               break;
+                       }
+                       printf("\n");
+               }
+       }
+  )
+       logmsg(LOG_SYSLOG | LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
+       signal(SIGHUP, init);
+       DEBUG(dprintf("%s restarted\n", ProgName);)
+  } else {
+       DEBUG(dprintf("cannot open %s\n", ConfFile);)
+       *nextp = (struct filed *) calloc(1, sizeof(*fLog));
+       cfline("*.ERR\t" CTTY, *nextp);
+       (*nextp)->f_next = (struct filed *) calloc(1, sizeof(*fLog));
+       cfline("*.PANIC\t*", (*nextp)->f_next);
+       Initialized = 1;
+  }
+  return;
+}
+
+/*
+**  Name:      void daemonize(char *line);
+**  Function:  Clone itself and becomes a daemon releasing unnecessay resources.
+*/
+void daemonize(char *line)
+{
+  int lfd, len, pid;
+
+  if ((lfd = open(PidFile, O_CREAT | O_RDWR, 0600)) > 0) {
+       len = read(lfd, line, 10);
+       line[len] = '\0';
+       close(lfd);
+       if ((kill(len = atoi(line), 0) < 0 && errno == ESRCH) || len == 0) {
+               if (!DbgOpt) {
+                       /* Parent ends and child becomes a daemon */
+                       if ((pid = fork()) > 0) {
+                               /* Write process id. in pid file */
+                               lfd = open(PidFile, O_TRUNC | O_WRONLY);
+                               len = sprintf(line, "%5d", pid);
+                               write(lfd, line, len);
+                               close(lfd);
+
+                               /* Wait for initialization to complete */
+                               exit(EXIT_SUCCESS);
+                       }
+                       sleep(1);
+                       setsid();       /* Set as session leader */
+                       chdir("/");     /* Change to the root directory */
+                       /* Get rid of all open files */
+                       for (lfd = STDERR_FILENO + 1; lfd < OPEN_MAX; lfd += 1)
+                               close(lfd);
+               }
+       } else {
+               fprintf(stderr, "\n%s already running\n", ProgName);
+               exit(EXIT_FAILURE);
+       }
+  } else {
+       fprintf(stderr, "\n%s can't open %s (%s)\n", ProgName, PidFile, strerror(errno));
+       exit(EXIT_FAILURE);
+  }
+  return;
+}
+
+/*
+**  Name:      int main(int argc, char **argv);
+**  Function:  Syslog daemon entry point
+*/
+int main(int argc, char **argv)
+{
+  char *p, *udpdev, *eol;
+  int nfd, kfd, len, fdmax;
+  int ch, port = 0;
+  fd_set fdset;
+  struct nwio_udpopt udpopt;
+  struct servent *sp;
+  char line[MAXLINE + 1];
+
+  while ((ch = getopt(argc, argv, "df:m:p:v?")) != EOF) {
+       switch ((char) ch) {
+           case 'd':           /* Debug */
+               DbgOpt += 1;
+               break;
+           case 'f':           /* Set configuration file */
+               ConfFile = optarg;
+               break;
+           case 'm':           /* Set mark interval */
+               MarkInterval = atoi(optarg) * 60;
+               break;
+           case 'p':           /* Set listening port */
+               port = atoi(optarg);
+               break;
+           case 'v':           /* Print version */
+               fprintf(stderr, "%s version %s\n", ProgName, version);
+               return EXIT_FAILURE;
+           case '?':           /* Help */
+           default:
+               fprintf(stderr, usage);
+               return EXIT_FAILURE;
+       }
+  }
+  if (argc -= optind) {
+       fprintf(stderr, usage);
+       return EXIT_FAILURE;
+  }
+
+  daemonize(line);
+
+  /* Get the official name of local host. */
+  gethostname(LocalHostName, sizeof(LocalHostName) - 1);
+  if ((p = strchr(LocalHostName, '.'))) *p = '\0';
+
+  udpdev = (p = getenv("UDP_DEVICE")) ? p : UDP_DEVICE;
+  sp = getservbyname("syslog", "udp");
+
+  signal(SIGTERM, die);
+  signal(SIGINT, DbgOpt ? die : SIG_IGN);
+  signal(SIGQUIT, DbgOpt ? die : SIG_IGN);
+  signal(SIGALRM, domark);
+
+  alarm(TIMERINTVL);
+
+  /* Open UDP device */
+  if ((nfd = open(udpdev, O_NONBLOCK | O_RDONLY)) < 0) {
+       logerror("UDP device not open");
+       return EXIT_FAILURE;
+  }
+
+  /* Configures the UDP device */
+  udpopt.nwuo_flags = NWUO_SHARED | NWUO_LP_SET | NWUO_EN_LOC |
+       NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET |
+       NWUO_RWDATONLY | NWUO_DI_IPOPT;
+  udpopt.nwuo_locport = udpopt.nwuo_remport =
+                       port == 0 ? sp->s_port : htons(port);
+  udpopt.nwuo_remaddr = udpopt.nwuo_locaddr = htonl(0x7F000001L);
+  
+  while (ioctl(nfd, NWIOSUDPOPT, &udpopt) < 0 ||
+      ioctl(nfd, NWIOGUDPOPT, &udpopt) < 0) {
+       if (errno == EAGAIN) {
+               sleep(1);
+               continue;
+       }
+       logerror("Set/Get UDP options failed");
+       return EXIT_FAILURE;
+  }
+
+  /* Open kernel log device */
+  if ((kfd = open("/dev/klog", O_NONBLOCK | O_RDONLY)) < 0) {
+       logerror("Open /dev/klog failed");
+       return EXIT_FAILURE;
+  }
+
+  fdmax = max(nfd, kfd) + 1;
+
+  DEBUG(dprintf("off & running....\n");)
+  
+  init(-1);                    /* Initilizes log data structures */
+
+  for (;;) {                   /* Main loop */
+
+       FD_ZERO(&fdset);        /* Setup descriptors for select */
+       FD_SET(nfd, &fdset);
+       FD_SET(kfd, &fdset);
+
+       if (select(fdmax, &fdset, NULL, NULL, NULL) <= 0) {
+               sleep(1);
+               continue;
+
+       }
+       if (FD_ISSET(nfd, &fdset)) {
+
+               /* Read a message from application programs */
+               len = read(nfd, line, MAXLINE);
+               if (len > 0) {          /* Got a message */
+                       line[len] = '\0';
+                       dprintf("got a message (%d, %#x)\n", nfd, len);
+                       printline(LocalHostName, line);
+
+               } else if (len < 0) {   /* Got an error or signal while reading */
+                       if (errno != EINTR)     /* */
+                               logerror("Receive error from UDP channel");
+
+               } else {        /* (len == 0) Channel has been closed */
+                       logerror("UDP channel has closed");
+                       close(nfd);
+                       die(-1);
+               }
+       }
+       if (FD_ISSET(kfd, &fdset)) {
+               static char linebuf[5*1024];
+
+               /* Read a message from kernel (klog) */
+               len = read(kfd, linebuf, sizeof(linebuf)-2);
+               dprintf("got a message (%d, %#x)\n", kfd, len);
+               for (ch = 0; ch < len; ch += 1)
+                       if (linebuf[ch] == '\0') linebuf[ch] = ' ';
+               if (linebuf[len - 1] == '\n') len -= 1;
+               linebuf[len] = '\n';
+               linebuf[len + 1] = '\0';
+               p = linebuf;
+               while(eol = strchr(p, '\n')) {
+                       *eol = '\0';
+                       printkline(LocalHostName, p);
+                       p = eol+1;
+               }
+       }
+  }
+  /* Control never gets here */
+}
+
+/** syslogd.c **/