summaryrefslogtreecommitdiffstats
path: root/usr.sbin/newsyslog
diff options
context:
space:
mode:
authorwollman <wollman@FreeBSD.org>1999-01-22 19:38:39 +0000
committerwollman <wollman@FreeBSD.org>1999-01-22 19:38:39 +0000
commit27719c46cd1486850c0576f2129a7fd6b5c6255b (patch)
treeaa67fa72e16f396639059e1bf65637886ac74b3e /usr.sbin/newsyslog
parent5a3e9b235099b0a4a7782a5b8498edee4ac9802f (diff)
downloadFreeBSD-src-27719c46cd1486850c0576f2129a7fd6b5c6255b.zip
FreeBSD-src-27719c46cd1486850c0576f2129a7fd6b5c6255b.tar.gz
A slight bit of code and doco cleanup, but mostly:
Add the much-needed and long-desired ability to force the log rotation to take place on a specific day or time, and document same. This works by extending the syntax of the `when' field to allow a restricted ISO 8601 time specification, and performing the log rotation if newsyslog is run during the same hour as is specified.
Diffstat (limited to 'usr.sbin/newsyslog')
-rw-r--r--usr.sbin/newsyslog/Makefile9
-rw-r--r--usr.sbin/newsyslog/newsyslog.8136
-rw-r--r--usr.sbin/newsyslog/newsyslog.c184
-rw-r--r--usr.sbin/newsyslog/pathnames.h27
4 files changed, 284 insertions, 72 deletions
diff --git a/usr.sbin/newsyslog/Makefile b/usr.sbin/newsyslog/Makefile
index 5d83c09..ea2b61a 100644
--- a/usr.sbin/newsyslog/Makefile
+++ b/usr.sbin/newsyslog/Makefile
@@ -1,14 +1,7 @@
-# $Id: Makefile,v 1.4 1997/02/22 16:08:24 peter Exp $
+# $Id: Makefile,v 1.5 1998/09/19 22:42:11 obrien Exp $
PROG= newsyslog
-CFLAGS+= -DOSF
-CFLAGS+= -DCONF=\"/etc/newsyslog.conf\"
-CFLAGS+= -DPIDFILE=\"/var/run/syslog.pid\"
-CFLAGS+= -DCOMPRESS_PATH=\"/usr/bin/gzip\"
-CFLAGS+= -DCOMPRESS_PROG=\"gzip\"
-CFLAGS+= -DCOMPRESS_POSTFIX=\".gz\"
-
MAN8= newsyslog.8
.include <bsd.prog.mk>
diff --git a/usr.sbin/newsyslog/newsyslog.8 b/usr.sbin/newsyslog/newsyslog.8
index a13e176..d54de06 100644
--- a/usr.sbin/newsyslog/newsyslog.8
+++ b/usr.sbin/newsyslog/newsyslog.8
@@ -1,7 +1,7 @@
.\" This file contains changes from the Open Software Foundation.
.\"
.\" from: @(#)newsyslog.8
-.\" $Id: newsyslog.8,v 1.13 1998/05/10 19:04:05 hoek Exp $
+.\" $Id: newsyslog.8,v 1.14 1998/06/09 18:24:04 ache Exp $
.\"
.\" Copyright 1988, 1989 by the Massachusetts Institute of Technology
.\"
@@ -17,7 +17,7 @@
.\" the suitability of this software for any purpose. It is
.\" provided "as is" without express or implied warranty.
.\"
-.Dd January 12, 1989
+.Dd January 22, 1999
.Dt NEWSYSLOG 8
.Os
.Sh NAME
@@ -34,25 +34,41 @@ is a program that should be scheduled to run periodically by
When it is executed it archives log files if necessary. If a log file
is determined to require archiving,
.Nm
-rearranges the files so that ``logfile'' is empty, ``logfile.0'' has
-the last period's logs in it, ``logfile.1'' has the next to last
+rearranges the files so that
+.Dq Va logfile
+is empty,
+.Dq Va logfile Ns Li \&.0
+has
+the last period's logs in it,
+.Dq Va logfile Ns Li \&.1
+has the next to last
period's logs in it, and so on, up to a user-specified number of
archived logs. Optionally the archived logs can be compressed to save
space.
.Pp
-A log can be archived because of two reasons. The log file can have
-grown bigger than a preset size in kilobytes, or a preset number of
-hours may have elapsed since the last log archive. The granularity of
+A log can be archived for three reasons:
+.Bl -enum -offset indent
+.It
+It is larger than the configured size (in kilobytes).
+.It
+A configured number of hours have elapsed since the log was last
+archived.
+.It
+This is the specific configured hour for rotation of the log.
+.El
+The granularity of
.Nm
is dependent on how often it is scheduled to run by
.Xr cron 8 .
Since the program is quite fast, it may be scheduled to run every hour
-without any ill effects.
+without any ill effects,
+and mode three (above) assumes that this is so.
.Pp
When starting up,
.Nm
-reads in a configuration file to determine which logs should be looked
-at. By default, this configuration file is
+reads in a configuration file to determine which logs may potentially
+be archived.
+By default, this configuration file is
.Pa /etc/newsyslog.conf .
Each line of the file contains information about a particular log file
that should be handled by
@@ -85,18 +101,98 @@ besides the log file itself.
When the size of the log file reaches
.Ar size ,
the log file will be trimmed as described above. If this field
-is replaced by a
-.Ar * ,
+is replaced by an asterisk
+.Pq Ql \&* ,
then the size of the log file is not taken into account
when determining when to trim the log file.
-.It Ar interval
-When
-.Ar interval
-hours have passed, the log file will be trimmed. If this field is
-replaced by a
-.Ar * ,
-then the number of hours since the last time the log was
-trimmed will not be taken into consideration.
+.It Ar when
+The
+.Ar when
+field can consist of an interval, a specific time, or both. If
+the
+.Ar when
+field is an asterisk
+.Pq Ql \&*
+log rotation will depend only on the contents of the
+.Ar size
+field.
+Otherwise, the
+.Ar when
+field consists of an optional interval in hours, optionally followed
+by an
+.So Li \&@ Sc Ns No -sign
+and a time in a restricted
+.Tn ISO 8601
+format. If a time is specified, the log file will only be trimmed
+if
+.Nm newsyslog
+is run within one hour of the specified time. If an
+interval is specified, the log file will be trimmed if that many hours have
+passed since the last rotation. When both a time and an interval are
+specified, both conditions must be satisfied for the rotation to take
+place.
+.Pp
+The particular format of the time is
+.Sm off
+.Oo
+.Oo
+.Oo
+.Oo
+.Oo
+.Va \&cc
+.Oc
+.Va \&yy
+.Oc
+.Va \&mm
+.Oc
+.Va \&dd
+.Oc
+.Oo
+.Li \&T
+.Oo
+.Va \&hh
+.Oo
+.Va \&mm
+.Oo
+.Va \&ss
+.Oc
+.Oc
+.Oc
+.Oc
+.Oc .
+.Sm on
+Optional date fields default to the appropriate component of the
+current date; optional time fields default to midnight; hence if today
+is January 22, 1999, the following date specifications are all
+equivalent:
+.Pp
+.Bl -item -compact -offset indent
+.It
+.Sq Li 19990122T000000
+.It
+.Sq Li 990122T000000
+.It
+.Sq Li 0122T000000
+.It
+.Sq Li 22T000000
+.It
+.Sq Li T000000
+.It
+.Sq Li T0000
+.It
+.Sq Li T00
+.It
+.Sq Li 22T
+.It
+.Sq Li \&T
+.It
+.Sq Li \&
+.El
+.Pp
+There is no provision for specification of a timezone. There is
+little point in specifying an explicit minutes or seconds component in
+the current implementation, since the only comparison is `within the
+hour'.
.It Ar flags
This optional field specifies if the archive should have any
special processing done to the archived log files.
diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c
index faae982..832a8c3 100644
--- a/usr.sbin/newsyslog/newsyslog.c
+++ b/usr.sbin/newsyslog/newsyslog.c
@@ -27,41 +27,33 @@ provided "as is" without express or implied warranty.
#ifndef lint
static const char rcsid[] =
- "$Id: newsyslog.c,v 1.20 1998/06/09 18:24:04 ache Exp $";
+ "$Id: newsyslog.c,v 1.21 1998/12/23 12:03:33 peter Exp $";
#endif /* not lint */
-#ifndef CONF
-#define CONF "/etc/athena/newsyslog.conf" /* Configuration file */
-#endif
-#ifndef PIDFILE
-#define PIDFILE "/etc/syslog.pid"
-#endif
-#ifndef COMPRESS_PATH
-#define COMPRESS_PATH "/usr/ucb/compress" /* File compression program */
-#endif
-#ifndef COMPRESS_PROG
-#define COMPRESS_PROG "compress"
-#endif
+#define OSF
#ifndef COMPRESS_POSTFIX
-#define COMPRESS_POSTFIX ".Z"
+#define COMPRESS_POSTFIX ".gz"
#endif
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
#include <grp.h>
+#include <paths.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include <sys/types.h>
-#include <sys/time.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/wait.h>
+#include "pathnames.h"
+
#define kbytes(size) (((size) + 1023) >> 10)
#ifdef _IBMR2
/* Calculates (db * DEV_BSIZE) */
@@ -71,6 +63,8 @@ static const char rcsid[] =
#define CE_COMPACT 1 /* Compact the achived log files */
#define CE_BINARY 2 /* Logfile is in binary, don't add */
/* status messages */
+#define CE_TRIMAT 4 /* trim at a specific time */
+
#define NONE -1
struct conf_entry {
@@ -81,6 +75,7 @@ struct conf_entry {
int numlogs; /* Number of logs to keep */
int size; /* Size cutoff to trigger trimming the log */
int hours; /* Hours between log trimming */
+ time_t trim_at; /* Specific time to do trimming */
int permissions; /* File permissions on the log */
int flags; /* Flags (CE_COMPACT & CE_BINARY) */
int sig; /* Signal to send */
@@ -91,17 +86,13 @@ int verbose = 0; /* Print out what's going on */
int needroot = 1; /* Root privs are necessary */
int noaction = 0; /* Don't do anything, just show it */
int force = 0; /* Force the trim no matter what*/
-char *conf = CONF; /* Configuration file to use */
+char *conf = _PATH_CONF; /* Configuration file to use */
time_t timenow;
#define MIN_PID 5
#define MAX_PID 99999 /* was lower, see /usr/include/sys/proc.h */
char hostname[MAXHOSTNAMELEN+1]; /* hostname */
char *daytime; /* timenow in human readable form */
-#ifndef OSF
-char *strdup(char *strp);
-#endif
-
static struct conf_entry *parse_file();
static char *sob(char *p);
static char *son(char *p);
@@ -115,6 +106,7 @@ static void compress_log(char *log);
static int sizefile(char *file);
static int age_old_log(char *file);
static pid_t get_pid(char *pid_file);
+static time_t parse8601(const char *s);
int main(argc,argv)
int argc;
@@ -155,11 +147,23 @@ static void do_entry(ent)
if (verbose)
printf("does not exist.\n");
} else {
+ if (ent->flags & CE_TRIMAT) {
+ if (timenow < ent->trim_at
+ || difftime(timenow, ent->trim_at) >= 60*60) {
+ if (verbose)
+ printf("--> will trim at %s",
+ ctime(&ent->trim_at));
+ return;
+ } else if (verbose && ent->hours <= 0) {
+ printf("--> time is up\n");
+ }
+ }
if (verbose && (ent->size > 0))
printf("size (Kb): %d [%d] ", size, ent->size);
if (verbose && (ent->hours > 0))
printf(" age (hr): %d [%d] ", modtime, ent->hours);
if (force || ((ent->size > 0) && (size >= ent->size)) ||
+ (ent->hours <= 0 && (ent->flags & CE_TRIMAT)) ||
((ent->hours > 0) && ((modtime >= ent->hours)
|| (modtime < 0)))) {
if (verbose)
@@ -177,7 +181,7 @@ static void do_entry(ent)
} else {
/* Only try to notify syslog if we are root */
if (needroot)
- pid_file = PIDFILE;
+ pid_file = _PATH_SYSLOGPID;
else
pid_file = NULL;
}
@@ -230,7 +234,7 @@ static void PRS(argc,argv)
default:
usage();
}
- }
+}
static void usage()
{
@@ -341,14 +345,34 @@ static struct conf_entry *parse_file()
else
working->size = -1;
+ working->flags = 0;
q = parse = missing_field(sob(++parse),errline);
parse = son(parse);
eol = !*parse;
*parse = '\0';
- if (isdigit(*q))
- working->hours = atoi(q);
- else
- working->hours = -1;
+ {
+ char *ep;
+ u_long ul;
+
+ ul = strtoul(q, &ep, 10);
+ if (ep == q)
+ working->hours = 0;
+ else if (*ep == '*')
+ working->hours = -1;
+ else if (ul > INT_MAX)
+ errx(1, "interval is too large:\n%s", errline);
+ else
+ working->hours = ul;
+
+ if (*ep != '\0' && *ep != '@' && *ep != '*')
+ errx(1, "malformed interval/at:\n%s", errline);
+ if (*ep == '@') {
+ if ((working->trim_at = parse8601(ep + 1))
+ == (time_t)-1)
+ errx(1, "malformed at:\n%s", errline);
+ working->flags |= CE_TRIMAT;
+ }
+ }
if (eol)
q = NULL;
@@ -360,7 +384,6 @@ static struct conf_entry *parse_file()
*parse = '\0';
}
- working->flags = 0;
while (q && *q && !isspace(*q)) {
if ((*q == 'Z') || (*q == 'z'))
working->flags |= CE_COMPACT;
@@ -517,7 +540,7 @@ static void dotrim(log,pid_file,numdays,flags,perm,owner_uid,group_gid,sig)
err(1, "can't add status message to log");
}
if (noaction)
- printf("chmod %o %s...",perm,log);
+ printf("chmod %o %s...\n", perm, log);
else
(void) chmod(log,perm);
@@ -583,8 +606,8 @@ static void compress_log(log)
if (pid < 0)
err(1, "fork");
else if (!pid) {
- (void) execl(COMPRESS_PATH,COMPRESS_PROG,"-f",tmp,0);
- err(1, COMPRESS_PATH);
+ (void) execl(_PATH_GZIP, _PATH_GZIP, "-f", tmp, 0);
+ err(1, _PATH_GZIP);
}
}
@@ -638,20 +661,6 @@ static pid_t get_pid(pid_file)
return pid;
}
-#ifndef OSF
-/* Duplicate a string using malloc */
-
-char *strdup(strp)
-register char *strp;
-{
- register char *cp;
-
- if ((cp = malloc((unsigned) strlen(strp) + 1)) == NULL)
- abort();
- return(strcpy (cp, strp));
-}
-#endif
-
/* Skip Over Blanks */
char *sob(p)
register char *p;
@@ -669,3 +678,90 @@ char *son(p)
p++;
return(p);
}
+
+/*
+ * Parse a limited subset of ISO 8601.
+ * The specific format is as follows:
+ *
+ * [CC[YY[MM[DD]]]][THH[MM[SS]]] (where `T' is the literal letter)
+ *
+ * We don't accept a timezone specification; missing fields (including
+ * timezone) are defaulted to the current date but time zero.
+ */
+static time_t
+parse8601(const char *s)
+{
+ char *t;
+ struct tm tm, *tmp;
+ u_long ul;
+
+ tmp = localtime(&timenow);
+ tm = *tmp;
+
+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
+
+ ul = strtoul(s, &t, 10);
+ if (*t != '\0' && *t != 'T')
+ return -1;
+
+ /*
+ * Now t points either to the end of the string (if no time
+ * was provided) or to the letter `T' which separates date
+ * and time in ISO 8601. The pointer arithmetic is the same for
+ * either case.
+ */
+ switch (t - s) {
+ case 8:
+ tm.tm_year = ((ul / 1000000) - 19) * 100;
+ ul = ul % 1000000;
+ case 6:
+ tm.tm_year = tm.tm_year - (tm.tm_year % 100);
+ tm.tm_year += ul / 10000;
+ ul = ul % 10000;
+ case 4:
+ tm.tm_mon = (ul / 100) - 1;
+ ul = ul % 100;
+ case 2:
+ tm.tm_mday = ul;
+ case 0:
+ break;
+ default:
+ return -1;
+ }
+
+ /* sanity check */
+ if (tm.tm_year < 70 || tm.tm_mon < 0 || tm.tm_mon > 12
+ || tm.tm_mday < 1 || tm.tm_mday > 31)
+ return -1;
+
+ if (*t != '\0') {
+ s = ++t;
+ ul = strtoul(s, &t, 10);
+ if (*t != '\0' && !isspace(*t))
+ return -1;
+
+ switch (t - s) {
+ case 6:
+ tm.tm_sec = ul % 100;
+ ul /= 100;
+ case 4:
+ tm.tm_min = ul % 100;
+ ul /= 100;
+ case 2:
+ tm.tm_hour = ul;
+ case 0:
+ break;
+ default:
+ return -1;
+ }
+
+ /* sanity check */
+ if (tm.tm_sec < 0 || tm.tm_sec > 60 || tm.tm_min < 0
+ || tm.tm_min > 59 || tm.tm_hour < 0 || tm.tm_hour > 23)
+ return -1;
+ }
+
+ return mktime(&tm);
+}
+
+
diff --git a/usr.sbin/newsyslog/pathnames.h b/usr.sbin/newsyslog/pathnames.h
new file mode 100644
index 0000000..2eb271d
--- /dev/null
+++ b/usr.sbin/newsyslog/pathnames.h
@@ -0,0 +1,27 @@
+/*
+ * This file contains changes from the Open Software Foundation.
+ */
+
+/*
+
+Copyright 1988, 1989 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, and distribute this software
+and its documentation for any purpose and without fee is
+hereby granted, provided that the above copyright notice
+appear in all copies and that both that copyright notice and
+this permission notice appear in supporting documentation,
+and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
+used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+M.I.T. and the M.I.T. S.I.P.B. make no representations about
+the suitability of this software for any purpose. It is
+provided "as is" without express or implied warranty.
+
+ $Id$
+
+*/
+
+#define _PATH_CONF "/etc/newsyslog.conf"
+#define _PATH_SYSLOGPID _PATH_VARRUN "syslog.pid"
+#define _PATH_GZIP "/usr/bin/gzip"
OpenPOWER on IntegriCloud