diff options
Diffstat (limited to 'syslogd/main.c')
-rw-r--r-- | syslogd/main.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/syslogd/main.c b/syslogd/main.c new file mode 100644 index 0000000..a5702b7 --- /dev/null +++ b/syslogd/main.c @@ -0,0 +1,209 @@ +/* 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 <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <unistd.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> +#include <ctype.h> + +#include "logfile.h" +#include "util.h" + + +#define SYSLOG_SOCKET "/dev/log" +#define SYSLOG_PATH "/var/log" + + +static volatile sig_atomic_t syslog_run = 1; +static logfile_t *logfiles = NULL; + +static const enum_map_t facilities[] = { + { "kernel.log", 0 }, + { "user.log", 1 }, + { "mail.log", 2 }, + { "daemon.log", 3 }, + { "auth.log", 4 }, + { "syslog.log", 5 }, + { "lpr.log", 6 }, + { "news.log", 7 }, + { "uucp.log", 8 }, + { "clock.log", 9 }, + { "authpriv.log", 10 }, + { "ftp.log", 11 }, + { "ntp.log", 12 }, + { "audit.log", 13 }, + { "alert.log", 14 }, + { "cron.log", 15 }, + { "local0.log", 16 }, + { "local1.log", 17 }, + { "local2.log", 18 }, + { "local3.log", 19 }, + { "local4.log", 20 }, + { "local5.log", 21 }, + { "local6.log", 22 }, + { "local7.log", 23 }, + { NULL, 0 }, +}; + +static const enum_map_t levels[] = { + { "emergency", 0 }, + { "alert", 1 }, + { "critical", 2 }, + { "error", 3 }, + { "warning", 4 }, + { "notice", 5 }, + { "info", 6 }, + { "debug", 7 }, + { NULL, 0 }, +}; + + +static int directory_setup(void) +{ + if (mkdir(SYSLOG_PATH, 0755)) { + if (errno != EEXIST) { + perror("mkdir " SYSLOG_PATH); + return -1; + } + } + + if (chdir(SYSLOG_PATH)) { + perror("cd " SYSLOG_PATH); + return -1; + } + + return 0; +} + +static void sighandler(int signo) +{ + switch (signo) { + case SIGINT: + case SIGTERM: + syslog_run = 0; + break; + default: + break; + } +} + +static void signal_setup(void) +{ + struct sigaction act; + + memset(&act, 0, sizeof(act)); + act.sa_handler = sighandler; + + sigaction(SIGINT, &act, NULL); + sigaction(SIGTERM, &act, NULL); +} + +static int print_to_log(int facility, int level, const char *data) +{ + const char *fac_name, *lvl_str; + logfile_t *log; + + fac_name = enum_to_name(facilities, facility); + if (fac_name == NULL) + return -1; + + lvl_str = enum_to_name(levels, level); + if (lvl_str == NULL) + return -1; + + for (log = logfiles; log != NULL; log = log->next) { + if (!strcmp(log->name, fac_name)) + break; + } + + if (log == NULL) { + log = logfile_create(fac_name); + if (log == NULL) + return -1; + log->next = logfiles; + logfiles = log; + } + + logfile_write(log, "[%s] %s", lvl_str, data); + return 0; +} + +static int handle_data(int fd) +{ + char buffer[2048], *ptr; + int i = 0, priority; + ssize_t ret; + + memset(buffer, 0, sizeof(buffer)); + + ret = read(fd, buffer, sizeof(buffer)); + if (ret <= 0) + return -1; + + for (ptr = buffer; isspace(*ptr); ++ptr) + ; + if (*(ptr++) != '<') + return -1; + if (!isdigit(*ptr)) + return -1; + for (priority = 0; isdigit(*ptr); ++ptr) + priority = priority * 10 + (*ptr) - '0'; + if (*(ptr++) != '>') + return -1; + while (isspace(*ptr)) + ++ptr; + + return print_to_log(priority >> 3, priority & 0x07, ptr); +} + +int main(void) +{ + int sfd, status = EXIT_FAILURE; + logfile_t *log; + + signal_setup(); + + sfd = mksock(SYSLOG_SOCKET, SOCK_FLAG_EVERYONE | SOCK_FLAG_DGRAM); + if (sfd < 0) + return EXIT_FAILURE; + + if (directory_setup()) + goto out; + + while (syslog_run) { + handle_data(sfd); + } + + status = EXIT_SUCCESS; +out: + while (logfiles != NULL) { + log = logfiles; + logfiles = logfiles->next; + + logfile_destroy(log); + } + if (sfd > 0) + close(sfd); + unlink(SYSLOG_SOCKET); + return status; +} |