summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@tele2.at>2018-06-06 14:59:12 +0200
committerDavid Oberhollenzer <david.oberhollenzer@tele2.at>2018-06-11 19:45:42 +0200
commitd9f883f2151a026d25277d57d56aa045417dd3bb (patch)
tree0169a56a846e0b9e4fb931e4866c1f8a9e432387
parentf52c7ea9d045db3a1f313f92ef786cbb58594a50 (diff)
Add utility for producing syslog message from the shell
This can can be used by shell scripts to produce syslog messages, as well as aiding in debugging the usyslogd daemon. Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am1
-rw-r--r--cmd/Makemodule.am10
-rw-r--r--cmd/syslog.c236
4 files changed, 248 insertions, 0 deletions
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 <https://www.gnu.org/licenses/>.
+ */
+#include <getopt.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#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 <https://gnu.org/licenses/gpl.html>.\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 <facility> Logging facilty name or numeric identifier.\n"
+" -l, --level <level> Log level name or numeric identifier.\n"
+" -i, --ident <name> 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;
+}
+