1 /* Copyright 1999-2004 The Apache Software Foundation
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
17 * Simple program to rotate Apache logs without having to kill the server.
19 * Contributed by Ben Laurie <ben algroup.co.uk>
23 * Ported to APR by Mladen Turk <mturk mappingsoft.com>
31 #include "apr_strings.h"
32 #include "apr_errno.h"
33 #include "apr_file_io.h"
34 #include "apr_file_info.h"
35 #include "apr_general.h"
44 #if APR_HAVE_STRINGS_H
55 int main (int argc, const char * const argv[])
57 char buf[BUFSIZE], buf2[MAX_PATH], errbuf[ERRMSGSZ];
58 int tLogEnd = 0, tRotation = 0, utc_offset = 0;
59 unsigned int sRotation = 0;
61 apr_size_t nRead, nWrite;
64 const char *szLogRoot;
65 apr_file_t *f_stdin, *nLogFD = NULL, *nLogFDprev = NULL;
69 apr_app_initialize(&argc, &argv, NULL);
70 atexit(apr_terminate);
72 apr_pool_create(&pool, NULL);
73 if (argc < 3 || argc > 4) {
75 "Usage: %s <logfile> <rotation time in seconds> "
76 "[offset minutes from UTC] or <rotation size in megabytes>\n\n",
80 "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n",
84 "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n",
87 "or \n\nTransferLog \"|%s /some/where 5M\"\n\n", argv[0]);
90 "to httpd.conf. The generated name will be /some/where.nnnn "
91 "where nnnn is the\nsystem time at which the log nominally "
92 "starts (N.B. if using a rotation time,\nthe time will always "
93 "be a multiple of the rotation time, so you can synchronize\n"
94 "cron scripts with it). At the end of each rotation time or "
95 "when the file size\nis reached a new log is started.\n");
101 ptr = strchr (argv[2], 'M');
103 if (*(ptr+1) == '\0') {
104 sRotation = atoi(argv[2]) * 1048576;
106 if (sRotation == 0) {
107 fprintf(stderr, "Invalid rotation size parameter\n");
113 utc_offset = atoi(argv[3]) * 60;
115 tRotation = atoi(argv[2]);
116 if (tRotation <= 0) {
117 fprintf(stderr, "Rotation time must be > 0\n");
122 use_strftime = (strchr(szLogRoot, '%') != NULL);
123 if (apr_file_open_stdin(&f_stdin, pool) != APR_SUCCESS) {
124 fprintf(stderr, "Unable to open stdin\n");
130 if (apr_file_read(f_stdin, buf, &nRead) != APR_SUCCESS)
133 now = (int)(apr_time_now() / APR_USEC_PER_SEC) + utc_offset;
134 if (nLogFD != NULL && now >= tLogEnd) {
139 else if (sRotation) {
141 apr_off_t current_size = -1;
143 if ((nLogFD != NULL) &&
144 (apr_file_info_get(&finfo, APR_FINFO_SIZE, nLogFD) == APR_SUCCESS)) {
145 current_size = finfo.size;
148 if (current_size > sRotation) {
154 fprintf(stderr, "No rotation time or size specified\n");
158 if (nLogFD == NULL) {
162 tLogStart = (now / tRotation) * tRotation;
164 tLogStart = (int)apr_time_sec(apr_time_now());
167 apr_time_t tNow = apr_time_from_sec(tLogStart);
171 apr_time_exp_gmt(&e, tNow);
172 apr_strftime(buf2, &rs, sizeof(buf2), szLogRoot, &e);
175 sprintf(buf2, "%s.%010d", szLogRoot, tLogStart);
177 tLogEnd = tLogStart + tRotation;
178 apr_file_open(&nLogFD, buf2, APR_READ | APR_WRITE | APR_CREATE | APR_APPEND,
179 APR_OS_DEFAULT, pool);
180 if (nLogFD == NULL) {
181 /* Uh-oh. Failed to open the new log file. Try to clear
182 * the previous log file, note the lost log entries,
183 * and keep on truckin'. */
184 if (nLogFDprev == NULL) {
185 fprintf(stderr, "1 Previous file handle doesn't exists %s\n", buf2);
191 "Resetting log file due to error opening "
192 "new log file. %10d messages lost.\n",
194 nWrite = strlen(errbuf);
195 apr_file_trunc(nLogFD, 0);
196 if (apr_file_write(nLogFD, errbuf, &nWrite) != APR_SUCCESS) {
197 fprintf(stderr, "Error writing to the file %s\n", buf2);
202 else if (nLogFDprev) {
203 apr_file_close(nLogFDprev);
208 apr_file_write(nLogFD, buf, &nWrite);
209 if (nWrite != nRead) {
212 "Error writing to log file. "
213 "%10d messages lost.\n",
215 nWrite = strlen(errbuf);
216 apr_file_trunc(nLogFD, 0);
217 if (apr_file_write(nLogFD, errbuf, &nWrite) != APR_SUCCESS) {
218 fprintf(stderr, "Error writing to the file %s\n", buf2);
226 /* Of course we never, but prevent compiler warnings */