about summary refs log tree commit diff
path: root/src/daemontools-extras
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2021-08-18 18:46:40 +0000
committerLaurent Bercot <ska@appnovation.com>2021-08-18 18:46:40 +0000
commit678508409a92f80cacd94a70e1e51ca4a389435a (patch)
tree8dc9502d1a8d6785d2ba14afe808a7b52942167a /src/daemontools-extras
parent0fbc13bdc5bf68c6ff44bca7d0f6db02ae045ba5 (diff)
downloads6-678508409a92f80cacd94a70e1e51ca4a389435a.tar.gz
s6-678508409a92f80cacd94a70e1e51ca4a389435a.tar.xz
s6-678508409a92f80cacd94a70e1e51ca4a389435a.zip
Add s6-socklog
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/daemontools-extras')
-rw-r--r--src/daemontools-extras/deps-exe/s6-socklog4
-rw-r--r--src/daemontools-extras/deps-exe/ucspilogd1
-rw-r--r--src/daemontools-extras/lolsyslog.c90
-rw-r--r--src/daemontools-extras/lolsyslog.h10
-rw-r--r--src/daemontools-extras/s6-socklog.c220
-rw-r--r--src/daemontools-extras/ucspilogd.c144
6 files changed, 345 insertions, 124 deletions
diff --git a/src/daemontools-extras/deps-exe/s6-socklog b/src/daemontools-extras/deps-exe/s6-socklog
new file mode 100644
index 0000000..8e48518
--- /dev/null
+++ b/src/daemontools-extras/deps-exe/s6-socklog
@@ -0,0 +1,4 @@
+lolsyslog.o
+-lskarnet
+${SOCKET_LIB}
+${SYSCLOCK_LIB}
diff --git a/src/daemontools-extras/deps-exe/ucspilogd b/src/daemontools-extras/deps-exe/ucspilogd
index e7187fe..3fe140f 100644
--- a/src/daemontools-extras/deps-exe/ucspilogd
+++ b/src/daemontools-extras/deps-exe/ucspilogd
@@ -1 +1,2 @@
+lolsyslog.o
 -lskarnet
diff --git a/src/daemontools-extras/lolsyslog.c b/src/daemontools-extras/lolsyslog.c
new file mode 100644
index 0000000..a397dae
--- /dev/null
+++ b/src/daemontools-extras/lolsyslog.c
@@ -0,0 +1,90 @@
+/* ISC license. */
+
+#undef INTERNAL_MARK
+#ifndef SYSLOG_NAMES
+#define SYSLOG_NAMES
+#endif
+
+#include <skalibs/nonposix.h>
+
+#include <string.h>
+#include <syslog.h>
+
+#include <skalibs/types.h>
+
+#include "lolsyslog.h"
+
+#ifndef INTERNAL_MARK
+
+typedef struct CODE_s CODE, *CODE_ref ;
+struct CODE_s
+{
+  char *c_name ;
+  unsigned int c_val ;
+} ;
+
+#define LOG_PRI(p) ((p) & LOG_PRIMASK)
+#define LOG_FAC(p) (((p) & LOG_FACMASK) / (LOG_PRIMASK + 1))
+
+static CODE const facilitynames[] =
+{
+  { "kern", LOG_KERN },
+  { "user", LOG_USER },
+  { "mail", LOG_MAIL },
+  { "news", LOG_NEWS },
+  { "uucp", LOG_UUCP },
+  { "daemon", LOG_DAEMON },
+  { "auth", LOG_AUTH },
+  { "cron", LOG_CRON },
+  { "lpr", LOG_LPR },
+#ifdef LOG_SYSLOG
+  { "syslog", LOG_SYSLOG },
+#endif
+#ifdef LOG_AUDIT
+  { "audit", LOG_AUDIT },
+#endif
+  { "local0", LOG_LOCAL0 },
+  { "local1", LOG_LOCAL1 },
+  { "local2", LOG_LOCAL2 },
+  { "local3", LOG_LOCAL3 },
+  { "local4", LOG_LOCAL4 },
+  { "local5", LOG_LOCAL5 },
+  { "local6", LOG_LOCAL6 },
+  { "local7", LOG_LOCAL7 },
+  { 0, -1 }
+} ;
+
+static CODE const prioritynames[] =
+{
+  { "emerg", LOG_EMERG },
+  { "alert", LOG_ALERT },
+  { "crit", LOG_CRIT },
+  { "err", LOG_ERR },
+  { "warning", LOG_WARNING },
+  { "notice", LOG_NOTICE },
+  { "info", LOG_INFO },
+  { "debug", LOG_DEBUG },
+  { 0, -1 }
+} ;
+
+#endif
+
+size_t lolsyslog_string (char *out, char const *in)
+{
+  size_t i ;
+  unsigned int fpr ;
+  int fp ;
+  CODE const *p = facilitynames ;
+
+  if (in[0] != '<' || !(i = uint_scan(in+1, &fpr)) || in[1+i] != '>') return 0 ;
+  fp = LOG_FAC(fpr) << 3 ;
+  for (; p->c_name ; p++) if (p->c_val == fp) break ;
+  out = stpcpy(out, p->c_name ? p->c_name : "unknown") ;
+  *out++ = '.' ;
+
+  fp = LOG_PRI(fpr) ;
+  for (p = prioritynames ; p->c_name ; p++) if (p->c_val == fp) break ;
+  out = stpcpy(out, p->c_name ? p->c_name : "unknown") ;
+  *out++ = ':' ; *out++ = ' ' ; *out++ = 0 ;
+  return i+2 ;
+}
diff --git a/src/daemontools-extras/lolsyslog.h b/src/daemontools-extras/lolsyslog.h
new file mode 100644
index 0000000..7364412
--- /dev/null
+++ b/src/daemontools-extras/lolsyslog.h
@@ -0,0 +1,10 @@
+/* ISC license. */
+
+#ifndef LOLSYSLOG_H
+#define LOLSYSLOG_H
+
+#define LOLSYSLOG_STRING 32
+
+extern size_t lolsyslog_string (char *, char const *) ;
+
+#endif
diff --git a/src/daemontools-extras/s6-socklog.c b/src/daemontools-extras/s6-socklog.c
new file mode 100644
index 0000000..f261916
--- /dev/null
+++ b/src/daemontools-extras/s6-socklog.c
@@ -0,0 +1,220 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <skalibs/types.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/allreadwrite.h>
+#include <skalibs/buffer.h>
+#include <skalibs/error.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/tai.h>
+#include <skalibs/iopause.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/socket.h>
+#include <skalibs/ip46.h>
+#include <skalibs/setgroups.h>
+#include <skalibs/sig.h>
+#include <skalibs/selfpipe.h>
+
+#include "lolsyslog.h"
+
+#define USAGE "s6-socklog [ -d notif ] [ -r ] [ -U | -u uid -g gid -G gidlist ] [ -l linelen ] [ -t lameducktimeout ] [ -x socket | -i ip_port ]"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+static tain lameducktto = TAIN_INFINITE_RELATIVE ;
+static int cont = 1 ;
+
+static inline void handle_signals (void)
+{
+  for (;;) switch (selfpipe_read())
+  {
+    case -1 : strerr_diefu1sys(111, "selfpipe_read()") ;
+    case 0 : return ;
+    case SIGTERM : cont = 0 ; break ;
+    default : break ;
+  }
+}
+
+int main (int argc, char const *const *argv)
+{
+  iopause_fd x[3] = { { .events = IOPAUSE_READ }, { .fd = 1 } } ;
+  int flagraw = 0 ;
+  char const *usock = "/dev/log" ;
+  unsigned int linelen = 1024 ;
+  PROG = "s6-socklog" ;
+  {
+    subgetopt l = SUBGETOPT_ZERO ;
+    unsigned int notif = 0 ;
+    unsigned int t = 0 ;
+    uid_t uid = 0 ;
+    gid_t gid = 0 ;
+    gid_t gids[NGROUPS_MAX + 1] ;
+    size_t gidn = (size_t)-1 ;
+    ip46 ip ;
+    uint16_t port = 514 ;
+    for (;;)
+    {
+      int opt = subgetopt_r(argc, argv, "rd:l:t:u:g:G:Ux:i:", &l) ;
+      if (opt == -1) break ;
+      switch (opt)
+      {
+        case 'r' : flagraw = 1 ; break ;
+        case 'd' : if (!uint0_scan(l.arg, &notif)) dieusage() ; break ;
+        case 'l' : if (!uint0_scan(l.arg, &linelen)) dieusage() ; break ;
+        case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
+        case 'u' : if (!uid0_scan(l.arg, &uid)) dieusage() ; break ;
+        case 'g' : if (!gid0_scan(l.arg, &gid)) dieusage() ; break ;
+        case 'G' : if (!gid_scanlist(gids, NGROUPS_MAX, l.arg, &gidn) && *l.arg) dieusage() ; break ;
+        case 'U' :
+        {
+          char const *x = getenv("UID") ;
+          if (!x) strerr_dienotset(100, "UID") ;
+          if (!uid0_scan(x, &uid)) strerr_dieinvalid(100, "UID") ;
+          x = getenv("GID") ;
+          if (!x) strerr_dienotset(100, "GID") ;
+          if (!gid0_scan(x, &gid)) strerr_dieinvalid(100, "GID") ;
+          x = getenv("GIDLIST") ;
+          if (!x) strerr_dienotset(100, "GIDLIST") ;
+          if (!gid_scanlist(gids, NGROUPS_MAX+1, x, &gidn) && *x)
+            strerr_dieinvalid(100, "GIDLIST") ;
+          break ;
+        }
+        case 'x' : usock = l.arg ; break ;
+        case 'i' :
+        {
+          size_t pos = ip46_scan(l.arg, &ip) ;
+          if (!pos) dieusage() ;
+          if (l.arg[pos] == '_' || (!ip46_is6(&ip) && l.arg[pos] == ':'))
+            if (!uint160_scan(l.arg + pos + 1, &port)) dieusage() ;
+          usock = 0 ;
+          break ;
+        }
+        default : dieusage() ;
+      }
+    }
+    argc -= l.ind ; argv += l.ind ;
+
+    if (linelen < 80) linelen = 80 ;
+    if (linelen > 1048576) linelen = 1048576 ;
+    if (t) tain_from_millisecs(&lameducktto, t) ;
+    else lameducktto = tain_infinite_relative ;
+    if (notif)
+    {
+      if (notif < 3) strerr_dief1x(100, "notification fd must be 3 or more") ;
+      if (fcntl(notif, F_GETFD) < 0) strerr_dief1sys(100, "invalid notification fd") ;
+    }
+
+    close(0) ;
+    if (fcntl(1, F_GETFD) < 0) strerr_dief1sys(100, "invalid stdout") ;
+    if (usock)
+    {
+      x[2].fd = ipc_datagram_nbcoe() ;
+      if (x[2].fd == -1) strerr_diefu1sys(111, "create socket") ;
+      if (ipc_bind_reuse_perms(x[2].fd, usock, 0777) == -1)
+        strerr_diefu2sys(111, "bind socket to ", usock) ;
+    }
+    else
+    {
+      x[2].fd = socket_udp46_nbcoe(ip46_is6(&ip)) ;
+      if (x[2].fd == -1) strerr_diefu1sys(111, "create socket") ;
+      if (socket_bind46_reuse(x[2].fd, &ip, port) == -1)
+      {
+        char fmti[IP46_FMT] ;
+        char fmtp[UINT16_FMT] ;
+        fmti[ip46_fmt(fmti, &ip)] = 0 ;
+        fmtp[uint16_fmt(fmtp, port)] = 0 ;
+        strerr_diefu5sys(111, "bind socket to ", "ip ", fmti, " port ", fmtp) ;
+      }
+    }
+
+    if (gidn != (size_t)-1 && setgroups_and_gid(gid ? gid : getegid(), gidn, gids) < 0)
+      strerr_diefu1sys(111, "set supplementary group list") ;
+    if (gid && setgid(gid) < 0)
+      strerr_diefu1sys(111, "setgid") ;
+    if (uid && setuid(uid) < 0)
+      strerr_diefu1sys(111, "setuid") ;
+
+    x[0].fd = selfpipe_init() ;
+    if (x[0].fd == -1) strerr_diefu1sys(111, "init selfpipe") ;
+    if (!sig_altignore(SIGPIPE)) strerr_diefu1sys(111, "ignore SIGPIPE") ;
+    if (!selfpipe_trap(SIGTERM)) strerr_diefu1sys(111, "trap signals") ;
+
+    tain_now_set_stopwatch_g() ;
+
+    if (notif)
+    {
+      fd_write(notif, "\n", 1) ;
+      fd_close(notif) ;
+    }
+  }
+
+  {
+    char outbuf[linelen << 2] ;
+    buffer b1 = BUFFER_INIT(&buffer_write, 1, outbuf, linelen << 2) ;
+    char line[linelen + 1] ;
+    while (cont || buffer_len(&b1))
+    {
+      tain deadline = TAIN_INFINITE ;
+      ssize_t r ;
+      if (!cont) tain_add_g(&deadline, &lameducktto) ;
+      x[1].events = buffer_len(&b1) ? IOPAUSE_WRITE : 0 ;
+      x[2].events = cont && buffer_available(&b1) >= linelen + 80 ? IOPAUSE_READ : 0 ;
+      r = iopause_g(x, 3, &deadline) ;
+      if (r == -1) strerr_diefu1sys(111, "iopause") ;
+      if (!r) return 99 ;
+      if (x[0].revents & IOPAUSE_READ) handle_signals() ;
+      if (x[1].events & x[1].revents & IOPAUSE_WRITE)
+        if (!buffer_flush(&b1) && !error_isagain(errno))
+          strerr_diefu1sys(111, "write to stdout") ;
+      if (x[2].events & x[2].revents & IOPAUSE_READ)
+      {
+        if (usock)
+        {
+          r = sanitize_read(fd_recv(x[2].fd, line, linelen + 1, 0)) ;
+          if (r == -1) strerr_diefu1sys(111, "recv") ;
+        }
+        else
+        {
+          ip46 ip ;
+          uint16 port ;
+          r = sanitize_read(socket_recv46(x[2].fd, line, linelen + 1, &ip, &port)) ;
+          if (r == -1) strerr_diefu1sys(111, "recv") ;
+          if (r)
+          {
+            char fmt[IP46_FMT + UINT16_FMT + 3] ;
+            size_t m = ip46_fmt(fmt, &ip) ;
+            fmt[m++] = '_' ;
+            m += uint16_fmt(fmt, port) ;
+            fmt[m++] = ':' ; fmt[m++] = ' ' ;
+            buffer_putnoflush(&b1, fmt, m) ;
+          }
+        }
+        if (r)
+        {
+          size_t len = r ;
+          size_t pos = 0 ;
+          while (r && (!line[r-1] || line[r-1] == '\n')) r-- ;
+          for (size_t i = 0 ; i < r ; i++)
+            if (!line[i] || line[i] == '\n') line[i] = '~' ;
+          if (!flagraw)
+          {
+            char sbuf[LOLSYSLOG_STRING] ;
+            pos = lolsyslog_string(sbuf, line) ;
+            if (pos) buffer_putsnoflush(&b1, sbuf) ;
+          }
+          buffer_putnoflush(&b1, line + pos, r - pos) ;
+          if (len == linelen+1) buffer_putnoflush(&b1, "...", 3) ;
+          buffer_putnoflush(&b1, "\n", 1) ;
+        }
+      }
+    }
+  }
+  return 0 ;
+}
diff --git a/src/daemontools-extras/ucspilogd.c b/src/daemontools-extras/ucspilogd.c
index c5694d3..0ab6013 100644
--- a/src/daemontools-extras/ucspilogd.c
+++ b/src/daemontools-extras/ucspilogd.c
@@ -1,24 +1,18 @@
 /* ISC license. */
 
-#undef INTERNAL_MARK
-#ifndef SYSLOG_NAMES
-#define SYSLOG_NAMES
-#endif
-
-#include <skalibs/nonposix.h>
 #include <sys/types.h>
 #include <errno.h>
 #include <stdlib.h>
-#include <syslog.h>
-#include <skalibs/types.h>
+
 #include <skalibs/sgetopt.h>
 #include <skalibs/bytestr.h>
 #include <skalibs/buffer.h>
 #include <skalibs/strerr2.h>
 #include <skalibs/stralloc.h>
-#include <skalibs/env.h>
 #include <skalibs/skamisc.h>
 
+#include "lolsyslog.h"
+
 #define USAGE "ucspilogd [ -D default ] [ var... ]"
 #define dieusage() strerr_dieusage(100, USAGE)
 
@@ -27,110 +21,7 @@ static inline void die (void)
   strerr_diefu1sys(111, "write to stdout") ;
 }
 
-
- /*
-   Hack: INTERNAL_MARK is defined by all systems that
-   use the CODE stuff, and not by others (Solaris).
-*/
-
-#ifndef INTERNAL_MARK
-
-typedef struct CODE_s CODE, *CODE_ref ;
-struct CODE_s
-{
-  char *c_name ;
-  unsigned int c_val ;
-} ;
-
-static CODE const prioritynames[] =
-{
-  { "emerg", LOG_EMERG },
-  { "alert", LOG_ALERT },
-  { "crit", LOG_CRIT },
-  { "err", LOG_ERR },
-  { "warning", LOG_WARNING },
-  { "notice", LOG_NOTICE },
-  { "info", LOG_INFO },
-  { "debug", LOG_DEBUG },
-  { 0, -1 }
-} ;
-
-static CODE const facilitynames[] =
-{
-  { "kern", LOG_KERN },
-  { "user", LOG_USER },
-  { "mail", LOG_MAIL },
-  { "news", LOG_NEWS },
-  { "uucp", LOG_UUCP },
-  { "daemon", LOG_DAEMON },
-  { "auth", LOG_AUTH },
-  { "cron", LOG_CRON },
-  { "lpr", LOG_LPR },
-#ifdef LOG_SYSLOG
-  { "syslog", LOG_SYSLOG },
-#endif
-#ifdef LOG_AUDIT
-  { "audit", LOG_AUDIT },
-#endif
-  { "local0", LOG_LOCAL0 },
-  { "local1", LOG_LOCAL1 },
-  { "local2", LOG_LOCAL2 },
-  { "local3", LOG_LOCAL3 },
-  { "local4", LOG_LOCAL4 },
-  { "local5", LOG_LOCAL5 },
-  { "local6", LOG_LOCAL6 },
-  { "local7", LOG_LOCAL7 },
-  { 0, -1 }
-} ;
-
-#define LOG_PRI(p) ((p) & LOG_PRIMASK)
-#define LOG_FAC(p) (((p) & LOG_FACMASK) / (LOG_PRIMASK + 1))
-
-#endif
-
-
-static size_t syslog_names (char const *line)
-{
-  size_t i ;
-  unsigned int fpr ;
-  int fp ;
-  CODE const *p = facilitynames ;
-
-  if (line[0] != '<') return 0 ;
-  i = uint_scan(line+1, &fpr) ;
-  if (!i || (line[i+1] != '>')) return 0 ;
-  i += 2 ;
-  
-  fp = LOG_FAC(fpr) << 3 ;
-  for (; p->c_name ; p++) if (p->c_val == fp) break ;
-  if (p->c_name)
-  {
-    if ((buffer_puts(buffer_1, p->c_name) < 0)
-     || (buffer_put(buffer_1, ".", 1) < 1)) die() ;
-  }
-  else
-  {
-    if (buffer_put(buffer_1, "unknown.", 8) < 8) die() ;
-    i = 0 ;
-  }
-
-  fp = LOG_PRI(fpr) ;
-  for (p = prioritynames ; p->c_name ; p++) if (p->c_val == fp) break ;
-  if (p->c_name)
-  {
-    if ((buffer_puts(buffer_1, p->c_name) < 0)
-     || (buffer_put(buffer_1, ": ", 2) < 2)) die() ;
-  }
-  else
-  {
-    if (buffer_put(buffer_1, "unknown: ", 9) < 9) die() ;
-    i = 0 ;
-  }
-  return i ;
-}
-
-
-int main (int argc, char const *const *argv, char const *const *envp)
+int main (int argc, char const *const *argv)
 {
   char const *d = "<undefined>" ;
   PROG = "ucspilogd" ;
@@ -150,38 +41,43 @@ int main (int argc, char const *const *argv, char const *const *envp)
   }
 
   {
-    char const *envs[argc] ;
     unsigned int i = 0 ;
+    stralloc sa = STRALLOC_ZERO ;
+    char buf[LOLSYSLOG_STRING] ;
+    char const *envs[argc] ;
     for (; i < (unsigned int)argc ; i++)
     {
-      envs[i] = env_get2(envp, argv[i]) ;
+      envs[i] = getenv(argv[i]) ;
       if (!envs[i]) envs[i] = d ;
     }
     for (;;)
     {
       size_t pos = 0 ;
-      satmp.len = 0 ;
+      size_t j ;
+      sa.len = 0 ;
       {
-        int r = skagetlnsep(buffer_0f1, &satmp, "\n", 2) ;
+        int r = skagetlnsep(buffer_0f1, &sa, "\n", 2) ;
         if (r < 0)
         {
-          if (errno != EPIPE || !stralloc_0(&satmp))
+          if (errno != EPIPE || !stralloc_0(&sa))
             strerr_diefu1sys(111, "read from stdin") ;
         }
         if (!r) break ;
       }
-      if (!satmp.len) continue ;
-      satmp.s[satmp.len-1] = '\n' ;
-      if ((satmp.s[0] == '@') && (satmp.len > 26) && (byte_chr(satmp.s, 26, ' ') == 25))
+      if (!sa.len) continue ;
+      sa.s[sa.len-1] = 0 ;
+      if ((sa.s[0] == '@') && (sa.len > 26) && (byte_chr(sa.s, 26, ' ') == 25))
       {
-        if (buffer_put(buffer_1, satmp.s, 26) < 26) die() ;
+        if (buffer_put(buffer_1, sa.s, 26) < 26) die() ;
         pos += 26 ;
       }
       for (i = 0 ; i < (unsigned int)argc ; i++)
         if ((buffer_puts(buffer_1, envs[i]) < 0)
          || (buffer_put(buffer_1, ": ", 2) < 2)) die() ;
-      pos += syslog_names(satmp.s + pos) ;
-      if (buffer_put(buffer_1, satmp.s + pos, satmp.len - pos) < (ssize_t)(satmp.len - pos)) die() ;
+      j = lolsyslog_string(buf, sa.s + pos) ; pos += j ;
+      if (j && buffer_puts(buffer_1, buf) < 0) die() ;
+      sa.s[sa.len-1] = '\n' ;
+      if (buffer_put(buffer_1, sa.s + pos, sa.len - pos) < 0) die() ;
     }
   }
   return 0 ;