mirror of
https://github.com/pygos/init.git
synced 2024-12-22 23:30:50 +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:
parent
0624f95de6
commit
4311b9a2f1
4 changed files with 175 additions and 147 deletions
|
@ -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)
|
||||
|
|
|
@ -18,18 +18,18 @@
|
|||
#ifndef LOGFILE_H
|
||||
#define LOGFILE_H
|
||||
|
||||
typedef struct logfile_t {
|
||||
struct logfile_t *next;
|
||||
int facility;
|
||||
int fd;
|
||||
#include "proto.h"
|
||||
|
||||
char filename[];
|
||||
} logfile_t;
|
||||
typedef struct log_backend_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 */
|
|
@ -20,15 +20,72 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
void logfile_write(logfile_t *file, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
lvl_str = enum_to_name(levels, msg->level);
|
||||
if (lvl_str == NULL)
|
||||
return -1;
|
||||
|
||||
va_start(ap, format);
|
||||
vdprintf(file->fd, format, ap);
|
||||
va_end(ap);
|
||||
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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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;
|
||||
|
|
126
syslogd/main.c
126
syslogd/main.c
|
@ -25,75 +25,16 @@
|
|||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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);
|
||||
|
|
Loading…
Reference in a new issue