Subject: bin/13400: Syslogd silently ignores lines with no tabs in syslogd.conf
To: None <gnats-bugs@gnats.netbsd.org>
From: Emmanuel Dreyfus <manu@netbsd.org>
List: netbsd-bugs
Date: 07/07/2001 10:13:47
>Number:         13400
>Category:       bin
>Synopsis:       Syslogd silently ignores lines with no tabs in
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Jul 07 01:12:00 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Emmanuel Dreyfus
>Release:        NetBSD-current  20010707
>Organization:
        The NetBSD Project
>Environment:
System: NetBSD violette 1.5W NetBSD 1.5W (TOMKERN) #2: Mon Jun 25
23:08:47 CEST 2001
manu@violette:/usr/src/sys/arch/macppc/compile/TOMKERN macppc
Architecture: powerpc
Machine: macppc
>Description:
When syslogd parses a line of syslogd.conf, it looks for a tab to
delimiter 
the logging facility from the log target. If there is no tab (the
logging
facillity and the log target are separated by spaces), then syslogd will
report that the facility is unknown.

Unfortunately, at the time the message is produced, syslogd is already a
deamon, hence the message cannot go to the terminal. The only hope to 
save the error message is logging it, but if there is a fatal error, 
syslogd won't start, and we will loose the error message. Even if
syslogd
starts, if you configured it that way:
*.*     /var/log/all-logs 
(only spaces here)
the line will be ignored (no tabs), and the error message will be lost.

>How-To-Repeat:
Add this line to your syslog.conf:
*.* /tmp/toto
(no tab, just one or more spaces)
kill syslogd, restart it, and check if you get something in /tmp/toto

>Fix:

Here is the fix. the call to daemon() have been moved later so that all
fatal
error will happen when we are not daemonized. logerror() is fixed to
output
the error message on the terminal when syslogd is not yet daemonized,
and to
syslog() when it is daemonized.

And finnally, when parsing lines in the config file, we first check if
there
is no tab in the line. If there are no tabs, we change spaces to tabs so
that
it will work, and we issue a warning message.

This will probably not make this kind of line working:
auth.info;\skern.notice\s\s@loghost.somewhere-over-the-rainbow.org
Because the log facility will be "auth.info" and the log target will be
"kern.notice\t@loghost.somewhere-over-the-rainbow.org"
But we don't care because we will have an error message.

Please try-out that patch. If no-one compalin, I'll will commit it
shortly

Index: syslogd.c
===================================================================
RCS file: /cvsroot/basesrc/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.44
diff -U4 -r1.44 syslogd.c
--- syslogd.c   2001/03/21 17:02:43     1.44
+++ syslogd.c   2001/07/07 07:54:29
@@ -185,8 +185,9 @@
 struct filed *Files;
 struct filed consfile;
 
 int    Debug;                  /* debug flag */
+int    daemonized = 0;         /* we are not daemonized yet */
 char   LocalHostName[MAXHOSTNAMELEN+1];        /* our hostname */
 char   *LocalDomain;           /* our local domain name */
 int    *finet = NULL;                  /* Internet datagram sockets */
 int    Initialized = 0;        /* set when we have initialized
ourselves */
@@ -259,12 +260,9 @@
                }
        if ((argc -= optind) != 0)
                usage();
 
-       if (!Debug)
-               (void)daemon(0, 0);
-       else
-               setlinebuf(stdout);
+       setlinebuf(stdout);
 
        consfile.f_type = F_CONSOLE;
        (void)strcpy(consfile.f_un.f_fname, ctty);
        (void)gethostname(LocalHostName, sizeof(LocalHostName));
@@ -365,8 +363,19 @@
                readfds[nfds].fd = funix[j++];
                readfds[nfds++].events = POLLIN | POLLPRI;
        }
 
+       /* 
+        * We cannot detach from the terminal before we are sure we
won't 
+        * have a fatal error, because error message would not go to the
+        * terminal and would not be logged because syslogd dies. 
+        * All die() calls are behind us, we can call daemon()
+        */
+       if (!Debug) {
+               (void)daemon(0, 0);
+               daemonized = 1;
+       }
+
        for (;;) {
                int rv;
 
                rv = poll(readfds, nfds, INFTIM);
@@ -1000,10 +1009,14 @@
                    sizeof(buf), "syslogd: %s: %s", type,
strerror(errno));
        else
                (void)snprintf(buf, sizeof(buf), "syslogd: %s", type);
        errno = 0;
-       dprintf("%s\n", buf);
-       logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
+       if (daemonized) 
+               logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
+       if (!daemonized && Debug)
+               dprintf("%s\n", buf);
+       if (!daemonized && !Debug)
+               printf("%s\n", buf);
 }
 
 void
 die(signo)
@@ -1021,8 +1034,12 @@
                dprintf("syslogd: exiting on signal %d\n", signo);
                (void)snprintf(buf, sizeof buf, "exiting on signal %d",
signo);
                errno = 0;
                logerror(buf);
+       } else {
+               (void)snprintf(buf, sizeof buf, "fatal error,
exitting");
+               errno = 0;
+               logerror(buf);
        }
        for (p = LogPaths; p && *p; p++)
                unlink(*p);
        exit(0);
@@ -1193,8 +1210,21 @@
        /* clear out file entry */
        memset(f, 0, sizeof(*f));
        for (i = 0; i <= LOG_NFACILITIES; i++)
                f->f_pmask[i] = INTERNAL_NOPRI;
+
+       /* check a format error: no tabs in the line */
+       for (q = line; *q && *q != '\t'; q++)
+               continue;
+       if (! *q) {
+               (void)snprintf(ebuf, sizeof ebuf,
+                   "Warning: \"%s\" no tabs in the line", line);
+               logerror(ebuf);
+               /* Fix it; replace all spaces by tabs */
+               for (q = line; *q; q++)
+                       if (*q == ' ')  
+                               *q='\t';
+       }
 
        /* scan through the list of selectors */
        for (p = line; *p && *p != '\t';) {
 


-- 
Emmanuel Dreyfus
manu@netbsd.org
>Release-Note:
>Audit-Trail:
>Unformatted:
 syslogd.conf