tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Add support for fifo files (mkfifo(2)) to syslogd(8)



Hi,

I would find it useful if syslogd(8) would handle writes to FIFO files in
addition to existing support for regular files.
I found some old discussion about this (see
http://mail-index.netbsd.org/tech-userlevel/2008/06/09/msg000742.html
and follow-ups), but this did not seem to reach a consensus

I just spent a few minutes adding support for FIFO to syslogd(8) with a
slightly different approach than in the thread above. AFAIK I did not introduce
any compatibility issue. My patch just tests if a file specified in a
syslog.conf is a FIFO or a regular file, and acts accordingly.

The patch is small enough so that I attach it below.
Would it be acceptable for integration into NetBSD?

-- 
Anthony

PS: The main reason for my request is not really fundamental, but I recently
figured out that since Linux kernel 2.6, Linux has broken^Wrestricted
/dev/console and the use of TIOCCONS to root. (and thus broken xconsole, xterm
-C etc.). I have a homemade ~20 lines script written in TCL that can watch
console messages on Linux by polling a FIFO file in /dev/xconsole (note the
'x'), which is what Linux found to unbreak xconsole and the like.

Watching /dev/console (the real one) from TCL on NetBSD is a bit hard, since
this requires some C code to send the proper TIOCCONS ioctl(2), and well
... this defeats the purpose of using some scripting language. All in all, I
finally find the use of a FIFO not that bad.

Index: syslogd.c
===================================================================
RCS file: /cvsroot/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.115
diff -u -r1.115 syslogd.c
--- syslogd.c   27 May 2013 23:15:51 -0000      1.115
+++ syslogd.c   7 Nov 2013 17:20:21 -0000
@@ -70,6 +70,7 @@
  * TLS, syslog-protocol, and syslog-sign code by Martin Schuette.
  */
 #define SYSLOG_NAMES
+#include <sys/stat.h>
 #include <poll.h>
 #include "syslogd.h"
 #include "extern.h"
@@ -133,7 +134,8 @@
 #define F_USERS                5               /* list of users */
 #define F_WALL         6               /* everyone logged on */
 #define F_PIPE         7               /* pipe to program */
-#define F_TLS          8
+#define F_FIFO         8               /* mkfifo(2) file */
+#define F_TLS          9
 
 struct TypeInfo {
        const char *name;
@@ -155,6 +157,7 @@
        {"USERS",   NULL,    "0", NULL,   "0", 0, 0,  1024},
        {"WALL",    NULL,    "0", NULL,   "0", 0, 0,  1024},
        {"PIPE",    NULL, "1024", NULL,  "1M", 0, 0, 16384},
+       {"FIFO",    NULL, "1024", NULL,  "1M", 0, 0, 16384},
 #ifndef DISABLE_TLS
        {"TLS",     NULL,   "-1", NULL, "16M", 0, 0, 16384}
 #endif /* !DISABLE_TLS */
@@ -2187,7 +2190,8 @@
            || (f->f_type == F_TTY)
            || (f->f_type == F_CONSOLE)
            || (f->f_type == F_USERS)
-           || (f->f_type == F_WALL))) {
+           || (f->f_type == F_WALL)
+           || (f->f_type == F_FIFO))) {
                DELREF(buffer);
                return;
        }
@@ -2196,7 +2200,8 @@
        if (qentry
            && (f->f_type != F_TLS)
            && (f->f_type != F_PIPE)
-           && (f->f_type != F_FILE)) {
+           && (f->f_type != F_FILE)
+           && (f->f_type != F_FIFO)) {
                errno = 0;
                logerror("Warning: unexpected message type %d in buffer",
                    f->f_type);
@@ -2253,6 +2258,7 @@
                len = linelen - tlsprefixlen;
                break;
        case F_PIPE:
+       case F_FIFO:
        case F_FILE:  /* fallthrough */
                if (f->f_flags & FFLAG_FULL) {
                        v->iov_base = line + tlsprefixlen;
@@ -2453,6 +2459,48 @@
                }
                break;
 
+       case F_FIFO:
+               DPRINTF(D_MISC, "Logging to %s %s\n",
+                       TypeInfo[f->f_type].name, f->f_un.f_fname);
+               if (f->f_file < 0) {
+                       f->f_file =
+                         open(f->f_un.f_fname, O_WRONLY|O_NONBLOCK, 0);
+                       e = errno;
+                       if (f->f_file < 0 && e == ENXIO) {
+                               /* Drop messages with no reader */
+                               if (qentry)
+                                       message_queue_remove(f, qentry);
+                               break;
+                       }
+               }
+
+               if (f->f_file >= 0 && writev(f->f_file, iov, v - iov) < 0) {
+                       e = errno;
+                       close(f->f_file);
+                       f->f_file = -1;
+
+                       /* Drop messages with no reader */
+                       if (e == EAGAIN || e == EPIPE) {
+                               if (qentry)
+                                       message_queue_remove(f, qentry);
+                               break;
+                       }
+               }
+
+               if (f->f_file < 0) {
+                       f->f_type = F_UNUSED;
+                       errno = e;
+                       f->f_lasterror = e;
+                       logerror("%s", f->f_un.f_fname);
+                       message_queue_freeall(f);
+                       break;
+               }
+
+               f->f_lasterror = 0;
+               if (qentry) /* sent buffered msg */
+                       message_queue_remove(f, qentry);
+               break;
+
        case F_USERS:
        case F_WALL:
                DPRINTF(D_MISC, "Logging to %s\n", TypeInfo[f->f_type].name);
@@ -3622,6 +3670,7 @@
        const char   *p, *q;
        char *bp;
        char   buf[MAXLINE];
+       struct stat sb;
 
        DPRINTF((D_CALL|D_PARSE),
                "cfline(%zu, \"%s\", f, \"%s\", \"%s\")\n",
@@ -3832,6 +3881,17 @@
                        f->f_flags |= FFLAG_SIGN;
 #endif /* !DISABLE_SIGN */
                (void)strlcpy(f->f_un.f_fname, p, sizeof(f->f_un.f_fname));
+               if (stat(p, &sb)) {
+                       f->f_type = F_UNUSED;
+                       logerror("%s", p);
+                       break;
+               }
+               if (S_ISFIFO(sb.st_mode)) {
+                       f->f_file = -1;
+                       f->f_type = F_FIFO;
+                       break;
+               }
+
                if ((f->f_file = open(p, O_WRONLY|O_APPEND, 0)) < 0) {
                        f->f_type = F_UNUSED;
                        logerror("%s", p);


Home | Main Index | Thread Index | Old Index