From 4311b9a2f14ee411ec3dc8b050f8efa25afa0bc5 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Wed, 15 Aug 2018 23:50:41 +0200 Subject: usyslogd: create abstraction for log stream management This commit seperates the formating and printing of log messages to files more cleanly from the message pump that retrieves the log messages. At a later point, other backends could be added more easiyl (e.g. forward the log message to some server). Signed-off-by: David Oberhollenzer --- syslogd/Makemodule.am | 2 +- syslogd/backend.h | 35 ++++++++++ syslogd/logfile.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++---- syslogd/logfile.h | 35 ---------- syslogd/main.c | 126 ++---------------------------------- 5 files changed, 200 insertions(+), 172 deletions(-) create mode 100644 syslogd/backend.h delete mode 100644 syslogd/logfile.h diff --git a/syslogd/Makemodule.am b/syslogd/Makemodule.am index 9e5378d..d954769 100644 --- a/syslogd/Makemodule.am +++ b/syslogd/Makemodule.am @@ -1,5 +1,5 @@ usyslogd_SOURCES = syslogd/main.c -usyslogd_SOURCES += syslogd/logfile.c syslogd/logfile.h +usyslogd_SOURCES += syslogd/logfile.c syslogd/backend.h usyslogd_SOURCES += syslogd/proto.c syslogd/proto.h usyslogd_CPPFLAGS = $(AM_CPPFLAGS) usyslogd_CFLAGS = $(AM_CFLAGS) diff --git a/syslogd/backend.h b/syslogd/backend.h new file mode 100644 index 0000000..9f26a54 --- /dev/null +++ b/syslogd/backend.h @@ -0,0 +1,35 @@ +/* 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 . + */ +#ifndef LOGFILE_H +#define LOGFILE_H + +#include "proto.h" + +typedef struct log_backend_t { + int (*init)(struct log_backend_t *log); + + void (*cleanup)(struct log_backend_t *log); + + int (*write)(struct log_backend_t *log, const syslog_msg_t *msg); +} log_backend_t; + + +extern log_backend_t *logmgr; + + +#endif /* LOGFILE_H */ diff --git a/syslogd/logfile.c b/syslogd/logfile.c index adc7e3c..0fe9c9b 100644 --- a/syslogd/logfile.c +++ b/syslogd/logfile.c @@ -20,15 +20,72 @@ #include #include #include -#include #include #include #include -#include "logfile.h" +#include "backend.h" +#include "util.h" -logfile_t *logfile_create(const char *filename, int facility) +#define SYSLOG_PATH "/var/log" + + +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 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 }, +}; + + +typedef struct logfile_t { + struct logfile_t *next; + int fd; + char filename[]; +} logfile_t; + + +typedef struct { + log_backend_t base; + logfile_t *list; +} log_backend_file_t; + + +static logfile_t *logfile_create(const char *filename) { logfile_t *file = calloc(1, sizeof(*file) + strlen(filename) + 1); @@ -39,8 +96,6 @@ logfile_t *logfile_create(const char *filename, int facility) strcpy(file->filename, filename); - file->facility = facility; - file->fd = open(file->filename, O_WRONLY | O_CREAT, 0640); if (file->fd < 0) { perror(file->filename); @@ -58,19 +113,110 @@ fail: return NULL; } -void logfile_destroy(logfile_t *file) +static int logfile_write(logfile_t *file, const syslog_msg_t *msg) { - close(file->fd); - free(file); + const char *lvl_str; + char timebuf[32]; + struct tm tm; + + lvl_str = enum_to_name(levels, msg->level); + if (lvl_str == NULL) + return -1; + + gmtime_r(&msg->timestamp, &tm); + strftime(timebuf, sizeof(timebuf), "%FT%T", &tm); + + dprintf(file->fd, "[%s][%s][%u] %s", timebuf, lvl_str, msg->pid, + msg->message); + + fsync(file->fd); + return 0; } -void logfile_write(logfile_t *file, const char *format, ...) +/*****************************************************************************/ + +static int file_backend_init(log_backend_t *log) { - va_list ap; + (void)log; - va_start(ap, format); - vdprintf(file->fd, format, ap); - va_end(ap); + if (mkdir(SYSLOG_PATH, 0755)) { + if (errno != EEXIST) { + perror("mkdir " SYSLOG_PATH); + return -1; + } + } - fsync(file->fd); + if (chdir(SYSLOG_PATH)) { + perror("cd " SYSLOG_PATH); + return -1; + } + + return 0; } + +static void file_backend_cleanup(log_backend_t *backend) +{ + log_backend_file_t *log = (log_backend_file_t *)backend; + logfile_t *f; + + while (log->list != NULL) { + f = log->list; + log->list = f->next; + + close(f->fd); + free(f); + } +} + +static int file_backend_write(log_backend_t *backend, const syslog_msg_t *msg) +{ + log_backend_file_t *log = (log_backend_file_t *)backend; + const char *fac_name; + char *filename; + logfile_t *f; + size_t len; + + fac_name = enum_to_name(facilities, msg->facility); + if (fac_name == NULL) + return -1; + + if (msg->ident) { + len = strlen(msg->ident) + 1 + strlen(fac_name) + 1; + filename = alloca(len); + sprintf(filename, "%s/%s", msg->ident, fac_name); + } else { + filename = (char *)fac_name; + } + + for (f = log->list; f != NULL; f = f->next) { + if (strcmp(filename, f->filename) == 0) + break; + } + + if (f == NULL) { + if (msg->ident != NULL && mkdir(msg->ident, 0750) != 0 && + errno != EEXIST) { + perror(msg->ident); + return -1; + } + + f = logfile_create(filename); + if (f == NULL) + return -1; + f->next = log->list; + log->list = f; + } + + return logfile_write(f, msg); +} + +log_backend_file_t filebackend = { + .base = { + .init = file_backend_init, + .cleanup = file_backend_cleanup, + .write = file_backend_write, + }, + .list = NULL, +}; + +log_backend_t *logmgr = (log_backend_t *)&filebackend; diff --git a/syslogd/logfile.h b/syslogd/logfile.h deleted file mode 100644 index ccbfd5d..0000000 --- a/syslogd/logfile.h +++ /dev/null @@ -1,35 +0,0 @@ -/* 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 . - */ -#ifndef LOGFILE_H -#define LOGFILE_H - -typedef struct logfile_t { - struct logfile_t *next; - int facility; - int fd; - - char filename[]; -} logfile_t; - -logfile_t *logfile_create(const char *filename, int facility); - -void logfile_destroy(logfile_t *file); - -void logfile_write(logfile_t *file, const char *format, ...); - -#endif /* LOGFILE_H */ diff --git a/syslogd/main.c b/syslogd/main.c index b98c414..8f11906 100644 --- a/syslogd/main.c +++ b/syslogd/main.c @@ -25,75 +25,16 @@ #include #include -#include "logfile.h" +#include "backend.h" #include "proto.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) { @@ -118,59 +59,6 @@ static void signal_setup(void) sigaction(SIGTERM, &act, NULL); } -static int print_to_log(const syslog_msg_t *msg) -{ - const char *fac_name, *lvl_str; - char timebuf[32], *filename; - logfile_t *log; - struct tm tm; - size_t len; - - fac_name = enum_to_name(facilities, msg->facility); - if (fac_name == NULL) - return -1; - - lvl_str = enum_to_name(levels, msg->level); - if (lvl_str == NULL) - return -1; - - if (msg->ident) { - len = strlen(msg->ident) + 1 + strlen(fac_name) + 1; - filename = alloca(len); - sprintf(filename, "%s/%s", msg->ident, fac_name); - } else { - filename = (char *)fac_name; - } - - for (log = logfiles; log != NULL; log = log->next) { - if (log->facility != msg->facility) - continue; - if (strcmp(filename, log->filename) == 0) - break; - } - - if (log == NULL) { - if (msg->ident != NULL && mkdir(msg->ident, 0750) != 0 && - errno != EEXIST) { - perror(msg->ident); - return -1; - } - - log = logfile_create(filename, msg->facility); - if (log == NULL) - return -1; - log->next = logfiles; - logfiles = log; - } - - gmtime_r(&msg->timestamp, &tm); - strftime(timebuf, sizeof(timebuf), "%FT%T", &tm); - - logfile_write(log, "[%s][%s][%u] %s", timebuf, lvl_str, msg->pid, - msg->message); - return 0; -} - static int handle_data(int fd) { char buffer[2048]; @@ -186,13 +74,12 @@ static int handle_data(int fd) if (syslog_msg_parse(&msg, buffer)) return -1; - return print_to_log(&msg); + return logmgr->write(logmgr, &msg); } int main(void) { int sfd, status = EXIT_FAILURE; - logfile_t *log; signal_setup(); @@ -200,7 +87,7 @@ int main(void) if (sfd < 0) return EXIT_FAILURE; - if (directory_setup()) + if (logmgr->init(logmgr)) goto out; while (syslog_run) { @@ -209,12 +96,7 @@ int main(void) status = EXIT_SUCCESS; out: - while (logfiles != NULL) { - log = logfiles; - logfiles = logfiles->next; - - logfile_destroy(log); - } + logmgr->cleanup(logmgr); if (sfd > 0) close(sfd); unlink(SYSLOG_SOCKET); -- cgit v1.2.3