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; +} +