diff --git a/.gitignore b/.gitignore
index 256a460..44d1ad5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@ reboot
shutdown
killall5
runsvc
+syslog
usyslogd
services/sigkill
diff --git a/Makefile.am b/Makefile.am
index 09fa4ef..bdee5cb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,6 +3,7 @@ ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/lib/include
AM_CFLAGS = $(WARN_CFLAGS)
+bin_PROGRAMS =
sbin_PROGRAMS =
noinst_LIBRARIES =
nobase_sysconf_DATA = netcfg/ifrename
diff --git a/cmd/Makemodule.am b/cmd/Makemodule.am
index f92610c..f4559a9 100644
--- a/cmd/Makemodule.am
+++ b/cmd/Makemodule.am
@@ -32,6 +32,16 @@ service_CFLAGS = $(AM_CFLAGS)
service_LDFLAGS = $(AM_LDFLAGS)
service_LDADD = libinit.a libcfg.a
+if USYSLOGD
+syslog_SOURCES = cmd/syslog.c
+syslog_CPPFLAGS = $(AM_CPPFLAGS)
+syslog_CFLAGS = $(AM_CFLAGS)
+syslog_LDFLAGS = $(AM_LDFLAGS)
+syslog_LDADD = libinit.a
+
+bin_PROGRAMS += syslog
+endif
+
EXTRA_DIST += $(SRVHEADERS)
sbin_PROGRAMS += service reboot shutdown
diff --git a/cmd/syslog.c b/cmd/syslog.c
new file mode 100644
index 0000000..d225921
--- /dev/null
+++ b/cmd/syslog.c
@@ -0,0 +1,236 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * Copyright (C) 2018 - David Oberhollenzer
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include "util.h"
+
+static int facility = LOG_USER;
+static int level = LOG_INFO;
+static int flags = LOG_NDELAY | LOG_NOWAIT;
+static const char *ident = "(shell)";
+
+static const enum_map_t facility_map[] = {
+ { "auth", LOG_AUTH },
+ { "cron", LOG_CRON },
+ { "daemon", LOG_DAEMON },
+ { "ftp", LOG_FTP },
+ { "local0", LOG_LOCAL0 },
+ { "local1", LOG_LOCAL1 },
+ { "local2", LOG_LOCAL2 },
+ { "local3", LOG_LOCAL3 },
+ { "local4", LOG_LOCAL4 },
+ { "local5", LOG_LOCAL5 },
+ { "local6", LOG_LOCAL6 },
+ { "local7", LOG_LOCAL7 },
+ { "lpr", LOG_LPR },
+ { "news", LOG_NEWS },
+ { "user", LOG_USER },
+ { "uucp", LOG_UUCP },
+ { NULL, 0 },
+};
+
+static const enum_map_t level_map[] = {
+ { "emergency", LOG_EMERG },
+ { "alert", LOG_ALERT },
+ { "critical", LOG_CRIT },
+ { "error", LOG_ERR },
+ { "warning", LOG_WARNING },
+ { "notice", LOG_NOTICE },
+ { "info", LOG_INFO },
+ { "debug", LOG_DEBUG },
+ { NULL, 0 },
+};
+
+static const struct option options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "console", required_argument, NULL, 'c' },
+ { "facility", required_argument, NULL, 'f' },
+ { "level", required_argument, NULL, 'l' },
+ { "ident", required_argument, NULL, 'i' },
+ { NULL, 0, NULL, 0 },
+};
+
+static const char *shortopt = "hVcf:l:i:";
+
+static const char *versiontext =
+"syslog (Pygos init) "PACKAGE_VERSION"\n"
+"Copyright (C) 2018 David Oberhollenzer\n"
+"License GPLv3+: GNU GPL version 3 or later .\n"
+"This is free software: you are free to change and redistribute it.\n"
+"There is NO WARRANTY, to the extent permitted by law.\n";
+
+static const char *helptext =
+"Usage: syslog [OPTION]... [STRING]...\n\n"
+"Concatenate the given STRINGs and send a log message to the syslog daemon.\n"
+"\n"
+"The following OPTIONSs can be used:\n"
+" -f, --facility Logging facilty name or numeric identifier.\n"
+" -l, --level Log level name or numeric identifier.\n"
+" -i, --ident Program name for log syslog message.\n"
+" Default is %s.\n\n"
+" -c, --console Write to the console if opening the syslog\n"
+" socket fails.\n\n"
+" -h, --help Print this help text and exit\n"
+" -V, --version Print version information and exit\n\n";
+
+static void print_map(const enum_map_t *map, int defaultval,
+ const char *option)
+{
+ size_t i;
+
+ printf("The following values can be used for %s:\n", option);
+
+ for (i = 0; map[i].name != NULL; ++i) {
+ if (map[i].value == defaultval) {
+ printf(" %s (=%d), set as default\n",
+ map[i].name, map[i].value);
+ } else {
+ printf(" %s (=%d)\n", map[i].name, map[i].value);
+ }
+ }
+
+ fputc('\n', stdout);
+}
+
+static NORETURN void usage(int status)
+{
+ if (status != EXIT_SUCCESS) {
+ fputs("Try `syslog --help' for more information\n", stderr);
+ } else {
+ printf(helptext, ident);
+ print_map(level_map, level, "--level");
+ print_map(facility_map, facility, "--facility");
+ }
+
+ exit(status);
+}
+
+static NORETURN void version(void)
+{
+ fputs(versiontext, stdout);
+ exit(EXIT_SUCCESS);
+}
+
+static int readint(const char *str)
+{
+ int x = 0;
+
+ if (!isdigit(*str))
+ return -1;
+
+ while (isdigit(*str))
+ x = x * 10 + (*(str++)) - '0';
+
+ return (*str == '\0') ? x : -1;
+}
+
+static void process_options(int argc, char **argv)
+{
+ const enum_map_t *e;
+ int c;
+
+ for (;;) {
+ c = getopt_long(argc, argv, shortopt, options, NULL);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'f':
+ facility = readint(optarg);
+ if (facility >= 0)
+ break;
+ e = enum_by_name(facility_map, optarg);
+ if (e == NULL) {
+ fprintf(stderr, "Unknown facility name '%s'\n",
+ optarg);
+ usage(EXIT_FAILURE);
+ }
+ facility = e->value;
+ break;
+ case 'l':
+ level = readint(optarg);
+ if (level >= 0)
+ break;
+ e = enum_by_name(level_map, optarg);
+ if (e == NULL) {
+ fprintf(stderr, "Unknown log level '%s'\n",
+ optarg);
+ usage(EXIT_FAILURE);
+ }
+ level = e->value;
+ break;
+ case 'i':
+ ident = optarg;
+ break;
+ case 'c':
+ flags |= LOG_CONS;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ case 'V':
+ version();
+ default:
+ usage(EXIT_FAILURE);
+ }
+ }
+}
+
+
+int main(int argc, char **argv)
+{
+ size_t len = 0;
+ char *str;
+ int i;
+
+ process_options(argc, argv);
+
+ if (optind >= argc) {
+ fputs("Error: no log string provided.\n", stderr);
+ usage(EXIT_FAILURE);
+ }
+
+ for (i = optind; i < argc; ++i)
+ len += strlen(argv[i]);
+
+ len += argc - optind - 1;
+
+ str = calloc(1, len + 1);
+ if (str == NULL) {
+ fputs("syslog: out of memory\n", stderr);
+ return EXIT_FAILURE;
+ }
+
+ for (i = optind; i < argc; ++i) {
+ if (i > optind)
+ strcat(str, " ");
+ strcat(str, argv[i]);
+ }
+
+ openlog(ident, flags, facility);
+ syslog(level, "%s", str);
+ closelog();
+
+ free(str);
+ return EXIT_SUCCESS;
+}
+