diff options
author | David Oberhollenzer <david.oberhollenzer@tele2.at> | 2018-06-06 14:59:12 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@tele2.at> | 2018-06-11 19:45:42 +0200 |
commit | d9f883f2151a026d25277d57d56aa045417dd3bb (patch) | |
tree | 0169a56a846e0b9e4fb931e4866c1f8a9e432387 | |
parent | f52c7ea9d045db3a1f313f92ef786cbb58594a50 (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-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | cmd/Makemodule.am | 10 | ||||
-rw-r--r-- | cmd/syslog.c | 236 |
4 files changed, 248 insertions, 0 deletions
@@ -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; +} + |