diff --git a/ChangeLog.md b/ChangeLog.md index 832588a..005a12d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -9,12 +9,19 @@ All relevant changes to the project are documented in this file. ### Changes - IPv6 support forward ported from FreeBSD, by John Haxby - Built-in log rotation support from BusyBox syslogd, disabled by default +- Automatic compression (gzip) of rotated files from .1 - Only read /etc/services when needed, by Martin Schulze - Improved sleep/alarm/mark implementation, by Alan Jenkins - Move hostname setting code from `main()` into `init()`, by Thomas Jarosch - Documentation update by Martin Schulze +- Reindent code to Linux KNF +- Touch PID file on `SIGHUP`, for integration with Finit +- Add systemd unit files +- Add GNU configure & build system + - Add configure flags to enable features and control behavior + - Detect systemd PATHs ### Fixes - Correct continuation line problems on 64bit architecture, @@ -138,6 +145,7 @@ All relevant changes to the project are documented in this file. [UNRELEASED]: https://github.com/troglobit/sysklogd/compare/v1.5...HEAD +[v1.6]: https://github.com/troglobit/sysklogd/compare/v1.5...v1.6 [v1.5.1]: https://github.com/troglobit/sysklogd/compare/v1.5...v1.5.1 [v1.5]: https://github.com/troglobit/sysklogd/compare/v1.4...v1.5 [v1.4]: https://github.com/troglobit/sysklogd/compare/v1.3...v1.4 diff --git a/README.md b/README.md index 96e1739..37bc195 100644 --- a/README.md +++ b/README.md @@ -30,12 +30,13 @@ determine a `System.map` file. Main differences from the original sysklogd are: -- Built-in log-rotation support, useful for embedded systems. No need - for cron and a separate logrotate daemon +- Built-in log-rotation support, with compression by default, useful for + embedded systems. No need for cron and a separate logrotate daemon - FreeBSD socket receive buffer size patch - Avoid blocking `syslogd` if console is backed up - Touch PID file on `SIGHUP`, for integration with [Finit][] -- Support for configuring remote syslog timeouot +- GNU configure & build system to ease porting/cross-compiling +- Support for configuring remote syslog timeout Build & Install diff --git a/configure.ac b/configure.ac index 7eb2181..012447a 100644 --- a/configure.ac +++ b/configure.ac @@ -31,6 +31,10 @@ AC_HEADER_STDC # Check for required packages PKG_PROG_PKG_CONFIG +AC_ARG_WITH(suspend-time, + AS_HELP_STRING([--with-suspend-time=SEC], [Retry timeout for remote syslogd servers, default: 180]), + [suspend_time=$withval], [suspend_time='no']) + AC_ARG_WITH(klogd-delay, AS_HELP_STRING([--with-klogd-delay=SEC], [when started at the same time as syslogd, default: 0]), [klogd_delay=$withval], [klogd_delay='no']) @@ -43,6 +47,12 @@ AC_ARG_WITH(systemd, [AS_HELP_STRING([--with-systemd=DIR], [Directory for systemd service files])],, [with_systemd=auto]) +AS_IF([test "x$suspend_time" != "xno"],[ + AS_IF([test "x$suspend_time" = "xyes"],[ + AC_MSG_ERROR([Must supply argument])]) + ] + AC_DEFINE_UNQUOTED(INET_SUSPEND_TIME, $suspend_time, [Retry timeout for remote syslgod servers, default: 180])) + AS_IF([test "x$klogd_delay" != "xno"],[ AS_IF([test "x$klogd_delay" = "xyes"],[ AC_MSG_ERROR([Must supply argument])]) diff --git a/man/sysklogd.8 b/man/sysklogd.8 index 65f8714..0a63a8f 100644 --- a/man/sysklogd.8 +++ b/man/sysklogd.8 @@ -111,7 +111,15 @@ described by the people from OpenBSD at .BI "\-b " "size" This option controls the max size of files in the built-in log-rotation. When present on the command line it activates log rotation of all files -with the given maximum size. Default: disabled (0). +with the given maximum size. It is also possible to control log rotate +per log file, see +.BR syslog.conf (5) +for details. + +The size argument takes optional modifiers; k, M, G. E.g., 100M is +100MB, 42k is 42 kB, etc. + +Default: disabled (0). .TP .BI "\-c " "count" This option controls the max number of files kept by the built-in @@ -119,7 +127,12 @@ log-rotation. To activate the built-in log rotation this option must be combined with the .BI "\-b" option. The number of files kept include both gzipped files and the -first rotated (not zipped) file. Default: 5. +first rotated (not zipped) file. It is also possible to control log +rotate per log file, see +.BR syslog.conf (5) +for details. + +Default: 5. .TP .B "\-d" Turns on debug mode. Using this the daemon will not proceed a diff --git a/man/syslog.conf.5 b/man/syslog.conf.5 index 4327a17..1bb1f03 100644 --- a/man/syslog.conf.5 +++ b/man/syslog.conf.5 @@ -30,13 +30,20 @@ for logging. For special features see the .BR sysklogd (8) manpage. -Every rule consists of two fields, a +Every rule consists of two fields, a .I selector -field and an -.I action -field. These two fields are separated by one or more spaces or -tabs. The selector field specifies a pattern of facilities and -priorities belonging to the specified action. +field an +.I action +and an optional +.I logrotate +field. The fields are separated by one or more spaces or tabs. The +selector field specifies a pattern of facilities and priorities +belonging to the specified action. The action details where or what to +do with the selected input. The optional logrotate field is only for +files and details the max SIZE:COUNT a file can reach before it is +rotated, and later compressed. The log rotated feature is mostly +intended for embedded systems that do not want to have cron and a +separate log rotate daemon. Lines starting with a hash mark (``#'') and empty lines are ignored. @@ -326,6 +333,20 @@ and store them in the file # *.=info;*.=notice;\\ mail.none /var/log/messages +.fi +.LP +The following is almost the same but will also log rotate and compress +aged out messages. The size argument takes the same modifiers as the +command line '-b' option. Notice the leading '-' to ensure the file is +flushed to disk after each message. + +.IP +.nf +# Log all messages, including kernel, to messages file +# rotated every 100 kB and keep up to 10 aged out and +# compressed files. +*.*;kern,kern.none -/log/messages 100k:10 + .fi .LP This lets the diff --git a/src/Makefile.am b/src/Makefile.am index 186268c..e9153ba 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,8 +21,10 @@ sbin_PROGRAMS = syslogd klogd AM_CFLAGS = -fomit-frame-pointer -fno-strength-reduce -Wno-unused-result syslogd_SOURCES = syslogd.c pidfile.c pidfile.h -syslogd_CPPFLAGS = -DSYSV -DFSSTND -DSYSLOG_INET -DINET6 -DNO_SCCS -DSYSLOG_UNIXAF +syslogd_CPPFLAGS = -DSYSV -DFSSTND -DSYSLOG_INET -DINET6 -DNO_SCCS -DSYSLOG_UNIXAF \ + -D_BSD_SOURCE -D_SVID_SOURCE -D_DEFAULT_SOURCE -klogd_SOURCES = klogd.c klogd.h syslog.c pidfile.c pidfile.h \ +klogd_SOURCES = klogd.c klogd.h syslog.c pidfile.c pidfile.h \ ksym.c ksyms.h ksym_mod.c module.h -klogd_CPPFLAGS = -DSYSV -DFSSTND -DALLOW_KERNEL_LOGGING +klogd_CPPFLAGS = -DSYSV -DFSSTND -DALLOW_KERNEL_LOGGING \ + -D_BSD_SOURCE -D_SVID_SOURCE -D_DEFAULT_SOURCE diff --git a/src/klogd.c b/src/klogd.c index 897879d..f6e92be 100644 --- a/src/klogd.c +++ b/src/klogd.c @@ -257,6 +257,7 @@ /* Includes. */ #include +#include #include #include #ifdef SYSV diff --git a/src/syslogd.c b/src/syslogd.c index cae50bf..c5949a1 100644 --- a/src/syslogd.c +++ b/src/syslogd.c @@ -521,6 +521,7 @@ static char sccsid[] = "@(#)syslogd.c 5.27 (Berkeley) 10/10/88"; #define CONT_LINE 1 /* Allow continuation lines */ #include +#include #include #include #include @@ -696,6 +697,8 @@ struct filed { int f_prevcount; /* repetition cnt of prevline */ size_t f_repeatcount; /* number of "repeated" msgs */ int f_flags; /* store some additional flags */ + int f_rotatecount; + int f_rotatesz; }; /* @@ -839,6 +842,7 @@ void die(int sig); void doexit(int sig); #endif void init(); +static int strtobytes(char *arg); void cfline(char *line, struct filed *f); int decode(char *name, struct code *codetab); static void logit(char *, ...); @@ -927,7 +931,7 @@ int main(int argc, char *argv[]) break; case 'b': /* Max file size (bytes) before rotating log file. */ - RotateSz = atoi(optarg); + RotateSz = strtobytes(optarg); break; case 'c': /* Number (count) of log files to keep. */ @@ -1857,28 +1861,43 @@ void logrotate(struct filed *f) { struct stat statf; - if (!RotateSz) + if (!f->f_rotatesz) return; fstat(f->f_file, &statf); /* bug (mostly harmless): can wrap around if file > 4gb */ - if (S_ISREG(statf.st_mode) && statf.st_size > RotateSz) { - if (RotateCnt) { /* always 0..99 */ - int i = strlen(f->f_un.f_fname) + 3 + 1; - char oldFile[i]; - char newFile[i]; + if (S_ISREG(statf.st_mode) && statf.st_size > f->f_rotatesz) { + if (f->f_rotatecount > 0) { /* always 0..999 */ + int len = strlen(f->f_un.f_fname) + 10 + 1; + int i; + char oldFile[len]; + char newFile[len]; + + /* First age zipped log files */ + for (i = f->f_rotatecount; i > 1; i--) { + snprintf(oldFile, len, "%s.%d.gz", f->f_un.f_fname, i - 1); + snprintf(newFile, len, "%s.%d.gz", f->f_un.f_fname, i); - i = RotateCnt - 1; - /* rename: f.8 -> f.9; f.7 -> f.8; ... */ - while (1) { - sprintf(newFile, "%s.%d", f->f_un.f_fname, i); - if (i == 0) - break; - sprintf(oldFile, "%s.%d", f->f_un.f_fname, --i); /* ignore errors - file might be missing */ - rename(oldFile, newFile); + (void)rename(oldFile, newFile); } + + /* rename: f.8 -> f.9; f.7 -> f.8; ... */ + for (i = 1; i > 0; i--) { + sprintf(oldFile, "%s.%d", f->f_un.f_fname, i - 1); + sprintf(newFile, "%s.%d", f->f_un.f_fname, i); + + if (!rename(oldFile, newFile) && i > 0) { + size_t len = 18 + strlen(newFile) + 1; + char cmd[len]; + + snprintf(cmd, sizeof(cmd), "gzip -f %s", newFile); + system(cmd); + } + } + /* newFile == "f.0" now */ + sprintf(newFile, "%s.0", f->f_un.f_fname); rename(f->f_un.f_fname, newFile); close(f->f_file); f->f_file = open(f->f_un.f_fname, O_WRONLY | O_APPEND | O_CREAT | O_NONBLOCK | O_NOCTTY, 0644); @@ -1947,8 +1966,7 @@ void fprintlog(struct filed *f, char *from, int flags, char *msg) logit(" %s\n", f->f_un.f_forw.f_hname); logit("Forwarding suspension not over, time " "left: %d.\n", - INET_SUSPEND_TIME - - fwd_suspend); + INET_SUSPEND_TIME - fwd_suspend); } break; @@ -2727,6 +2745,35 @@ void init(void) } /* balance parentheses for emacs */ #endif +static int strtobytes(char *arg) +{ + int mod = 0, bytes; + size_t pos; + + if (!arg) + return -1; + + pos = strspn(arg, "0123456789"); + if (arg[pos] != 0) { + if (arg[pos] == 'G') + mod = 3; + else if (arg[pos] == 'M') + mod = 2; + else if (arg[pos] == 'k') + mod = 1; + else + return -1; + + arg[pos] = 0; + } + + bytes = atoi(arg); + while (mod--) + bytes *= 1000; + + return bytes; +} + /* * Crack a configuration file line */ @@ -2755,6 +2802,10 @@ void cfline(char *line, struct filed *f) f->f_flags = 0; } + /* default rotate from command line */ + f->f_rotatecount = RotateCnt; + f->f_rotatesz = RotateSz; + /* scan through the list of selectors */ for (p = line; *p && *p != '\t' && *p != ' ';) { @@ -2908,6 +2959,30 @@ void cfline(char *line, struct filed *f) case '|': case '/': + /* Look for optional per-file rotate BYTES:COUNT */ + for (q = p; *q && !isspace(*q); q++) + ; + if (isspace(*q)) { + char *c; + int sz = 0, cnt = 0; + + *q++ = 0; + while (*q && isspace(*q)) + q++; + + c = strchr(q, ':'); + if (c) { + *c++ = 0; + cnt = atoi(c); + } + + sz = strtobytes(q); + if (sz > 0 && cnt > 0) { + f->f_rotatecount = cnt; + f->f_rotatesz = sz; + } + } + (void)strcpy(f->f_un.f_fname, p); logit("filename: %s\n", p); /*ASP*/ if (syncfile)