mirror of
https://github.com/pygos/init.git
synced 2024-11-22 19:19:47 +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/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)
|
||||||
|
|
|
@ -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 */
|
|
@ -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;
|
||||||
|
|
126
syslogd/main.c
126
syslogd/main.c
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue