summaryrefslogtreecommitdiff
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
parent0fbc13bdc5bf68c6ff44bca7d0f6db02ae045ba5 (diff)
downloads6-678508409a92f80cacd94a70e1e51ca4a389435a.tar.xz
Add s6-socklog
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--doc/index.html1
-rw-r--r--doc/s6-socklog.html139
-rwxr-xr-xexamples/klogd-linux/log/run2
-rwxr-xr-xexamples/klogd-linux/run2
-rwxr-xr-xexamples/s6-svscanboot16
-rw-r--r--examples/syslogd-linux/README9
-rw-r--r--examples/syslogd-linux/log/env/LOGSCRIPT6
-rwxr-xr-xexamples/syslogd-linux/run8
-rw-r--r--examples/syslogd/README4
-rw-r--r--examples/syslogd/log/README (renamed from examples/syslogd-linux/log/README)0
-rw-r--r--examples/syslogd/log/env/LOGSCRIPT6
-rw-r--r--examples/syslogd/log/notification-fd (renamed from examples/syslogd-linux/log/notification-fd)0
-rwxr-xr-xexamples/syslogd/log/run (renamed from examples/syslogd-linux/log/run)2
-rw-r--r--examples/syslogd/notification-fd (renamed from examples/syslogd-linux/notification-fd)0
-rwxr-xr-xexamples/syslogd/run4
-rw-r--r--package/deps.mak8
-rw-r--r--package/modes1
-rw-r--r--package/targets.mak1
-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
24 files changed, 518 insertions, 160 deletions
diff --git a/doc/index.html b/doc/index.html
index 7707fe7..d3e7e6f 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -259,6 +259,7 @@ synchronization</a>.
<ul>
<li><a href="s6-log.html">The <tt>s6-log</tt> program</a></li>
+<li><a href="s6-socklog.html">The <tt>s6-socklog</tt> program</a></li>
<li><a href="ucspilogd.html">The <tt>ucspilogd</tt> program</a></li>
</ul>
diff --git a/doc/s6-socklog.html b/doc/s6-socklog.html
new file mode 100644
index 0000000..03f8c6b
--- /dev/null
+++ b/doc/s6-socklog.html
@@ -0,0 +1,139 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>s6: the s6-socklog program</title>
+ <meta name="Description" content="s6: the s6-socklog program" />
+ <meta name="Keywords" content="s6 syslog syslogd log logging daemon root utilities socket unix inet udp datagram protocol" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">s6</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>s6-socklog</tt> program </h1>
+
+<p>
+<tt>s6-socklog</tt> is a minimal syslog daemon. It reads datagrams
+from the <tt>/dev/log</tt> Unix domain socket, or from a Unix domain
+or Internet domain socket of the user's choice, converts the encoded
+syslog facility and priority names to their human-readable equivalents,
+and prints the logs to its stdout.
+</p>
+
+<p>
+<tt>s6-socklog</tt> is a reimplementation of the
+<a href="http://smarden.org/socklog/socklog.8.html">socklog</a> program
+with a few more features.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ s6-socklog [ -d <em>notif</em> ] [ -r ] [ -U | -u <em>uid</em> -g <em>gid</em> -G <em>gidlist</em> ] [ -l <em>linelen</em> ] [ -t <em>lameducktimeout</em> ] [ -x <em>unixsocket</em> | -i <em>ipport</em> ]
+</pre>
+
+<ul>
+ <li> <tt>s6-socklog</tt> binds to <tt>/dev/log</tt>. </li>
+ <li> It drops its root privileges. </li>
+ <li> For every datagram it reads, it turns its content into a log line:
+ <ul>
+ <li> Messages are truncated to 1024 characters </li>
+ <li> Trailing nulls or newlines are removed </li>
+ <li> Embedded nulls or newlines are converted to <tt>~</tt> characters (tildas) </li>
+ <li> A <tt>&lt;syslogcode&gt;</tt> at the beginning of the line is converted to <tt>facility.priority: </tt> </li>
+ </ul>
+and prints the log line to its stdout, terminated by a newline. </li>
+ <li> It exits 0 on a SIGTERM. </li>
+</ul>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 0: SIGTERM received, clean exit </li>
+ <li> 99: SIGTERM received but the buffer could not be flushed in time, some logs may be lost </li>
+ <li> 100: wrong usage </li>
+ <li> 111: system call failed </li>
+</ul>
+
+<h2> Signals </h2>
+
+<p>
+ <tt>s6-socklog</tt> reacts to the following signals:
+</p>
+
+<ul>
+ <li> SIGTERM: exit as soon as possible </li>
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-r</tt>&nbsp;: raw logging. <tt>&lt;syslogcode&gt;</tt> codes
+will not be converted to facility/priority names. </li>
+ <li> <tt>-d</tt>&nbsp;<em>notif</em>&nbsp;: when ready
+(actually bound to its socket),
+write a newline to file descriptor <em>notif</em> then close it.
+This allows <tt>s6-socklog</tt> to use the <a href="notifywhenup.html">s6
+mechanism to notify readiness</a>. <em>notif</em> cannot be lesser than 3.
+If this option is not given, no readiness notification is sent. </li>
+ <li> <tt>-u&nbsp;<em>uid</em></tt>&nbsp;: set the process' user ID to <em>uid</em> </li>
+ <li> <tt>-g&nbsp;<em>gid</em></tt>&nbsp;: set the process' group ID to <em>gid</em> </li>
+ <li> <tt>-G&nbsp;<em>gidlist</em></tt>&nbsp;: set the process' supplementary group list
+to <em>gidlist</em>, which must be given as a comma-separated list of numeric GIDs,
+without spaces. </li>
+ <li> <tt>-U</tt>&nbsp;: set the process' user ID, group ID and supplementary group list
+to the values of the UID, GID and GIDLIST environment variables. If a <tt>-u</tt>,
+<tt>-g</tt> or <tt>-G</tt> option is given after <tt>-U</tt>, the command line
+value overrides the environment variable. </li>
+ <li> <tt>-l</tt>&nbsp;<em>linelen</em>&nbsp;: Set the maximum datagram size to
+<em>linelen</em>. Default is 1024. It cannot be set to less than 80 or more than
+1048576. If a datagram is bigger than <em>linelen</em>, it will be truncated to
+<em>linelen</em> characters, and the logged line will end with a <tt>...</tt> ellipsis
+to show the truncation. </li>
+ <li> <tt>-t</tt>&nbsp;<em>lameducktimeout</em>&nbsp;: on receipt of a SIGTERM, give
+<tt>s6-socklog</tt> a grace period of <em>lameducktimeout</em> milliseconds to
+flush any log lines that are still in its buffer. Default is 0, which means
+infinite: the program will only exit when its buffer is empty, and may wait
+forever. If <em>lameducktimeout</em> is nonzero and the timeout expires, the
+program will exit 99. </li>
+ <li> <tt>-x</tt>&nbsp;<em>unixsocket</em>&nbsp;: bind to a Unix domain socket
+at <em>unixsocket</em>. Default is <tt>/dev/log</tt>. </li>
+ <li> <tt>-i</tt>&nbsp;<em>ipport</em>&nbsp;: bind to a UDP socket. <em>ipport</em>
+is a combination of <em>ip</em>, which must be an IPv4 or IPv6 address, and
+<em>port</em>, which must be an integer. <em>port</em> may be omitted, in which
+case it defaults to 514. If <em>port</em> is given, <em>ip</em> and <em>port</em>
+must be separated by a <tt>_</tt> character (an underscore). If <em>ip</em> is
+IPv4, a <tt>:</tt> (colon) can be used instead of an underscore. </li>
+</ul>
+
+<h2> Typical use </h2>
+
+<p>
+ <tt>s6-socklog</tt> can be paired with <a href="s6-log.html">s6-log</a> to
+implement <em>syslogd</em> functionality. <tt>s6-socklog</tt> acts as the
+<em>frontend</em>: it reads the log lines and processes them, then pipes them
+to an <a href="s6-log.html">s6-log</a> instance that acts as the <em>backend</em>,
+i.e. sorts the log lines depending on regular expressions that typically involve
+the facility and priority names, then stores them into the filesystem.
+</p>
+
+<p>
+ The pipe between <tt>s6-socklog</tt> and <a href="s6-log.html">s6-log</a> is
+typically a <em>logging pipe</em> automatically provided by
+<a href="s6-svscan.html">s6-svscan</a> when the <tt>s6-log</tt> instance is declared as
+a logger service for the <tt>s6-socklog</tt> instance.
+</p>
+
+<p>
+ The <tt>examples/</tt> subdirectory of the s6 package contains a turnkey
+<tt>syslogd</tt> service that implements this pattern.
+</p>
+
+</body>
+</html>
diff --git a/examples/klogd-linux/log/run b/examples/klogd-linux/log/run
index 458fe27..82a3bb6 100755
--- a/examples/klogd-linux/log/run
+++ b/examples/klogd-linux/log/run
@@ -1,4 +1,4 @@
-#!/command/execlineb -P
+#!/bin/execlineb -P
s6-setuidgid klog
exec -c
s6-log -d3 t s1000000 n20 /var/log/klogd
diff --git a/examples/klogd-linux/run b/examples/klogd-linux/run
index 453b55b..ae9935a 100755
--- a/examples/klogd-linux/run
+++ b/examples/klogd-linux/run
@@ -1,4 +1,4 @@
-#!/command/execlineb -P
+#!/bin/execlineb -P
fdmove -c 2 1
redirfd -r 0 /proc/kmsg
exec -c
diff --git a/examples/s6-svscanboot b/examples/s6-svscanboot
index 6bac3a2..be4bea4 100755
--- a/examples/s6-svscanboot
+++ b/examples/s6-svscanboot
@@ -1,9 +1,9 @@
-#!/command/execlineb -P
+#!/bin/execlineb -P
-/command/exec -c
-/command/s6-setsid -qb
-/command/redirfd -r 0 /dev/null
-/command/redirfd -wnb 1 /service/s6-svscan-log/fifo
-/command/fdmove -c 2 1
-/command/exec -a s6-svscan
-/command/s6-svscan -t0 /service
+/bin/exec -c
+/bin/s6-setsid -qb
+/bin/redirfd -r 0 /dev/null
+/bin/redirfd -wnb 1 /service/s6-svscan-log/fifo
+/bin/fdmove -c 2 1
+/bin/exec -a s6-svscan
+/bin/s6-svscan -t0 /service
diff --git a/examples/syslogd-linux/README b/examples/syslogd-linux/README
deleted file mode 100644
index 675715b..0000000
--- a/examples/syslogd-linux/README
+++ /dev/null
@@ -1,9 +0,0 @@
-This is an example of a service directory for process supervision by s6.
-
-This syslogd emulation works on any Unix where syslog() is
-implemented via a connection on the /dev/log Unix-domain socket.
-It needs a Unix superserver (see s6-networking, ucspi-unix or
-ucspi-ipc) and ucspilogd.
-A ucspilogd process is spawned for every syslog() client. It
-processes logs and sends them to stderr, i.e. the service's
-logger.
diff --git a/examples/syslogd-linux/log/env/LOGSCRIPT b/examples/syslogd-linux/log/env/LOGSCRIPT
deleted file mode 100644
index e7a1eb7..0000000
--- a/examples/syslogd-linux/log/env/LOGSCRIPT
+++ /dev/null
@@ -1,6 +0,0 @@
-- +^[0-9]+:\s[0-9]+:\serror\. t /var/log/syslogd/error
-- +^[0-9]+:\s[0-9]+:\sauthpriv\. t /var/log/syslogd/auth
-- +^[0-9]+:\s[0-9]+:\suser\. t /var/log/syslogd/user
-- +^[0-9]+:\s[0-9]+:\smessages\. t /var/log/syslogd/messages
-- +^[0-9]+:\s[0-9]+:\sdaemon\. t /var/log/syslogd/daemon
-f t /var/log/syslogd/misc
diff --git a/examples/syslogd-linux/run b/examples/syslogd-linux/run
deleted file mode 100755
index de33c2c..0000000
--- a/examples/syslogd-linux/run
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/command/execlineb -P
-fdmove -c 2 1
-exec -c
-s6-envuidgid nobody
-fdmove 1 3
-s6-ipcserver -U -1 -- /dev/log
-fdmove -c 1 2
-ucspilogd IPCREMOTEEUID IPCREMOTEEGID
diff --git a/examples/syslogd/README b/examples/syslogd/README
new file mode 100644
index 0000000..c115a4e
--- /dev/null
+++ b/examples/syslogd/README
@@ -0,0 +1,4 @@
+This is an example of a service directory for process supervision by s6.
+
+This syslogd emulation works on any Unix where syslog() is
+implemented via a connection on the /dev/log Unix-domain socket.
diff --git a/examples/syslogd-linux/log/README b/examples/syslogd/log/README
index 9d4968e..9d4968e 100644
--- a/examples/syslogd-linux/log/README
+++ b/examples/syslogd/log/README
diff --git a/examples/syslogd/log/env/LOGSCRIPT b/examples/syslogd/log/env/LOGSCRIPT
new file mode 100644
index 0000000..35ae234
--- /dev/null
+++ b/examples/syslogd/log/env/LOGSCRIPT
@@ -0,0 +1,6 @@
+- +^\\serror\\. t /var/log/syslogd/error
+- +^\\sauthpriv\\. t /var/log/syslogd/auth
+- +^\\suser\\. t /var/log/syslogd/user
+- +^\\smessages\\. t /var/log/syslogd/messages
+- +^\\sdaemon\\. t /var/log/syslogd/daemon
+f t /var/log/syslogd/misc
diff --git a/examples/syslogd-linux/log/notification-fd b/examples/syslogd/log/notification-fd
index 00750ed..00750ed 100644
--- a/examples/syslogd-linux/log/notification-fd
+++ b/examples/syslogd/log/notification-fd
diff --git a/examples/syslogd-linux/log/run b/examples/syslogd/log/run
index fcb667c..c066f37 100755
--- a/examples/syslogd-linux/log/run
+++ b/examples/syslogd/log/run
@@ -1,4 +1,4 @@
-#!/command/execlineb -P
+#!/bun/execlineb -P
s6-setuidgid syslog
s6-envdir -f env
importas -Cs LOGSCRIPT LOGSCRIPT
diff --git a/examples/syslogd-linux/notification-fd b/examples/syslogd/notification-fd
index 00750ed..00750ed 100644
--- a/examples/syslogd-linux/notification-fd
+++ b/examples/syslogd/notification-fd
diff --git a/examples/syslogd/run b/examples/syslogd/run
new file mode 100755
index 0000000..98a52d9
--- /dev/null
+++ b/examples/syslogd/run
@@ -0,0 +1,4 @@
+#!/bin/execlineb -P
+fdmove -c 2 1
+s6-envuidgid nobody
+s6-socklog -d3 -U -t3000
diff --git a/package/deps.mak b/package/deps.mak
index 3c051aa..2f21727 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -19,6 +19,7 @@ src/conn-tools/s6-ipcserverd.o src/conn-tools/s6-ipcserverd.lo: src/conn-tools/s
src/conn-tools/s6-sudo.o src/conn-tools/s6-sudo.lo: src/conn-tools/s6-sudo.c src/include/s6/config.h
src/conn-tools/s6-sudoc.o src/conn-tools/s6-sudoc.lo: src/conn-tools/s6-sudoc.c src/conn-tools/s6-sudo.h
src/conn-tools/s6-sudod.o src/conn-tools/s6-sudod.lo: src/conn-tools/s6-sudod.c src/conn-tools/s6-sudo.h
+src/daemontools-extras/lolsyslog.o src/daemontools-extras/lolsyslog.lo: src/daemontools-extras/lolsyslog.c src/daemontools-extras/lolsyslog.h
src/daemontools-extras/s6-applyuidgid.o src/daemontools-extras/s6-applyuidgid.lo: src/daemontools-extras/s6-applyuidgid.c
src/daemontools-extras/s6-envdir.o src/daemontools-extras/s6-envdir.lo: src/daemontools-extras/s6-envdir.c
src/daemontools-extras/s6-envuidgid.o src/daemontools-extras/s6-envuidgid.lo: src/daemontools-extras/s6-envuidgid.c
@@ -27,10 +28,11 @@ src/daemontools-extras/s6-log.o src/daemontools-extras/s6-log.lo: src/daemontool
src/daemontools-extras/s6-setlock.o src/daemontools-extras/s6-setlock.lo: src/daemontools-extras/s6-setlock.c src/include/s6/config.h src/include-local/s6lockd.h
src/daemontools-extras/s6-setsid.o src/daemontools-extras/s6-setsid.lo: src/daemontools-extras/s6-setsid.c
src/daemontools-extras/s6-setuidgid.o src/daemontools-extras/s6-setuidgid.lo: src/daemontools-extras/s6-setuidgid.c src/include/s6/config.h
+src/daemontools-extras/s6-socklog.o src/daemontools-extras/s6-socklog.lo: src/daemontools-extras/s6-socklog.c src/daemontools-extras/lolsyslog.h
src/daemontools-extras/s6-softlimit.o src/daemontools-extras/s6-softlimit.lo: src/daemontools-extras/s6-softlimit.c
src/daemontools-extras/s6-tai64n.o src/daemontools-extras/s6-tai64n.lo: src/daemontools-extras/s6-tai64n.c
src/daemontools-extras/s6-tai64nlocal.o src/daemontools-extras/s6-tai64nlocal.lo: src/daemontools-extras/s6-tai64nlocal.c
-src/daemontools-extras/ucspilogd.o src/daemontools-extras/ucspilogd.lo: src/daemontools-extras/ucspilogd.c
+src/daemontools-extras/ucspilogd.o src/daemontools-extras/ucspilogd.lo: src/daemontools-extras/ucspilogd.c src/daemontools-extras/lolsyslog.h
src/fdholder/s6-fdholder-daemon.o src/fdholder/s6-fdholder-daemon.lo: src/fdholder/s6-fdholder-daemon.c src/include/s6/config.h
src/fdholder/s6-fdholder-delete.o src/fdholder/s6-fdholder-delete.lo: src/fdholder/s6-fdholder-delete.c src/include/s6/s6-fdholder.h
src/fdholder/s6-fdholder-getdump.o src/fdholder/s6-fdholder-getdump.lo: src/fdholder/s6-fdholder-getdump.c src/include/s6/s6-fdholder.h
@@ -176,6 +178,8 @@ s6-setsid: EXTRA_LIBS := -lskarnet
s6-setsid: src/daemontools-extras/s6-setsid.o
s6-setuidgid: EXTRA_LIBS := -lskarnet
s6-setuidgid: src/daemontools-extras/s6-setuidgid.o
+s6-socklog: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
+s6-socklog: src/daemontools-extras/s6-socklog.o src/daemontools-extras/lolsyslog.o
s6-softlimit: EXTRA_LIBS := -lskarnet
s6-softlimit: src/daemontools-extras/s6-softlimit.o
s6-tai64n: EXTRA_LIBS := -lskarnet ${SYSCLOCK_LIB}
@@ -183,7 +187,7 @@ s6-tai64n: src/daemontools-extras/s6-tai64n.o
s6-tai64nlocal: EXTRA_LIBS := -lskarnet
s6-tai64nlocal: src/daemontools-extras/s6-tai64nlocal.o
ucspilogd: EXTRA_LIBS := -lskarnet
-ucspilogd: src/daemontools-extras/ucspilogd.o
+ucspilogd: src/daemontools-extras/ucspilogd.o src/daemontools-extras/lolsyslog.o
s6-fdholder-daemon: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
s6-fdholder-daemon: src/fdholder/s6-fdholder-daemon.o ${LIBS6}
s6-fdholder-delete: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${SYSCLOCK_LIB}
diff --git a/package/modes b/package/modes
index b457f7d..4678bec 100644
--- a/package/modes
+++ b/package/modes
@@ -31,6 +31,7 @@ s6-setlock 0755
s6-setsid 0755
s6-setuidgid 0700
s6-softlimit 0755
+s6-socklog 0755
s6-tai64n 0755
s6-tai64nlocal 0755
s6-accessrules-cdb-from-fs 0755
diff --git a/package/targets.mak b/package/targets.mak
index 32971b9..0f1ebab 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -29,6 +29,7 @@ s6-log \
s6-setlock \
s6-setsid \
s6-softlimit \
+s6-socklog \
s6-tai64n \
s6-tai64nlocal \
s6-accessrules-cdb-from-fs \
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 ;