Index: support/rotatelogs.c =================================================================== --- support/rotatelogs.c (revision 597046) +++ support/rotatelogs.c (working copy) @@ -42,6 +42,7 @@ #include "apr_file_info.h" #include "apr_general.h" #include "apr_time.h" +#include "apr_getopt.h" #if APR_HAVE_STDLIB_H #include @@ -60,6 +61,37 @@ #define MAX_PATH 1024 #endif +static void usage(const char *argv0, const char *reason) +{ + if (reason) { + fprintf(stderr, "%s\n", reason); + } + fprintf(stderr, + "Usage: %s [-l] " + "{|} " + "[offset minutes from UTC]\n\n", + argv0); +#ifdef OS2 + fprintf(stderr, + "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n", + argv0); +#else + fprintf(stderr, + "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n", + argv0); + fprintf(stderr, + "or \n\nTransferLog \"|%s /some/where 5M\"\n\n", argv0); +#endif + fprintf(stderr, + "to httpd.conf. The generated name will be /some/where.nnnn " + "where nnnn is the\nsystem time at which the log nominally " + "starts (N.B. if using a rotation time,\nthe time will always " + "be a multiple of the rotation time, so you can synchronize\n" + "cron scripts with it). At the end of each rotation time or " + "when the file size\nis reached a new log is started.\n"); + exit(1); +} + int main (int argc, const char * const argv[]) { char buf[BUFSIZE], buf2[MAX_PATH], errbuf[ERRMSGSZ]; @@ -73,72 +105,59 @@ const char *szLogRoot; apr_file_t *f_stdin, *nLogFD = NULL, *nLogFDprev = NULL; apr_pool_t *pool; + apr_getopt_t *opt; + apr_status_t rv; + char c; + const char *optarg; char *ptr = NULL; - int argBase = 0; - int argFile = 1; - int argIntv = 2; - int argOffset = 3; apr_app_initialize(&argc, &argv, NULL); atexit(apr_terminate); apr_pool_create(&pool, NULL); - if ((argc > 2) && (strcmp(argv[1], "-l") == 0)) { - argBase++; - argFile += argBase; - argIntv += argBase; - argOffset += argBase; - use_localtime = 1; + apr_getopt_init(&opt, pool, argc, argv); + while ((rv = apr_getopt(opt, "l", &c, &optarg)) == APR_SUCCESS) { + switch (c) { + case 'l': + use_localtime = 1; + break; + } } - if (argc < (argBase + 3) || argc > (argBase + 4)) { - fprintf(stderr, - "Usage: %s [-l] " - "[offset minutes from UTC] or \n\n", - argv[0]); -#ifdef OS2 - fprintf(stderr, - "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n", - argv[0]); -#else - fprintf(stderr, - "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n", - argv[0]); - fprintf(stderr, - "or \n\nTransferLog \"|%s /some/where 5M\"\n\n", argv[0]); -#endif - fprintf(stderr, - "to httpd.conf. The generated name will be /some/where.nnnn " - "where nnnn is the\nsystem time at which the log nominally " - "starts (N.B. if using a rotation time,\nthe time will always " - "be a multiple of the rotation time, so you can synchronize\n" - "cron scripts with it). At the end of each rotation time or " - "when the file size\nis reached a new log is started.\n"); - exit(1); + + if (rv != APR_EOF) { + usage(argv[0], NULL /* specific error message already issued */ ); } - szLogRoot = argv[argFile]; + if (opt->ind + 2 != argc && opt->ind + 3 != argc) { + usage(argv[0], "Incorrect number of arguments"); + } - ptr = strchr(argv[argIntv], 'M'); - if (ptr) { + szLogRoot = argv[opt->ind++]; + + ptr = strchr(argv[opt->ind], 'M'); + if (ptr) { /* rotation based on file size */ if (*(ptr+1) == '\0') { - sRotation = atoi(argv[argIntv]) * 1048576; + sRotation = atoi(argv[opt->ind]) * 1048576; } if (sRotation == 0) { - fprintf(stderr, "Invalid rotation size parameter\n"); - exit(1); + usage(argv[0], "Invalid rotation size parameter"); } } - else { - if (argc >= (argBase + 4)) { - utc_offset = atoi(argv[argOffset]) * 60; - } - tRotation = atoi(argv[argIntv]); + else { /* rotation based on elapsed time */ + tRotation = atoi(argv[opt->ind]); if (tRotation <= 0) { - fprintf(stderr, "Rotation time must be > 0\n"); - exit(6); + usage(argv[0], "Invalid rotation time parameter"); } } + opt->ind++; + if (opt->ind < argc) { /* have UTC offset */ + if (use_localtime) { + usage(argv[0], "UTC offset parameter is not valid with -l"); + } + utc_offset = atoi(argv[opt->ind]) * 60; + } + use_strftime = (strchr(szLogRoot, '%') != NULL); if (apr_file_open_stdin(&f_stdin, pool) != APR_SUCCESS) { fprintf(stderr, "Unable to open stdin\n"); @@ -194,7 +213,16 @@ tLogStart = (now / tRotation) * tRotation; } else { - tLogStart = (int)apr_time_sec(apr_time_now()); + if (use_localtime) { + /* Check for our UTC offset before using it, since it might + * change if there's a switch between standard and daylight + * savings time. + */ + apr_time_exp_t lt; + apr_time_exp_lt(<, apr_time_now()); + utc_offset = lt.tm_gmtoff; + } + tLogStart = (int)apr_time_sec(apr_time_now()) + utc_offset; } if (use_strftime) { Index: docs/manual/programs/rotatelogs.xml =================================================================== --- docs/manual/programs/rotatelogs.xml (revision 597046) +++ docs/manual/programs/rotatelogs.xml (working copy) @@ -27,33 +27,8 @@

rotatelogs is a simple program for use in - conjunction with Apache's piped logfile feature. For example:

- - - CustomLog "|bin/rotatelogs /var/logs/logfile 86400" common - - -

This creates the files /var/logs/logfile.nnnn where nnnn is - the system time at which the log nominally starts (this time - will always be a multiple of the rotation time, so you can - synchronize cron scripts with it). At the end of each rotation - time (here after 24 hours) a new log is started.

- - - CustomLog "|bin/rotatelogs /var/logs/logfile 5M" common - - -

This configuration will rotate the logfile whenever it reaches - a size of 5 megabytes.

- - - ErrorLog "|bin/rotatelogs /var/logs/errorlog.%Y-%m-%d-%H_%M_%S 5M" - -

This configuration will rotate the error logfile whenever it - reaches a size of 5 megabytes, and the suffix to the logfile name - will be created of the form - errorlog.YYYY-mm-dd-HH_MM_SS.

- + conjunction with Apache's piped logfile feature. It supports + rotation based on a time interval or maximum size of the log.

Synopsis @@ -61,8 +36,8 @@

rotatelogs [ -l ] logfile - [ rotationtime [ offset ]] | - [ filesizeM ]

+ rotationtime|filesizeM + [ offset ]

Options @@ -71,8 +46,10 @@
-l
Causes the use of local time rather than GMT as the base for the -interval. Note that using -l in an environment which changes the -GMT offset (such as for BST or DST) can lead to unpredictable results!
+interval or for strftime(3) formatting with size-based +rotation. Note that using -l in an environment which +changes the GMT offset (such as for BST or DST) can lead to unpredictable +results!
logfile
@@ -81,26 +58,73 @@ strftime(3). Otherwise, the suffix .nnnnnnnnnn is automatically added and is the time in seconds. Both formats compute the start time from the beginning of -the current period. +the current period. For example, if a rotation time of 86400 is +specified, the hour, minute, and second fields created by +strftime(3) format will all be zero, referring to the +beginning of the current 24-hour period (midnight).
rotationtime
-
The time between log file rotations in seconds.
+
The time between log file rotations in seconds. The rotation +occurs at the beginning of this interval. For example, if the +rotation time is 3600, the log file will be rotated at the beginning +of every hour; if the rotation time is 86400, the log file will be +rotated every night at midnight. (If no data is logged during an +interval, no file will be created.)
+
filesizeM
+ +
The maximum file size in megabytes followed by the letter +M to specify size rather than time.
+
offset
The number of minutes offset from UTC. If omitted, zero is assumed and UTC is used. For example, to use local time in the zone -UTC -5 hours, specify a value of -300 for this argument.
+UTC -5 hours, specify a value of -300 for this argument. +In most cases, -l should be used instead of specifying +an offset. -
filesizeM
- -
The maximum file size in megabytes followed by the letter -M to specify size rather than time. Use this parameter -in place of both rotationtime and offset.
+
Examples + + + CustomLog "|bin/rotatelogs /var/logs/logfile 86400" common + + +

This creates the files /var/logs/logfile.nnnn where nnnn is + the system time at which the log nominally starts (this time + will always be a multiple of the rotation time, so you can + synchronize cron scripts with it). At the end of each rotation + time (here after 24 hours) a new log is started.

+ + + CustomLog "|bin/rotatelogs -l /var/logs/logfile.%Y.%m.%d 86400" common + + +

This creates the files /var/logs/logfile.yyyy.mm.dd where + yyyy is the year, mm is the month, and dd is the day of the month. + Logging will switch to a new file every day at midnight, local time.

+ + + CustomLog "|bin/rotatelogs /var/logs/logfile 5M" common + + +

This configuration will rotate the logfile whenever it reaches + a size of 5 megabytes.

+ + + ErrorLog "|bin/rotatelogs /var/logs/errorlog.%Y-%m-%d-%H_%M_%S 5M" + +

This configuration will rotate the error logfile whenever it + reaches a size of 5 megabytes, and the suffix to the logfile name + will be created of the form + errorlog.YYYY-mm-dd-HH_MM_SS.

+ +
+
Portability

The following logfile format string substitutions should be