summaryrefslogtreecommitdiff
path: root/syslogd
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@tele2.at>2018-08-16 22:32:34 +0200
committerDavid Oberhollenzer <david.oberhollenzer@tele2.at>2018-08-16 22:48:55 +0200
commit29e4fc5607ace15c0be03fab6930acfadda2610a (patch)
tree3b8c8068bc5afd0ee1e76c0277058f42f058f758 /syslogd
parent21b88d935267503a52d12c208145ccf61562c441 (diff)
usyslogd: more control over log rotate behaviour, command line processing
- Add more fine grained control over how log rotation is supposed to behave - Add command line option processing to usyslogd - Expose log rotation control via command line switches - Add default values to usyslogd service for pygos use case Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
Diffstat (limited to 'syslogd')
-rw-r--r--syslogd/backend.h24
-rw-r--r--syslogd/logfile.c31
-rw-r--r--syslogd/main.c78
3 files changed, 122 insertions, 11 deletions
diff --git a/syslogd/backend.h b/syslogd/backend.h
index b5e238a..5880ee3 100644
--- a/syslogd/backend.h
+++ b/syslogd/backend.h
@@ -20,8 +20,30 @@
#include "proto.h"
+enum {
+ /*
+ Rotate log data in a way that we still generate a continuous stream
+ of log data. E.g. in the case of log files, move the current log file
+ to one suffixed with a timestamp. We don't lose any log data.
+ */
+ LOG_ROTATE_CONTINUOUS = 0x00,
+
+ /*
+ Rotate log data by overwriting old data with more recent data.
+ E.g. in the case of log files, move the current log file to one
+ with a constant prefix, overwriting any existing data.
+ */
+ LOG_ROTATE_OVERWRITE = 0x01,
+
+ /*
+ Automatically do a log rotatation if a log stream reaches a preset
+ size limit.
+ */
+ LOG_ROTATE_SIZE_LIMIT = 0x10,
+};
+
typedef struct log_backend_t {
- int (*init)(struct log_backend_t *log);
+ int (*init)(struct log_backend_t *log, int flags, size_t sizelimit);
void (*cleanup)(struct log_backend_t *log);
diff --git a/syslogd/logfile.c b/syslogd/logfile.c
index 2adc136..606db8e 100644
--- a/syslogd/logfile.c
+++ b/syslogd/logfile.c
@@ -83,6 +83,8 @@ typedef struct logfile_t {
typedef struct {
log_backend_t base;
logfile_t *list;
+ size_t maxsize;
+ int flags;
} log_backend_file_t;
@@ -156,16 +158,20 @@ static int logfile_write(logfile_t *file, const syslog_msg_t *msg)
return 0;
}
-static int logfile_rotate(logfile_t *f)
+static int logfile_rotate(logfile_t *f, int flags)
{
char timebuf[32];
char *filename;
struct tm tm;
time_t now;
- now = time(NULL);
- gmtime_r(&now, &tm);
- strftime(timebuf, sizeof(timebuf), "%FT%T", &tm);
+ if (flags & LOG_ROTATE_OVERWRITE) {
+ strcpy(timebuf, "1");
+ } else {
+ now = time(NULL);
+ gmtime_r(&now, &tm);
+ strftime(timebuf, sizeof(timebuf), "%FT%T", &tm);
+ }
filename = alloca(strlen(f->filename) + strlen(timebuf) + 2);
sprintf(filename, "%s.%s", f->filename, timebuf);
@@ -182,9 +188,10 @@ static int logfile_rotate(logfile_t *f)
/*****************************************************************************/
-static int file_backend_init(log_backend_t *log)
+static int file_backend_init(log_backend_t *backend, int flags,
+ size_t sizelimit)
{
- (void)log;
+ log_backend_file_t *log = (log_backend_file_t *)backend;
if (mkdir(SYSLOG_PATH, 0755)) {
if (errno != EEXIST) {
@@ -198,6 +205,8 @@ static int file_backend_init(log_backend_t *log)
return -1;
}
+ log->flags = flags;
+ log->maxsize = sizelimit;
return 0;
}
@@ -254,7 +263,13 @@ static int file_backend_write(log_backend_t *backend, const syslog_msg_t *msg)
log->list = f;
}
- return logfile_write(f, msg);
+ if (logfile_write(f, msg))
+ return -1;
+
+ if ((log->flags & LOG_ROTATE_SIZE_LIMIT) && f->size >= log->maxsize)
+ logfile_rotate(f, log->flags);
+
+ return 0;
}
static void file_backend_rotate(log_backend_t *backend)
@@ -263,7 +278,7 @@ static void file_backend_rotate(log_backend_t *backend)
logfile_t *f;
for (f = log->list; f != NULL; f = f->next)
- logfile_rotate(f);
+ logfile_rotate(f, log->flags);
}
log_backend_file_t filebackend = {
diff --git a/syslogd/main.c b/syslogd/main.c
index 6b4937e..7a466d6 100644
--- a/syslogd/main.c
+++ b/syslogd/main.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <signal.h>
#include <string.h>
+#include <getopt.h>
#include <errno.h>
#include <stdio.h>
@@ -32,9 +33,41 @@
#define SYSLOG_SOCKET "/dev/log"
+#define GPL_URL "https://gnu.org/licenses/gpl.html"
+
+
+static const struct option long_opts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "rotate-replace", no_argument, NULL, 'r' },
+ { "max-size", required_argument, NULL, 'm' },
+ { NULL, 0, NULL, 0 },
+};
+
+const char *short_opts = "hVrm:";
+
+const char *version_string =
+"usyslogd (pygos init) " PACKAGE_VERSION "\n"
+"Copyright (C) 2018 David Oberhollenzer\n\n"
+"License GPLv3+: GNU GPL version 3 or later <" GPL_URL ">.\n"
+"This is free software: you are free to change and redistribute it.\n"
+"There is NO WARRANTY, to the extent permitted by law.\n";
+
+const char *usage_string =
+"Usage: usyslogd [OPTIONS..]\n\n"
+"The following options are supported:\n"
+" -h, --help Print this help text and exit\n"
+" -V, --version Print version information and exit\n"
+" -r, --rotate-replace Replace old log files when doing log rotation.\n"
+" -m, --max-size <size> Automatically rotate log files bigger than this.\n";
+
+
static volatile sig_atomic_t syslog_run = 1;
static volatile sig_atomic_t syslog_rotate = 0;
+static int log_flags = 0;
+static size_t max_size = 0;
+
static void sighandler(int signo)
@@ -82,17 +115,58 @@ static int handle_data(int fd)
return logmgr->write(logmgr, &msg);
}
-int main(void)
+static void process_options(int argc, char **argv)
+{
+ char *end;
+ int i;
+
+ for (;;) {
+ i = getopt_long(argc, argv, short_opts, long_opts, NULL);
+ if (i == -1)
+ break;
+
+ switch (i) {
+ case 'r':
+ log_flags |= LOG_ROTATE_OVERWRITE;
+ break;
+ case 'm':
+ log_flags |= LOG_ROTATE_SIZE_LIMIT;
+ max_size = strtol(optarg, &end, 10);
+ if (max_size == 0 || *end != '\0') {
+ fputs("Numeric argument > 0 expected for -m\n",
+ stderr);
+ goto fail;
+ }
+ break;
+ case 'h':
+ fputs(usage_string, stdout);
+ exit(EXIT_SUCCESS);
+ case 'V':
+ fputs(version_string, stdout);
+ exit(EXIT_SUCCESS);
+ default:
+ goto fail;
+ }
+ }
+ return;
+fail:
+ fputs("Try `usyslogd --help' for more information\n", stderr);
+ exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv)
{
int sfd, status = EXIT_FAILURE;
+ process_options(argc, argv);
+
signal_setup();
sfd = mksock(SYSLOG_SOCKET, SOCK_FLAG_EVERYONE | SOCK_FLAG_DGRAM);
if (sfd < 0)
return EXIT_FAILURE;
- if (logmgr->init(logmgr))
+ if (logmgr->init(logmgr, log_flags, max_size))
goto out;
while (syslog_run) {