rotatelogs.c revision ac738faa5ec958960f59f60b0109fb103874b8e3
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek/* Licensed to the Apache Software Foundation (ASF) under one or more
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * contributor license agreements. See the NOTICE file distributed with
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * this work for additional information regarding copyright ownership.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * The ASF licenses this file to You under the Apache License, Version 2.0
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * (the "License"); you may not use this file except in compliance with
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * the License. You may obtain a copy of the License at
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * http://www.apache.org/licenses/LICENSE-2.0
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Unless required by applicable law or agreed to in writing, software
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * distributed under the License is distributed on an "AS IS" BASIS,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * See the License for the specific language governing permissions and
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * limitations under the License.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek/*
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Simple program to rotate Apache logs without having to kill the server.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Contributed by Ben Laurie <ben algroup.co.uk>
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * 12 Mar 1996
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Ported to APR by Mladen Turk <mturk mappingsoft.com>
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * 23 Sep 2001
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * -l option added 2004-06-11
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * -l causes the use of local time rather than GMT as the base for the
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * interval. NB: Using -l in an environment which changes the GMT offset
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * (such as for BST or DST) can lead to unpredictable results!
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * -f option added Feb, 2008. This causes rotatelog to open/create
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * the logfile as soon as it's started, not as soon as it sees
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * data.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * -v option added Feb, 2008. Verbose output of command line parsing.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
fd8595874aa06c8057740001ec465ba76b4af142Jakub Hrozek#include "apr.h"
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek#include "apr_lib.h"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#include "apr_strings.h"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#include "apr_errno.h"
95cc3f4be93d3cb5bb28bb3787f0aace4edb3124Jakub Hrozek#include "apr_file_io.h"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#include "apr_file_info.h"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#include "apr_general.h"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#include "apr_time.h"
95cc3f4be93d3cb5bb28bb3787f0aace4edb3124Jakub Hrozek#include "apr_getopt.h"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#include "apr_thread_proc.h"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#if APR_HAVE_STDLIB_H
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#include <stdlib.h>
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#endif
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#define APR_WANT_STRFUNC
95cc3f4be93d3cb5bb28bb3787f0aace4edb3124Jakub Hrozek#include "apr_want.h"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#define BUFSIZE 65536
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#define ERRMSGSZ 256
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#ifndef MAX_PATH
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#define MAX_PATH 1024
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#endif
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#define ROTATE_NONE 0
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#define ROTATE_NEW 1
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#define ROTATE_TIME 2
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#define ROTATE_SIZE 3
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#define ROTATE_FORCE 4
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic const char *ROTATE_REASONS[] = {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "None",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "Open a new file",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "Time interval expired",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "Maximum size reached",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "Forced rotation",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek NULL
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek};
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozektypedef struct rotate_config rotate_config_t;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstruct rotate_config {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek unsigned int sRotation;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int tRotation;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int utc_offset;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int use_localtime;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int use_strftime;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int force_open;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int verbose;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int echo;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek const char *szLogRoot;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int truncate;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek const char *linkfile;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek const char *postrotate_prog;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek};
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozektypedef struct rotate_status rotate_status_t;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstruct rotate_status {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_pool_t *pool;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_pool_t *pfile;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_pool_t *pfile_prev;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_file_t *nLogFD;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_file_t *nLogFDprev;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek char filename[MAX_PATH];
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek char filenameprev[MAX_PATH];
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek char errbuf[ERRMSGSZ];
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int rotateReason;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int tLogEnd;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int nMessCount;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek};
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic rotate_config_t config;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic rotate_status_t status;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic void usage(const char *argv0, const char *reason)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek{
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (reason) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "%s\n", reason);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "Usage: %s [-v] [-l] [-L linkname] [-p prog] [-f] [-t] [-e] <logfile> "
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "{<rotation time in seconds>|<rotation size>(B|K|M|G)} "
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "[offset minutes from UTC]\n\n",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek argv0);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#ifdef OS2
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek argv0);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#else
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek argv0);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "or \n\nTransferLog \"|%s /some/where 5M\"\n\n", argv0);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek#endif
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "to httpd.conf. By default, the generated name will be\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "<logfile>.nnnn where nnnn is the system time at which the log\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "nominally starts (N.B. if using a rotation time, the time will\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "always be a multiple of the rotation time, so you can synchronize\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "cron scripts with it). If <logfile> contains strftime conversion\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "specifications, those will be used instead. At the end of each\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "rotation time or when the file size is reached a new log is\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "started.\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "Options:\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek " -v Verbose operation. Messages are written to stderr.\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek " -l Base rotation on local time instead of UTC.\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek " -L path Create hard link from current log to specified path.\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek " -p prog Run specified program after opening a new log file. See below.\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek " -f Force opening of log on program start.\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek " -t Truncate logfile instead of rotating, tail friendly.\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek " -e Echo log to stdout for further processing.\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "The program is invoked as \"[prog] <curfile> [<prevfile>]\"\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "where <curfile> is the filename of the newly opened logfile, and\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "<prevfile>, if given, is the filename of the previously used logfile.\n"
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "\n");
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek exit(1);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek}
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek/*
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Get the unix time with timezone corrections
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * given in the config struct.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic int get_now(rotate_config_t *config)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek{
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_time_t tNow = apr_time_now();
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int utc_offset = config->utc_offset;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->use_localtime) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek /* Check for our UTC offset before using it, since it might
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * change if there's a switch between standard and daylight
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * savings time.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_time_exp_t lt;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_time_exp_lt(&lt, tNow);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek utc_offset = lt.tm_gmtoff;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return (int)apr_time_sec(tNow) + utc_offset;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek}
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek/*
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Close a file and destroy the associated pool.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic void closeFile(rotate_config_t *config, apr_pool_t *pool, apr_file_t *file)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek{
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (file != NULL) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->verbose) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_finfo_t finfo;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_int32_t wanted = APR_FINFO_NAME;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_status_t rv = apr_file_info_get(&finfo, wanted, file);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if ((rv == APR_SUCCESS) || (rv == APR_INCOMPLETE)) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (finfo.valid & APR_FINFO_NAME) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Closing file %s (%s)\n", finfo.name, finfo.fname);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek } else {
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek fprintf(stderr, "Closing file %s\n", finfo.fname);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_file_close(file);
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek if (pool) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_pool_destroy(pool);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek}
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek/*
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Dump the configuration parsing result to STDERR.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic void dumpConfig (rotate_config_t *config)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek{
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Rotation time interval: %12d\n", config->tRotation);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Rotation size interval: %12d\n", config->sRotation);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Rotation time UTC offset: %12d\n", config->utc_offset);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Rotation based on localtime: %12s\n", config->use_localtime ? "yes" : "no");
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Rotation file date pattern: %12s\n", config->use_strftime ? "yes" : "no");
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Rotation file forced open: %12s\n", config->force_open ? "yes" : "no");
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Rotation verbose: %12s\n", config->verbose ? "yes" : "no");
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Rotation file name: %21s\n", config->szLogRoot);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Post-rotation prog: %21s\n", config->postrotate_prog);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek}
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek/*
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Check whether we need to rotate.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Possible reasons are:
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * - No log file open (ROTATE_NEW)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * - User forces us to rotate (ROTATE_FORCE)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * - Our log file size is already bigger than the
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * allowed maximum (ROTATE_SIZE)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * - The next log time interval expired (ROTATE_TIME)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * When size and time constraints are both given,
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek * it suffices that one of them is fulfilled.
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek */
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozekstatic void checkRotate(rotate_config_t *config, rotate_status_t *status)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek{
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (status->nLogFD == NULL) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->rotateReason = ROTATE_NEW;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else if (config->sRotation) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_finfo_t finfo;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_off_t current_size = -1;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (apr_file_info_get(&finfo, APR_FINFO_SIZE, status->nLogFD) == APR_SUCCESS) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek current_size = finfo.size;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (current_size > config->sRotation) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->rotateReason = ROTATE_SIZE;
fd8595874aa06c8057740001ec465ba76b4af142Jakub Hrozek }
fd8595874aa06c8057740001ec465ba76b4af142Jakub Hrozek else if (config->tRotation) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (get_now(config) >= status->tLogEnd) {
fd8595874aa06c8057740001ec465ba76b4af142Jakub Hrozek status->rotateReason = ROTATE_TIME;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek }
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek }
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek else if (config->tRotation) {
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek if (get_now(config) >= status->tLogEnd) {
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek status->rotateReason = ROTATE_TIME;
6ca87e797982061576885f944e2ccfaba9573897Stephen Gallagher }
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek }
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek else {
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek fprintf(stderr, "No rotation time or size specified\n");
6ca87e797982061576885f944e2ccfaba9573897Stephen Gallagher exit(2);
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek }
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek if (status->rotateReason != ROTATE_NONE && config->verbose) {
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek fprintf(stderr, "File rotation needed, reason: %s\n", ROTATE_REASONS[status->rotateReason]);
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek }
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek return;
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek}
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek/*
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek * Spawn a post-rotate process.
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek */
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozekstatic void post_rotate(apr_pool_t *pool, rotate_config_t *config, rotate_status_t *status)
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek{
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek apr_status_t rv;
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek char error[120];
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek apr_procattr_t *pattr;
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek const char *argv[4];
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek apr_proc_t proc;
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek /* Collect any zombies from a previous run, but don't wait. */
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek while (apr_proc_wait_all_procs(&proc, NULL, NULL, APR_NOWAIT, pool) == APR_CHILD_DONE)
9a3ba9ca00e73adc3fb17ce8afa532076768023bJakub Hrozek /* noop */;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if ((rv = apr_procattr_create(&pattr, pool)) != APR_SUCCESS) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "post_rotate: apr_procattr_create failed for '%s': %s\n",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config->postrotate_prog,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_strerror(rv, error, sizeof(error)));
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek rv = apr_procattr_error_check_set(pattr, 1);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (rv == APR_SUCCESS)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek rv = apr_procattr_cmdtype_set(pattr, APR_PROGRAM_ENV);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (rv != APR_SUCCESS) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "post_rotate: could not set up process attributes for '%s': %s\n",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config->postrotate_prog,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_strerror(rv, error, sizeof(error)));
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek argv[0] = config->postrotate_prog;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek argv[1] = status->filename;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (status->filenameprev[0]) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek argv[2] = status->filenameprev;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek argv[3] = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek argv[2] = NULL;
95cc3f4be93d3cb5bb28bb3787f0aace4edb3124Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->verbose)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Calling post-rotate program: %s\n", argv[0]);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek rv = apr_proc_create(&proc, argv[0], argv, NULL, pattr, pool);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (rv != APR_SUCCESS) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Could not spawn post-rotate process '%s': %s\n",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config->postrotate_prog,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_strerror(rv, error, sizeof(error)));
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek}
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek/*
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Open a new log file, and if successful
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * also close the old one.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek *
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * The timestamp for the calculation of the file
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * name of the new log file will be the actual millisecond
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * timestamp, except when a regular rotation based on a time
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * interval is configured and the previous interval
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * is over. Then the timestamp is the starting time
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * of the actual interval.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic void doRotate(rotate_config_t *config, rotate_status_t *status)
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek{
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int now = get_now(config);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int tLogStart;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_status_t rv;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->rotateReason = ROTATE_NONE;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->nLogFDprev = status->nLogFD;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->nLogFD = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->pfile_prev = status->pfile;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->tRotation) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek int tLogEnd;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek tLogStart = (now / config->tRotation) * config->tRotation;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek tLogEnd = tLogStart + config->tRotation;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek /*
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Check if rotation was forced and the last rotation
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * interval is not yet over. Use the value of now instead
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * of the time interval boundary for the file name then.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (tLogStart < status->tLogEnd) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek tLogStart = now;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->tLogEnd = tLogEnd;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek tLogStart = now;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_cpystrn(status->filenameprev, status->filename, MAX_PATH);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->use_strftime) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_time_t tNow = apr_time_from_sec(tLogStart);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_time_exp_t e;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_size_t rs;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_time_exp_gmt(&e, tNow);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_strftime(status->filename, &rs, sizeof(status->filename), config->szLogRoot, &e);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->truncate) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_snprintf(status->filename, sizeof(status->filename), "%s", config->szLogRoot);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_snprintf(status->filename, sizeof(status->filename), "%s.%010d", config->szLogRoot,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek tLogStart);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_pool_create(&status->pfile, status->pool);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->verbose) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Opening file %s\n", status->filename);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek rv = apr_file_open(&status->nLogFD, status->filename, APR_WRITE | APR_CREATE | APR_APPEND
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek | (config->truncate ? APR_TRUNCATE : 0), APR_OS_DEFAULT, status->pfile);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (rv != APR_SUCCESS) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek char error[120];
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_strerror(rv, error, sizeof error);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek /* Uh-oh. Failed to open the new log file. Try to clear
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * the previous log file, note the lost log entries,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * and keep on truckin'. */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (status->nLogFDprev == NULL) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Could not open log file '%s' (%s)\n", status->filename, error);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek exit(2);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_size_t nWrite;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->nLogFD = status->nLogFDprev;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_pool_destroy(status->pfile);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->pfile = status->pfile_prev;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek /* Try to keep this error message constant length
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * in case it occurs several times. */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_snprintf(status->errbuf, sizeof status->errbuf,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "Resetting log file due to error opening "
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek "new log file, %10d messages lost: %-25.25s\n",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->nMessCount, error);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek nWrite = strlen(status->errbuf);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_file_trunc(status->nLogFD, 0);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (apr_file_write(status->nLogFD, status->errbuf, &nWrite) != APR_SUCCESS) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Error writing to the file %s\n", status->filename);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek exit(2);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek /* If postrotate configured, run the post-rotate program: */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->postrotate_prog) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek post_rotate(status->pfile, config, status);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek closeFile(config, status->pfile_prev, status->nLogFDprev);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->nLogFDprev = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->pfile_prev = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->nMessCount = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->linkfile) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_file_remove(config->linkfile, status->pfile);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->verbose) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr,"Linking %s to %s\n", status->filename, config->linkfile);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek rv = apr_file_link(status->filename, config->linkfile);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (rv != APR_SUCCESS) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek char error[120];
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_strerror(rv, error, sizeof error);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek fprintf(stderr, "Error linking file %s to %s (%s)\n",
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status->filename, config->linkfile, error);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek exit(2);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek}
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek/*
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Get a size or time param from a string.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * Parameter 'last' indicates, whether the
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * argument is the last commadnline argument.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * UTC offset is only allowed as a last argument
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * in order to make is distinguishable from the
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek * rotation interval time.
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekstatic const char *get_time_or_size(rotate_config_t *config,
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek const char *arg, int last) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek char *ptr = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek /* Byte multiplier */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek unsigned int mult = 1;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if ((ptr = strchr(arg, 'B')) != NULL) { /* Found KB size */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek mult = 1;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else if ((ptr = strchr(arg, 'K')) != NULL) { /* Found KB size */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek mult = 1024;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else if ((ptr = strchr(arg, 'M')) != NULL) { /* Found MB size */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek mult = 1024 * 1024;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else if ((ptr = strchr(arg, 'G')) != NULL) { /* Found GB size */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek mult = 1024 * 1024 * 1024;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (ptr) { /* rotation based on file size */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->sRotation > 0) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return "Rotation size parameter allowed only once";
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (*(ptr+1) == '\0') {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config->sRotation = atoi(arg) * mult;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->sRotation == 0) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return "Invalid rotation size parameter";
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else if ((config->sRotation > 0 || config->tRotation > 0) && last) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek /* rotation based on elapsed time */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->use_localtime) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return "UTC offset parameter is not valid with -l";
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config->utc_offset = atoi(arg) * 60;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek else { /* rotation based on elapsed time */
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->tRotation > 0) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return "Rotation time parameter allowed only once";
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config->tRotation = atoi(arg);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek if (config->tRotation <= 0) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return "Invalid rotation time parameter";
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek }
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek return NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek}
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozekint main (int argc, const char * const argv[])
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek{
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek char buf[BUFSIZE];
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_size_t nRead, nWrite;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_file_t *f_stdin;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_file_t *f_stdout;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_getopt_t *opt;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_status_t rv;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek char c;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek const char *opt_arg;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek const char *err = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_app_initialize(&argc, &argv, NULL);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek atexit(apr_terminate);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.sRotation = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.tRotation = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.utc_offset = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.use_localtime = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.use_strftime = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.force_open = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.verbose = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.echo = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status.pool = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status.pfile = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status.pfile_prev = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status.nLogFD = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status.nLogFDprev = NULL;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status.tLogEnd = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status.rotateReason = ROTATE_NONE;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek status.nMessCount = 0;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_pool_create(&status.pool, NULL);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek apr_getopt_init(&opt, status.pool, argc, argv);
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek while ((rv = apr_getopt(opt, "lL:p:ftve", &c, &opt_arg)) == APR_SUCCESS) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek switch (c) {
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek case 'l':
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.use_localtime = 1;
fd8595874aa06c8057740001ec465ba76b4af142Jakub Hrozek break;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek case 'L':
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.linkfile = opt_arg;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek break;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek case 'p':
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek config.postrotate_prog = opt_arg;
f232789430a080384188d5da89b19d874cf17513Jakub Hrozek break;
case 'f':
config.force_open = 1;
break;
case 't':
config.truncate = 1;
break;
case 'v':
config.verbose = 1;
break;
case 'e':
config.echo = 1;
break;
}
}
if (rv != APR_EOF) {
usage(argv[0], NULL /* specific error message already issued */ );
}
/*
* After the initial flags we need 2 to 4 arguments,
* the file name, either the rotation interval time or size
* or both of them, and optionally the UTC offset.
*/
if ((argc - opt->ind < 2) || (argc - opt->ind > 4) ) {
usage(argv[0], "Incorrect number of arguments");
}
config.szLogRoot = argv[opt->ind++];
/* Read in the remaining flags, namely time, size and UTC offset. */
for(; opt->ind < argc; opt->ind++) {
if ((err = get_time_or_size(&config, argv[opt->ind],
opt->ind < argc - 1 ? 0 : 1)) != NULL) {
usage(argv[0], err);
}
}
config.use_strftime = (strchr(config.szLogRoot, '%') != NULL);
if (apr_file_open_stdin(&f_stdin, status.pool) != APR_SUCCESS) {
fprintf(stderr, "Unable to open stdin\n");
exit(1);
}
if (apr_file_open_stdout(&f_stdout, status.pool) != APR_SUCCESS) {
fprintf(stderr, "Unable to open stdout\n");
exit(1);
}
/*
* Write out result of config parsing if verbose is set.
*/
if (config.verbose) {
dumpConfig(&config);
}
/*
* Immediately open the logfile as we start, if we were forced
* to do so via '-f'.
*/
if (config.force_open) {
doRotate(&config, &status);
}
for (;;) {
nRead = sizeof(buf);
rv = apr_file_read(f_stdin, buf, &nRead);
if (rv != APR_SUCCESS) {
exit(3);
}
checkRotate(&config, &status);
if (status.rotateReason != ROTATE_NONE) {
doRotate(&config, &status);
}
nWrite = nRead;
rv = apr_file_write(status.nLogFD, buf, &nWrite);
if (rv == APR_SUCCESS && nWrite != nRead) {
/* buffer partially written, which for rotatelogs means we encountered
* an error such as out of space or quota or some other limit reached;
* try to write the rest so we get the real error code
*/
apr_size_t nWritten = nWrite;
nRead = nRead - nWritten;
nWrite = nRead;
rv = apr_file_write(status.nLogFD, buf + nWritten, &nWrite);
}
if (nWrite != nRead) {
char strerrbuf[120];
apr_off_t cur_offset;
cur_offset = 0;
if (apr_file_seek(status.nLogFD, APR_CUR, &cur_offset) != APR_SUCCESS) {
cur_offset = -1;
}
apr_strerror(rv, strerrbuf, sizeof strerrbuf);
status.nMessCount++;
apr_snprintf(status.errbuf, sizeof status.errbuf,
"Error %d writing to log file at offset %" APR_OFF_T_FMT ". "
"%10d messages lost (%s)\n",
rv, cur_offset, status.nMessCount, strerrbuf);
nWrite = strlen(status.errbuf);
apr_file_trunc(status.nLogFD, 0);
if (apr_file_write(status.nLogFD, status.errbuf, &nWrite) != APR_SUCCESS) {
fprintf(stderr, "Error writing to the file %s\n", status.filename);
exit(2);
}
}
else {
status.nMessCount++;
}
if (config.echo) {
if (apr_file_write_full(f_stdout, buf, nRead, &nWrite)) {
fprintf(stderr, "Unable to write to stdout\n");
exit(4);
}
}
}
/* Of course we never, but prevent compiler warnings */
return 0;
}