1
0
Fork 0
mirror of https://github.com/pygos/init.git synced 2024-11-05 04:07:10 +01:00

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 <david.oberhollenzer@tele2.at>
This commit is contained in:
David Oberhollenzer 2018-08-15 23:50:41 +02:00
parent 0624f95de6
commit 4311b9a2f1
4 changed files with 175 additions and 147 deletions

View file

@ -1,5 +1,5 @@
usyslogd_SOURCES = syslogd/main.c 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_SOURCES += syslogd/proto.c syslogd/proto.h
usyslogd_CPPFLAGS = $(AM_CPPFLAGS) usyslogd_CPPFLAGS = $(AM_CPPFLAGS)
usyslogd_CFLAGS = $(AM_CFLAGS) usyslogd_CFLAGS = $(AM_CFLAGS)

View file

@ -18,18 +18,18 @@
#ifndef LOGFILE_H #ifndef LOGFILE_H
#define LOGFILE_H #define LOGFILE_H
typedef struct logfile_t { #include "proto.h"
struct logfile_t *next;
int facility;
int fd;
char filename[]; typedef struct log_backend_t {
} logfile_t; int (*init)(struct log_backend_t *log);
logfile_t *logfile_create(const char *filename, int facility); void (*cleanup)(struct log_backend_t *log);
void logfile_destroy(logfile_t *file); int (*write)(struct log_backend_t *log, const syslog_msg_t *msg);
} log_backend_t;
extern log_backend_t *logmgr;
void logfile_write(logfile_t *file, const char *format, ...);
#endif /* LOGFILE_H */ #endif /* LOGFILE_H */

View file

@ -20,15 +20,72 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#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); 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); strcpy(file->filename, filename);
file->facility = facility;
file->fd = open(file->filename, O_WRONLY | O_CREAT, 0640); file->fd = open(file->filename, O_WRONLY | O_CREAT, 0640);
if (file->fd < 0) { if (file->fd < 0) {
perror(file->filename); perror(file->filename);
@ -58,19 +113,110 @@ fail:
return NULL; return NULL;
} }
void logfile_destroy(logfile_t *file) static int logfile_write(logfile_t *file, const syslog_msg_t *msg)
{ {
close(file->fd); const char *lvl_str;
free(file); char timebuf[32];
} struct tm tm;
void logfile_write(logfile_t *file, const char *format, ...) lvl_str = enum_to_name(levels, msg->level);
{ if (lvl_str == NULL)
va_list ap; return -1;
va_start(ap, format); gmtime_r(&msg->timestamp, &tm);
vdprintf(file->fd, format, ap); strftime(timebuf, sizeof(timebuf), "%FT%T", &tm);
va_end(ap);
dprintf(file->fd, "[%s][%s][%u] %s", timebuf, lvl_str, msg->pid,
msg->message);
fsync(file->fd); fsync(file->fd);
return 0;
} }
/*****************************************************************************/
static int file_backend_init(log_backend_t *log)
{
(void)log;
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 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;

View file

@ -25,75 +25,16 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include "logfile.h" #include "backend.h"
#include "proto.h" #include "proto.h"
#include "util.h" #include "util.h"
#define SYSLOG_SOCKET "/dev/log" #define SYSLOG_SOCKET "/dev/log"
#define SYSLOG_PATH "/var/log"
static volatile sig_atomic_t syslog_run = 1; 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) static void sighandler(int signo)
{ {
@ -118,59 +59,6 @@ static void signal_setup(void)
sigaction(SIGTERM, &act, NULL); 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) static int handle_data(int fd)
{ {
char buffer[2048]; char buffer[2048];
@ -186,13 +74,12 @@ static int handle_data(int fd)
if (syslog_msg_parse(&msg, buffer)) if (syslog_msg_parse(&msg, buffer))
return -1; return -1;
return print_to_log(&msg); return logmgr->write(logmgr, &msg);
} }
int main(void) int main(void)
{ {
int sfd, status = EXIT_FAILURE; int sfd, status = EXIT_FAILURE;
logfile_t *log;
signal_setup(); signal_setup();
@ -200,7 +87,7 @@ int main(void)
if (sfd < 0) if (sfd < 0)
return EXIT_FAILURE; return EXIT_FAILURE;
if (directory_setup()) if (logmgr->init(logmgr))
goto out; goto out;
while (syslog_run) { while (syslog_run) {
@ -209,12 +96,7 @@ int main(void)
status = EXIT_SUCCESS; status = EXIT_SUCCESS;
out: out:
while (logfiles != NULL) { logmgr->cleanup(logmgr);
log = logfiles;
logfiles = logfiles->next;
logfile_destroy(log);
}
if (sfd > 0) if (sfd > 0)
close(sfd); close(sfd);
unlink(SYSLOG_SOCKET); unlink(SYSLOG_SOCKET);