diff options
Diffstat (limited to 'syslogd')
| -rw-r--r-- | syslogd/backend.h | 24 | ||||
| -rw-r--r-- | syslogd/logfile.c | 31 | ||||
| -rw-r--r-- | syslogd/main.c | 78 | 
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) { | 
