about summary refs log tree commit diff
path: root/vlogger.c
diff options
context:
space:
mode:
authorDuncaen <mail@duncano.de>2017-03-01 19:15:03 +0100
committerDuncaen <mail@duncano.de>2018-06-20 18:02:46 +0200
commitb29a3c4d11ec1cf778b253e3c3fbbf04b0794f86 (patch)
treef81345c482f77b0d31b2ca73d98fa6752013a23f /vlogger.c
parent8fe7df917d20e4bdad51fabcc3675e66fa50e330 (diff)
downloadrunit-void-b29a3c4d11ec1cf778b253e3c3fbbf04b0794f86.tar.gz
runit-void-b29a3c4d11ec1cf778b253e3c3fbbf04b0794f86.tar.xz
runit-void-b29a3c4d11ec1cf778b253e3c3fbbf04b0794f86.zip
Add vlogger(8)
vlogger(8) is a alternative to logger(1), by default it sends messages
from stdin to syslog.

The main reason to replace logger(1) is, that logger only connects once to
the syslog socket in default mode and puts all messages into the void if
syslog is not running at the time.
logger(1) has a new `--socket-errors=on` mode which would work, but some
void uses don't use syslog at all and in this case the log service would
constantly restart.

As a bonus vlogger(8) looks for /etc/vlogger and if its executable it
just executes it and is replaced by it.
This can be used to avoid syslog and just write all logs to files with
svlogd(8) as example, without having to edit all log services.
Diffstat (limited to 'vlogger.c')
-rw-r--r--vlogger.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/vlogger.c b/vlogger.c
new file mode 100644
index 0000000..981b692
--- /dev/null
+++ b/vlogger.c
@@ -0,0 +1,111 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+typedef struct _code {
+  const char *const c_name;
+  int c_val;
+} CODE;
+
+CODE prioritynames[] = {
+	{ "alert", LOG_ALERT },
+	{ "crit", LOG_CRIT },
+	{ "debug", LOG_DEBUG },
+	{ "emerg", LOG_EMERG },
+	{ "err", LOG_ERR },
+	{ "error", LOG_ERR },
+	{ "info", LOG_INFO },
+	{ "notice", LOG_NOTICE },
+	{ "panic", LOG_EMERG },
+	{ "warn", LOG_WARNING },
+	{ "warning", LOG_WARNING },
+	{ 0, -1 }
+};
+
+CODE facilitynames[] = {
+	{ "auth", LOG_AUTH },
+	{ "authpriv", LOG_AUTHPRIV },
+	{ "cron", LOG_CRON },
+	{ "daemon", LOG_DAEMON },
+	{ "ftp", LOG_FTP },
+	{ "kern", LOG_KERN },
+	{ "lpr", LOG_LPR },
+	{ "mail", LOG_MAIL },
+	{ "news", LOG_NEWS },
+	{ "security", LOG_AUTH },
+	{ "syslog", LOG_SYSLOG },
+	{ "user", LOG_USER },
+	{ "uucp", LOG_UUCP },
+	{ "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 char *tag;
+
+static void
+strpriority(char *s, int *facility, int *level)
+{
+	char *p;
+	CODE *cp;
+
+	if ((p = strchr(s, '.'))) {
+		*p++ = 0;
+		for (cp = prioritynames; cp->c_name; cp++) {
+			if (strcmp(cp->c_name, p) == 0)
+				*level = cp->c_val;
+		}
+	}
+	if (*s)
+		for (cp = facilitynames; cp->c_name; cp++) {
+			if (strcmp(cp->c_name, s) == 0)
+				*facility = cp->c_val;
+		}
+}
+
+int
+main(int argc, char *argv[])
+{
+	char c, *p;
+	int facility = LOG_DAEMON;
+	int level = LOG_INFO;
+
+	if (((p = strrchr(*argv, '/')) && !strncmp(p+1, "run", 3)) &&
+	    (*p = 0, (p = strrchr(*argv, '/')) && !strncmp(p+1, "log", 3)) &&
+	    (*p = 0, (p = strrchr(*argv, '/'))) != 0) {
+		tag = strdup(p+1);
+	}
+
+	while ((c = getopt(argc, argv, "p:t:")) != -1)
+		switch (c) {
+		case 'p': strpriority(optarg, &facility, &level); break;
+		case 't': tag = optarg; break;
+		default:
+			fprintf(stderr, "usage: vlogger [-p priority] [-t tag]\n");
+			exit(1);
+		}
+
+	if (access("/etc/vlogger", X_OK) != -1)
+		execl("/etc/vlogger", "/etc/vlogger", tag, (char *)0);
+
+	openlog(tag, 0, facility);
+
+	char *line;
+	size_t linelen = 0;
+	ssize_t rd;
+	while ((rd = getline(&line, &linelen, stdin)) != -1) {
+		if (line[rd-1] == '\n')
+			line[rd-1] = 0;
+		syslog(level|facility, "%s", line);
+	}
+
+	return 1;
+}