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/logfile.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 160 insertions(+), 14 deletions(-) (limited to 'syslogd/logfile.c') 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; -- cgit v1.2.3