diff --git a/configure.ac b/configure.ac index 9c8e72ae..d57f3641 100644 --- a/configure.ac +++ b/configure.ac @@ -56,6 +56,9 @@ AC_ARG_ENABLE(watchdog, AC_ARG_ENABLE(inetd, AS_HELP_STRING([--disable-inetd], [Disable built-in inetd super server, default enabled])) +AC_ARG_ENABLE(logrotate, + AS_HELP_STRING([--disable-logrotate], [Disable built-in rotation of /var/log/wtmp, default enabled])) + AC_ARG_ENABLE(quiet, AS_HELP_STRING([--disable-quiet], [Default Finit obeys the kernel quiet option])) @@ -145,6 +148,9 @@ AS_IF([test "x$enable_inetd" != "xno"], [ enable_inetd="yes" AC_DEFINE(INETD_ENABLED, 1, [Enable built-in inetd])]) +AS_IF([test "x$enable_logrotate" != "xno"], [ + AC_DEFINE(LOGROTATE_ENABLED, 1, [Enable built-in rotation of /var/log/wtmp et al.])]) + AS_IF([test "x$enable_quiet" != "xno"], [ AC_DEFINE(QUIET_MODE, 1, [Silent, after initial boot, no stopping/starting messages. Default: 1]) ], [ diff --git a/src/utmp-api.c b/src/utmp-api.c index 87dd8c80..df9e711a 100644 --- a/src/utmp-api.c +++ b/src/utmp-api.c @@ -21,6 +21,9 @@ * THE SOFTWARE. */ +#include "config.h" + +#include #include #include #include @@ -28,6 +31,14 @@ #include #include +#include "helpers.h" + +#ifndef _PATH_BTMP +#define _PATH_BTMP "/var/log/btmp" +#endif + +#define MAX_NO 2 +#define MAX_SZ 100 * 1024 static void utmp_strncpy(char *dst, const char *src, size_t dlen) { @@ -40,6 +51,62 @@ static void utmp_strncpy(char *dst, const char *src, size_t dlen) dst[i] = 0; } +#ifdef LOGROTATE_ENABLED +static int logrotate(char *file, int num, off_t sz) +{ + struct stat st; + + if (stat(file, &st)) + return 1; + + if (sz > 0 && S_ISREG(st.st_mode) && st.st_size > sz) { + if (num > 0) { + size_t len = strlen(file) + 3 + 1; + char ofile[len]; + char nfile[len]; + + while (num) { + snprintf(ofile, len, "%s.%d", file, num - 1); + snprintf(nfile, len, "%s.%d", file, num--); + + /* May fail because ofile doesn't exist yet, ignore. */ + (void)rename(ofile, nfile); + } + + rename(file, nfile); + create(file, st.st_mode, st.st_uid, st.st_gid); + } else { + truncate(file, 0); + } + } + + return 0; +} +#endif /* LOGROTATE_ENABLED */ + +/* + * Rotate /var/log/wtmp (+ btmp?) and /run/utmp + * + * Useful on systems with no logrotate daemon, e.g. BusyBox based + * systems where syslogd rotates its own log files only. + */ +void utmp_logrotate(void) +{ +#ifdef LOGROTATE_ENABLED + int i; + char *files[] = { + _PATH_UTMP, + _PATH_WTMP, + _PATH_BTMP, + _PATH_LASTLOG, + NULL + }; + + for (i = 0; files[i]; i++) + logrotate(files[i], MAX_NO, MAX_SZ); +#endif /* LOGROTATE_ENABLED */ +} + int utmp_set(int type, int pid, char *line, char *id, char *user) { int result = 0; @@ -75,6 +142,8 @@ int utmp_set(int type, int pid, char *line, char *id, char *user) result += pututline(&ut) ? 0 : 1; endutent(); } + + utmp_logrotate(); updwtmp(_PATH_WTMP, &ut); return result;