mod_log_config.c revision 11a7b0dff22d26770b532c174d1cf2e7b56ec244
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * The Apache Software License, Version 1.1
842ae4bd224140319ae7feec1872b93dfd491143fielding *
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
842ae4bd224140319ae7feec1872b93dfd491143fielding * reserved.
842ae4bd224140319ae7feec1872b93dfd491143fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Redistribution and use in source and binary forms, with or without
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * modification, are permitted provided that the following conditions
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * are met:
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 1. Redistributions of source code must retain the above copyright
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * notice, this list of conditions and the following disclaimer.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 2. Redistributions in binary form must reproduce the above copyright
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * notice, this list of conditions and the following disclaimer in
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the documentation and/or other materials provided with the
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh * distribution.
e8f95a682820a599fe41b22977010636be5c2717jim *
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh * 3. The end-user documentation included with the redistribution,
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh * if any, must include the following acknowledgment:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * "This product includes software developed by the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Apache Software Foundation (http://www.apache.org/)."
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * Alternately, this acknowledgment may appear in the software itself,
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * if and wherever such third-party acknowledgments normally appear.
1b21d7b3d97def358b2e923655edeb16613a1c31gstein *
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * 4. The names "Apache" and "Apache Software Foundation" must
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * not be used to endorse or promote products derived from this
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * software without prior written permission. For written
1b21d7b3d97def358b2e923655edeb16613a1c31gstein * permission, please contact apache@apache.org.
2d71630471d1c23f0137309e3c3957c633ecbfd6rbb *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 5. Products derived from this software may not be called "Apache",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * nor may "Apache" appear in their name, without prior written
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * permission of the Apache Software Foundation.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
51af95bb51b5084e883bad250b2afa2838e9ceebfielding * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
d4f1d9c1ff112a8ab9bee31f196973761329b236rbb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
7fae9cc4639013f3c04c085547256c68814aee8ftrawick * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
7fae9cc4639013f3c04c085547256c68814aee8ftrawick * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
7fae9cc4639013f3c04c085547256c68814aee8ftrawick * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
7fae9cc4639013f3c04c085547256c68814aee8ftrawick * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asf * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asf * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * SUCH DAMAGE.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * ====================================================================
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This software consists of voluntary contributions made by many
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * individuals on behalf of the Apache Software Foundation. For more
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * information on the Apache Software Foundation, please see
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * <http://www.apache.org/>.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Portions of this software are based upon public domain software
785be1b6298010956622771c870ab3cd8ca57a2faaron * originally written at the National Center for Supercomputing Applications,
785be1b6298010956622771c870ab3cd8ca57a2faaron * University of Illinois, Urbana-Champaign.
785be1b6298010956622771c870ab3cd8ca57a2faaron */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Modified by djm@va.pubnix.com:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If no TransferLog is given explicitly, decline to log.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This is module implements the TransferLog directive (same as the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * common log module), and additional directives, LogFormat and CustomLog.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
785be1b6298010956622771c870ab3cd8ca57a2faaron *
785be1b6298010956622771c870ab3cd8ca57a2faaron * Syntax:
785be1b6298010956622771c870ab3cd8ca57a2faaron *
785be1b6298010956622771c870ab3cd8ca57a2faaron * TransferLog fn Logs transfers to fn in standard log format, unless
785be1b6298010956622771c870ab3cd8ca57a2faaron * a custom format is set with LogFormat
785be1b6298010956622771c870ab3cd8ca57a2faaron * LogFormat format Set a log format from TransferLog files
7697b1b7376a532163c621e050b70c90dcb15d66covener * CustomLog fn format
7697b1b7376a532163c621e050b70c90dcb15d66covener * Log to file fn with format given by the format
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * argument
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
f4b96a996afbc46872f57ad1450e6ee1c8f13707jorton * CookieLog fn For backwards compatability with old Cookie
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * logging module - now deprecated.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * There can be any number of TransferLog and CustomLog
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * commands. Each request will be logged to _ALL_ the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * named files, in the appropriate format.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If no TransferLog or CustomLog directive appears in a VirtualHost,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the request will be logged to the log file(s) defined outside
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the virtual host section. If a TransferLog or CustomLog directive
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * appears in the VirtualHost section, the log files defined outside
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the VirtualHost will _not_ be used. This makes this module compatable
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * with the CLF and config log modules, where the use of TransferLog
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * inside the VirtualHost section overrides its use outside.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Examples:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * TransferLog logs/access_log
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * <VirtualHost>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * LogFormat "... custom format ..."
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * TransferLog log/virtual_only
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * CustomLog log/virtual_useragents "%t %{user-agent}i"
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier * </VirtualHost>
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier *
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier * This will log using CLF to access_log any requests handled by the
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier * main server, while any requests to the virtual host will be logged
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier * with the "... custom format..." to virtual_only _AND_ using
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier * the custom user-agent log to virtual_useragents.
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Note that the NCSA referer and user-agent logs are easily added with
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * CustomLog:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * CustomLog logs/referer "%{referer}i -> %U"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * CustomLog logs/agent "%{user-agent}i"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * RefererIgnore functionality can be obtained with conditional
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * logging (SetEnvIf and CustomLog ... env=!VAR).
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * But using this method allows much easier modification of the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * log format, e.g. to log hosts along with UA:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * CustomLog logs/referer "%{referer}i %U %h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * The argument to LogFormat and CustomLog is a string, which can include
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * literal characters copied into the log files, and '%' directives as
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * follows:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...B: bytes sent, excluding HTTP headers.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...b: bytes sent, excluding HTTP headers in CLF format, i.e. a '-'
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * when no bytes where sent (rather than a '0'.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...c: Status of the connection.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 'X' = connection aborted before the response completed.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * '+' = connection may be kept alive after the response is sent.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * '-' = connection will be closed after the response is sent.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...{FOOBAR}C: The contents of the HTTP cookie FOOBAR
45acd673a68181802b112e97e84fa3813ddd3ec1stoddard * %...{FOOBAR}e: The contents of the environment variable FOOBAR
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...f: filename
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...h: remote host
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...a: remote IP-address
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier * %...A: local IP-address
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...{Foobar}i: The contents of Foobar: header line(s) in the request
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * sent to the client.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...l: remote logname (from identd, if supplied)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...{Foobar}n: The contents of note "Foobar" from another module.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...{Foobar}o: The contents of Foobar: header line(s) in the reply.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...p: the port the request was served to
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...P: the process ID of the child that serviced the request.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...r: first line of request
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...s: status. For requests that got internally redirected, this
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * is status of the *original* request --- %...>s for the last.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * %...t: time, in common log format time format
e8f95a682820a599fe41b22977010636be5c2717jim * %...{format}t: The time, in the form given by format, which should
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * be in strftime(3) format.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...T: the time taken to serve the request, in seconds.
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick * %...D: the time taken to serve the request, in micro seconds.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...u: remote user (from auth; may be bogus if return status (%s) is 401)
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * %...U: the URL path requested.
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * %...v: the configured name of the server (i.e. which virtual host?)
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski * %...V: the server name according to the UseCanonicalName setting
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * %...m: the request method
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick * %...H: the request protocol
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * %...q: the query string prepended by "?", or empty if no query string
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick *
785be1b6298010956622771c870ab3cd8ca57a2faaron * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * indicate conditions for inclusion of the item (which will cause it
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * to be replaced with '-' if the condition is not met). Note that
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * there is no escaping performed on the strings from %r, %...i and
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * %...o; some with long memories may remember that I thought this was
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * a bad idea, once upon a time, and I'm still not comfortable with
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * it, but it is difficult to see how to "do the right thing" with all
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * of '%..i', unless we URL-escape everything and break with CLF.
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames *
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * The forms of condition are a list of HTTP status codes, which may
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * or may not be preceded by '!'. Thus, '%400,501{User-agent}i' logs
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * User-agent: on 400 errors and 501 errors (Bad Request, Not
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * Implemented) only; '%!200,304,302{Referer}i' logs Referer: on all
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * requests which did *not* return some sort of normal status.
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick *
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * The default LogFormat reproduces CLF; see below.
560f6ac786d611b858b2bad932713d9e971f0716trawick *
560f6ac786d611b858b2bad932713d9e971f0716trawick * The way this is supposed to work with virtual hosts is as follows:
560f6ac786d611b858b2bad932713d9e971f0716trawick * a virtual host can have its own LogFormat, or its own TransferLog.
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * If it doesn't have its own LogFormat, it inherits from the main
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * server. If it doesn't have its own TransferLog, it writes to the
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * same descriptor (meaning the same process for "| ...").
7bf77d70b6830636bc36e6b76a228c301be23ff7brianp *
7bf77d70b6830636bc36e6b76a228c301be23ff7brianp * --- rst */
7bf77d70b6830636bc36e6b76a228c301be23ff7brianp
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick#include "apr_strings.h"
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick#include "apr_lib.h"
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick#include "apr_hash.h"
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick#include "apr_optional.h"
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define APR_WANT_STRFUNC
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "apr_want.h"
7697b1b7376a532163c621e050b70c90dcb15d66covener
39b76a07959a0a332366c735a23894d9e8ed6872trawick#include "ap_config.h"
de00ec7378227d05be63ecd2053ebbb01b940023jorton#include "mod_log_config.h"
f3aa436e29aa30e29695a18b7f469dd66b39b7e4jorton#include "httpd.h"
de00ec7378227d05be63ecd2053ebbb01b940023jorton#include "http_config.h"
de00ec7378227d05be63ecd2053ebbb01b940023jorton#include "http_core.h" /* For REMOTE_NAME */
785be1b6298010956622771c870ab3cd8ca57a2faaron#include "http_log.h"
785be1b6298010956622771c870ab3cd8ca57a2faaron#include "http_protocol.h"
066877f1a045103acfdd376d48cdd473c33f409bdougm
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick#if APR_HAVE_UNISTD_H
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick#include <unistd.h>
f3aa436e29aa30e29695a18b7f469dd66b39b7e4jorton#endif
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid#ifdef HAVE_LIMITS_H
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid#include <limits.h>
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid#endif
74b39333600dee3260355ad3a06e36ef6c61c8f1dreid
97c78987224dcd037076d393aad1867c26b2c8cftrawick#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"
97c78987224dcd037076d393aad1867c26b2c8cftrawick
97c78987224dcd037076d393aad1867c26b2c8cftrawickmodule AP_MODULE_DECLARE_DATA log_config_module;
97c78987224dcd037076d393aad1867c26b2c8cftrawick
97c78987224dcd037076d393aad1867c26b2c8cftrawickstatic int xfer_flags = (APR_WRITE | APR_APPEND | APR_CREATE);
97c78987224dcd037076d393aad1867c26b2c8cftrawickstatic apr_fileperms_t xfer_perms = APR_OS_DEFAULT;
97c78987224dcd037076d393aad1867c26b2c8cftrawickstatic apr_hash_t *log_hash;
97c78987224dcd037076d393aad1867c26b2c8cftrawick
97c78987224dcd037076d393aad1867c26b2c8cftrawick/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
97c78987224dcd037076d393aad1867c26b2c8cftrawick * guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512
97c78987224dcd037076d393aad1867c26b2c8cftrawick * is guaranteed. So we'll just guess 512 in the event the system
97c78987224dcd037076d393aad1867c26b2c8cftrawick * doesn't have this. Now, for file writes there is actually no limit,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the entire write is atomic. Whether all systems implement this
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * correctly is another question entirely ... so we'll just use PIPE_BUF
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * because it's probably a good guess as to what is implemented correctly
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * everywhere.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
785be1b6298010956622771c870ab3cd8ca57a2faaron#ifdef PIPE_BUF
785be1b6298010956622771c870ab3cd8ca57a2faaron#define LOG_BUFSIZE PIPE_BUF
785be1b6298010956622771c870ab3cd8ca57a2faaron#else
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define LOG_BUFSIZE (512)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * multi_log_state is our per-(virtual)-server configuration. We store
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * an array of the logs we are going to use, each of type config_log_state.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If a default log format is given by LogFormat, store in default_format
785be1b6298010956622771c870ab3cd8ca57a2faaron * (backward compat. with mod_log_config). We also store for each virtual
785be1b6298010956622771c870ab3cd8ca57a2faaron * server a pointer to the logs specified for the main server, so that if this
785be1b6298010956622771c870ab3cd8ca57a2faaron * vhost has no logs defined, we can use the main server's logs instead.
785be1b6298010956622771c870ab3cd8ca57a2faaron *
785be1b6298010956622771c870ab3cd8ca57a2faaron * So, for the main server, config_logs contains a list of the log files
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * and server_config_logs in empty. For a vhost, server_config_logs
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * points to the same array as config_logs in the main server, and
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * config_logs points to the array of logs defined inside this vhost,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * which might be empty.
785be1b6298010956622771c870ab3cd8ca57a2faaron */
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faarontypedef struct {
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *default_format_string;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_array_header_t *default_format;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_array_header_t *config_logs;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_array_header_t *server_config_logs;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_table_t *formats;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding} multi_log_state;
c5d006b2861d49c61bcf79316163e30611c6fd08trawick
c5d006b2861d49c61bcf79316163e30611c6fd08trawick/*
c5d006b2861d49c61bcf79316163e30611c6fd08trawick * config_log_state holds the status of a single log file. fname might
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * be NULL, which means this module does no logging for this
7697b1b7376a532163c621e050b70c90dcb15d66covener * request. format might be NULL, in which case the default_format
7697b1b7376a532163c621e050b70c90dcb15d66covener * from the multi_log_state should be used, or if that is NULL as
7697b1b7376a532163c621e050b70c90dcb15d66covener * well, use the CLF. log_fd is NULL before the log file is opened and
7697b1b7376a532163c621e050b70c90dcb15d66covener * set to a valid fd after it is opened.
7697b1b7376a532163c621e050b70c90dcb15d66covener */
7697b1b7376a532163c621e050b70c90dcb15d66covener
7697b1b7376a532163c621e050b70c90dcb15d66covenertypedef struct {
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier const char *fname;
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier const char *format_string;
7697b1b7376a532163c621e050b70c90dcb15d66covener apr_array_header_t *format;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_t *log_fd;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *condition_var;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#ifdef BUFFERED_LOGS
f4b96a996afbc46872f57ad1450e6ee1c8f13707jorton apr_size_t outcnt;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char outbuf[LOG_BUFSIZE];
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding} config_log_state;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Format items...
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Note that many of these could have ap_sprintfs replaced with static buffers.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingtypedef struct {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_log_handler_fn_t *func;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *arg;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int condition_sense;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int want_orig;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_array_header_t *conditions;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding} log_format_item;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *format_integer(apr_pool_t *p, int i)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_itoa(p, i);
785be1b6298010956622771c870ab3cd8ca57a2faaron}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic char *pfmt(apr_pool_t *p, int i)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron if (i <= 0) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return "-";
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return format_integer(p, i);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic const char *constant_item(request_rec *dummy, char *stuff)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return stuff;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic const char *log_remote_host(request_rec *r, char *a)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron return ap_get_remote_host(r->connection, r->per_dir_config,
785be1b6298010956622771c870ab3cd8ca57a2faaron REMOTE_NAME, NULL);
785be1b6298010956622771c870ab3cd8ca57a2faaron}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic const char *log_remote_address(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm return r->connection->remote_ip;
785be1b6298010956622771c870ab3cd8ca57a2faaron}
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_local_address(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return r->connection->local_ip;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_remote_logname(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return ap_get_remote_logname(r);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_remote_user(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *rvalue = r->user;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
a7ed9c525f9460187f327cea953bf90ecf1bdc51gstein if (rvalue == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rvalue = "-";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (strlen(rvalue) == 0) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rvalue = "\"\"";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
a7ed9c525f9460187f327cea953bf90ecf1bdc51gstein return rvalue;
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick}
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_request_line(request_rec *r, char *a)
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick{
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick /* NOTE: If the original request contained a password, we
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick * re-write the request line here to contain XXXXXX instead:
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick * (note the truncation before the protocol string for HTTP/0.9 requests)
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick * (note also that r->the_request contains the unmodified request)
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick */
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick return (r->parsed_uri.password) ? apr_pstrcat(r->pool, r->method, " ",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_uri_unparse_components(r->pool, &r->parsed_uri, 0),
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm r->assbackwards ? NULL : " ", r->protocol, NULL)
785be1b6298010956622771c870ab3cd8ca57a2faaron : r->the_request;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_request_file(request_rec *r, char *a)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return r->filename;
7697b1b7376a532163c621e050b70c90dcb15d66covener}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_request_uri(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return r->uri;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_request_method(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return r->method;
785be1b6298010956622771c870ab3cd8ca57a2faaron}
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic const char *log_request_protocol(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return r->protocol;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic const char *log_request_query(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (r->args != NULL) ? apr_pstrcat(r->pool, "?", r->args, NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding : "";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_status(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return pfmt(r->pool, r->status);
a7ed9c525f9460187f327cea953bf90ecf1bdc51gstein}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *clf_log_bytes_sent(request_rec *r, char *a)
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener{
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener if (!r->sent_bodyct) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return "-";
f4b96a996afbc46872f57ad1450e6ee1c8f13707jorton }
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_off_t_toa(r->pool, r->bytes_sent);
785be1b6298010956622771c870ab3cd8ca57a2faaron }
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick}
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covenerstatic const char *log_bytes_sent(request_rec *r, char *a)
8fd7c5046d164fb0959222497e5925dfc6a52ff3trawick{
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick if (!r->sent_bodyct) {
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick return "0";
e8f95a682820a599fe41b22977010636be5c2717jim }
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener else {
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener return apr_psprintf(r->pool, "%ld", r->bytes_sent);
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener }
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener}
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_header_in(request_rec *r, char *a)
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_table_get(r->headers_in, a);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
8f8ec0957334f50b7ac11359f90490ee467258eedreid
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_header_out(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener const char *cp = apr_table_get(r->headers_out, a);
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener if (!strcasecmp(a, "Content-type") && r->content_type) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cp = ap_field_noparam(r->pool, r->content_type);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (cp) {
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener return cp;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
785be1b6298010956622771c870ab3cd8ca57a2faaron return apr_table_get(r->err_headers_out, a);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covenerstatic const char *log_note(request_rec *r, char *a)
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener{
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covener return apr_table_get(r->notes, a);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
27c5ebb7d411a214f5b6b55a881086ce086d3dd3covenerstatic const char *log_env_var(request_rec *r, char *a)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_table_get(r->subprocess_env, a);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_cookie(request_rec *r, char *a)
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *cookies;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick const char *start_cookie;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
39b76a07959a0a332366c735a23894d9e8ed6872trawick if ((cookies = apr_table_get(r->headers_in, "Cookie"))) {
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick if ((start_cookie = ap_strstr_c(cookies,a))) {
785be1b6298010956622771c870ab3cd8ca57a2faaron char *cookie, *end_cookie;
785be1b6298010956622771c870ab3cd8ca57a2faaron start_cookie += strlen(a) + 1; /* cookie_name + '=' */
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf cookie = apr_pstrdup(r->pool, start_cookie);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf /* kill everything in cookie after ';' */
785be1b6298010956622771c870ab3cd8ca57a2faaron end_cookie = strchr(cookie, ';');
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if (end_cookie) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf *end_cookie = '\0';
785be1b6298010956622771c870ab3cd8ca57a2faaron }
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf return cookie;
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf }
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron return NULL;
785be1b6298010956622771c870ab3cd8ca57a2faaron}
785be1b6298010956622771c870ab3cd8ca57a2faaron
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanfstatic const char *log_request_time(request_rec *r, char *a)
066877f1a045103acfdd376d48cdd473c33f409bdougm{
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_exploded_time_t xt;
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_size_t retcode;
785be1b6298010956622771c870ab3cd8ca57a2faaron char tstr[MAX_STRING_LEN];
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
785be1b6298010956622771c870ab3cd8ca57a2faaron /*
785be1b6298010956622771c870ab3cd8ca57a2faaron hi. i think getting the time again at the end of the request
785be1b6298010956622771c870ab3cd8ca57a2faaron just for logging is dumb. i know it's "required" for CLF.
785be1b6298010956622771c870ab3cd8ca57a2faaron folks writing log parsing tools don't realise that out of order
785be1b6298010956622771c870ab3cd8ca57a2faaron times have always been possible (consider what happens if one
785be1b6298010956622771c870ab3cd8ca57a2faaron process calculates the time to log, but then there's a context
785be1b6298010956622771c870ab3cd8ca57a2faaron switch before it writes and before that process is run again the
785be1b6298010956622771c870ab3cd8ca57a2faaron log rotation occurs) and they should just fix their tools rather
785be1b6298010956622771c870ab3cd8ca57a2faaron than force the server to pay extra cpu cycles. if you've got
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier a problem with this, you can set the define. -djg
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier */
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier#ifdef I_INSIST_ON_EXTRA_CYCLES_FOR_CLF_COMPLIANCE
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier apr_explode_localtime(&xt, apr_time_now());
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier#else
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier apr_explode_localtime(&xt, r->request_time);
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier#endif
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier if (a && *a) { /* Custom format */
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier apr_strftime(tstr, &retcode, MAX_STRING_LEN, a, &xt);
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier }
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier else { /* CLF format */
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier char sign;
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier int timz;
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier timz = xt.tm_gmtoff;
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier if (timz < 0) {
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier timz = -timz;
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier sign = '-';
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier }
b6d9e9d6421b9cebfc74f9c1a870b8b85473f1c1poirier else {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf sign = '+';
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf }
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf apr_snprintf(tstr, sizeof(tstr), "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]",
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf xt.tm_mday, apr_month_snames[xt.tm_mon], xt.tm_year+1900,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf xt.tm_hour, xt.tm_min, xt.tm_sec,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf sign, timz / (60*60), timz % (60*60));
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf }
066877f1a045103acfdd376d48cdd473c33f409bdougm
7697b1b7376a532163c621e050b70c90dcb15d66covener return apr_pstrdup(r->pool, tstr);
7697b1b7376a532163c621e050b70c90dcb15d66covener}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic const char *log_request_duration(request_rec *r, char *a)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron return apr_psprintf(r->pool, "%qd", (apr_time_now() - r->request_time)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding / APR_USEC_PER_SEC);
7697b1b7376a532163c621e050b70c90dcb15d66covener}
7697b1b7376a532163c621e050b70c90dcb15d66covener
7697b1b7376a532163c621e050b70c90dcb15d66covenerstatic const char *log_request_duration_microseconds(request_rec *r, char *a)
7697b1b7376a532163c621e050b70c90dcb15d66covener{
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf return apr_psprintf(r->pool, "%qd", (apr_time_now() - r->request_time));
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf}
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf
7697b1b7376a532163c621e050b70c90dcb15d66covener/* These next two routines use the canonical name:port so that log
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf * parsers don't need to duplicate all the vhost parsing crud.
7697b1b7376a532163c621e050b70c90dcb15d66covener */
7697b1b7376a532163c621e050b70c90dcb15d66covenerstatic const char *log_virtual_host(request_rec *r, char *a)
7697b1b7376a532163c621e050b70c90dcb15d66covener{
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf return r->server->server_hostname;
7697b1b7376a532163c621e050b70c90dcb15d66covener}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic const char *log_server_port(request_rec *r, char *a)
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf{
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf return apr_psprintf(r->pool, "%u",
7697b1b7376a532163c621e050b70c90dcb15d66covener r->server->port ? r->server->port : ap_default_port(r));
7697b1b7376a532163c621e050b70c90dcb15d66covener}
7697b1b7376a532163c621e050b70c90dcb15d66covener
7697b1b7376a532163c621e050b70c90dcb15d66covener/* This respects the setting of UseCanonicalName so that
7697b1b7376a532163c621e050b70c90dcb15d66covener * the dynamic mass virtual hosting trick works better.
7697b1b7376a532163c621e050b70c90dcb15d66covener */
7697b1b7376a532163c621e050b70c90dcb15d66covenerstatic const char *log_server_name(request_rec *r, char *a)
7697b1b7376a532163c621e050b70c90dcb15d66covener{
7697b1b7376a532163c621e050b70c90dcb15d66covener return ap_get_server_name(r);
7697b1b7376a532163c621e050b70c90dcb15d66covener}
7697b1b7376a532163c621e050b70c90dcb15d66covener
7697b1b7376a532163c621e050b70c90dcb15d66covenerstatic const char *log_child_pid(request_rec *r, char *a)
7697b1b7376a532163c621e050b70c90dcb15d66covener{
7697b1b7376a532163c621e050b70c90dcb15d66covener return apr_psprintf(r->pool, "%ld", (long) getpid());
7697b1b7376a532163c621e050b70c90dcb15d66covener}
7697b1b7376a532163c621e050b70c90dcb15d66covener
7697b1b7376a532163c621e050b70c90dcb15d66covenerstatic const char *log_connection_status(request_rec *r, char *a)
7697b1b7376a532163c621e050b70c90dcb15d66covener{
7697b1b7376a532163c621e050b70c90dcb15d66covener if (r->connection->aborted)
7697b1b7376a532163c621e050b70c90dcb15d66covener return "X";
7697b1b7376a532163c621e050b70c90dcb15d66covener
7697b1b7376a532163c621e050b70c90dcb15d66covener if (r->connection->keepalive &&
7697b1b7376a532163c621e050b70c90dcb15d66covener (!r->server->keep_alive_max ||
7697b1b7376a532163c621e050b70c90dcb15d66covener (r->server->keep_alive_max - r->connection->keepalives) > 0)) {
7697b1b7376a532163c621e050b70c90dcb15d66covener return "+";
7697b1b7376a532163c621e050b70c90dcb15d66covener }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return "-";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
ebc18d48bea83ee5ed7a1b4e30007e5192539829wrowe/*****************************************************************
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Parsing the log format string
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic char *parse_log_misc_string(apr_pool_t *p, log_format_item *it,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char **sa)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *s;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *d;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding it->func = constant_item;
785be1b6298010956622771c870ab3cd8ca57a2faaron it->conditions = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding s = *sa;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (*s && *s != '%') {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding s++;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * This might allocate a few chars extra if there's a backslash
f4b96a996afbc46872f57ad1450e6ee1c8f13707jorton * escape in the format string.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding it->arg = apr_palloc(p, s - *sa + 1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding d = it->arg;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding s = *sa;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (*s && *s != '%') {
785be1b6298010956622771c870ab3cd8ca57a2faaron if (*s != '\\') {
785be1b6298010956622771c870ab3cd8ca57a2faaron *d++ = *s++;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
900127764fb985c340ee4979cac97146a330c694trawick else {
785be1b6298010956622771c870ab3cd8ca57a2faaron s++;
7697b1b7376a532163c621e050b70c90dcb15d66covener switch (*s) {
785be1b6298010956622771c870ab3cd8ca57a2faaron case '\\':
7697b1b7376a532163c621e050b70c90dcb15d66covener *d++ = '\\';
7697b1b7376a532163c621e050b70c90dcb15d66covener s++;
7697b1b7376a532163c621e050b70c90dcb15d66covener break;
7697b1b7376a532163c621e050b70c90dcb15d66covener case 'r':
7697b1b7376a532163c621e050b70c90dcb15d66covener *d++ = '\r';
785be1b6298010956622771c870ab3cd8ca57a2faaron s++;
785be1b6298010956622771c870ab3cd8ca57a2faaron break;
785be1b6298010956622771c870ab3cd8ca57a2faaron case 'n':
785be1b6298010956622771c870ab3cd8ca57a2faaron *d++ = '\n';
785be1b6298010956622771c870ab3cd8ca57a2faaron s++;
785be1b6298010956622771c870ab3cd8ca57a2faaron break;
785be1b6298010956622771c870ab3cd8ca57a2faaron case 't':
785be1b6298010956622771c870ab3cd8ca57a2faaron *d++ = '\t';
785be1b6298010956622771c870ab3cd8ca57a2faaron s++;
785be1b6298010956622771c870ab3cd8ca57a2faaron break;
7697b1b7376a532163c621e050b70c90dcb15d66covener default:
7697b1b7376a532163c621e050b70c90dcb15d66covener /* copy verbatim */
7697b1b7376a532163c621e050b70c90dcb15d66covener *d++ = '\\';
7697b1b7376a532163c621e050b70c90dcb15d66covener /*
7697b1b7376a532163c621e050b70c90dcb15d66covener * Allow the loop to deal with this *s in the normal
785be1b6298010956622771c870ab3cd8ca57a2faaron * fashion so that it handles end of string etc.
785be1b6298010956622771c870ab3cd8ca57a2faaron * properly.
785be1b6298010956622771c870ab3cd8ca57a2faaron */
785be1b6298010956622771c870ab3cd8ca57a2faaron break;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron }
7697b1b7376a532163c621e050b70c90dcb15d66covener }
785be1b6298010956622771c870ab3cd8ca57a2faaron *d = '\0';
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron *sa = s;
785be1b6298010956622771c870ab3cd8ca57a2faaron return NULL;
785be1b6298010956622771c870ab3cd8ca57a2faaron}
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic char *parse_log_item(apr_pool_t *p, log_format_item *it, const char **sa)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *s = *sa;
785be1b6298010956622771c870ab3cd8ca57a2faaron ap_log_handler *handler;
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron if (*s != '%') {
785be1b6298010956622771c870ab3cd8ca57a2faaron return parse_log_misc_string(p, it, sa);
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron ++s;
785be1b6298010956622771c870ab3cd8ca57a2faaron it->condition_sense = 0;
785be1b6298010956622771c870ab3cd8ca57a2faaron it->conditions = NULL;
785be1b6298010956622771c870ab3cd8ca57a2faaron it->want_orig = -1;
785be1b6298010956622771c870ab3cd8ca57a2faaron it->arg = ""; /* For safety's sake... */
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (*s) {
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick int i;
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick switch (*s) {
785be1b6298010956622771c870ab3cd8ca57a2faaron case '!':
785be1b6298010956622771c870ab3cd8ca57a2faaron ++s;
785be1b6298010956622771c870ab3cd8ca57a2faaron it->condition_sense = !it->condition_sense;
785be1b6298010956622771c870ab3cd8ca57a2faaron break;
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick case '<':
066877f1a045103acfdd376d48cdd473c33f409bdougm ++s;
785be1b6298010956622771c870ab3cd8ca57a2faaron it->want_orig = 1;
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick break;
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick case '>':
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick ++s;
785be1b6298010956622771c870ab3cd8ca57a2faaron it->want_orig = 0;
785be1b6298010956622771c870ab3cd8ca57a2faaron break;
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron case ',':
785be1b6298010956622771c870ab3cd8ca57a2faaron ++s;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case '{':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ++s;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding it->arg = ap_getword(p, &s, '}');
bbbf8f0e622ad5a37ccf70f35660fc755575278arbb break;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
2659802f083b95856f571b49e4ec087838b53039rederpj case '0':
785be1b6298010956622771c870ab3cd8ca57a2faaron case '1':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case '2':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case '3':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case '4':
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier case '5':
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier case '6':
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier case '7':
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier case '8':
e08076ca56e6cb68b30846b9e9339061058aae6dpoirier case '9':
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding i = *s - '0';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (apr_isdigit(*++s)) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding i = i * 10 + (*s) - '0';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (!it->conditions) {
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf it->conditions = apr_array_make(p, 4, sizeof(int));
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf }
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf *(int *) apr_array_push(it->conditions) = i;
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf break;
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf default:
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf handler = (ap_log_handler *)apr_hash_get(log_hash, s++, 1);
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf if (!handler) {
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf char dummy[2];
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf dummy[0] = s[-1];
91583d2e9c0550f539ea6f4dedf051979ad1ad88fanf dummy[1] = '\0';
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return apr_pstrcat(p, "Unrecognized LogFormat directive %",
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding dummy, NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick it->func = handler->func;
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf if (it->want_orig == -1) {
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick it->want_orig = handler->want_orig_default;
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick }
4f133508c93204c06e1acba9774ff184e5812606niq *sa = s;
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf return NULL;
9c518951a46c7a12e20876827bb2e84ef87d3c11jerenkrantz }
9c518951a46c7a12e20876827bb2e84ef87d3c11jerenkrantz }
9c518951a46c7a12e20876827bb2e84ef87d3c11jerenkrantz
9c518951a46c7a12e20876827bb2e84ef87d3c11jerenkrantz return "Ran off end of LogFormat parsing args to some directive";
9c518951a46c7a12e20876827bb2e84ef87d3c11jerenkrantz}
4f133508c93204c06e1acba9774ff184e5812606niq
4f133508c93204c06e1acba9774ff184e5812606niqstatic apr_array_header_t *parse_log_string(apr_pool_t *p, const char *s, const char **err)
4f133508c93204c06e1acba9774ff184e5812606niq{
4f133508c93204c06e1acba9774ff184e5812606niq apr_array_header_t *a = apr_array_make(p, 30, sizeof(log_format_item));
4f133508c93204c06e1acba9774ff184e5812606niq char *res;
4f133508c93204c06e1acba9774ff184e5812606niq
4f133508c93204c06e1acba9774ff184e5812606niq while (*s) {
4f133508c93204c06e1acba9774ff184e5812606niq if ((res = parse_log_item(p, (log_format_item *) apr_array_push(a), &s))) {
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick *err = res;
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick return NULL;
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
4f133508c93204c06e1acba9774ff184e5812606niq s = APR_EOL_STR;
644be6f54749d2d9950d2c4d2ac448f7af016d26martin parse_log_item(p, (log_format_item *) apr_array_push(a), &s);
43c3e6a4b559b76b750c245ee95e2782c15b4296jim return a;
644be6f54749d2d9950d2c4d2ac448f7af016d26martin}
43c3e6a4b559b76b750c245ee95e2782c15b4296jim
43c3e6a4b559b76b750c245ee95e2782c15b4296jim/*****************************************************************
644be6f54749d2d9950d2c4d2ac448f7af016d26martin *
43c3e6a4b559b76b750c245ee95e2782c15b4296jim * Actually logging.
644be6f54749d2d9950d2c4d2ac448f7af016d26martin */
0db1b9810f06c0e3c537e0e0dfbc30160c308526trawick
e8f95a682820a599fe41b22977010636be5c2717jimstatic const char *process_item(request_rec *r, request_rec *orig,
e8f95a682820a599fe41b22977010636be5c2717jim log_format_item *item)
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick{
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick const char *cp;
71715c646d5231de578431f8961e711764b899d3fanf
3c8b3749225668f06abbb2b023a833a2cef46931brianp /* First, see if we need to process this thing at all... */
3c8b3749225668f06abbb2b023a833a2cef46931brianp
3c8b3749225668f06abbb2b023a833a2cef46931brianp if (item->conditions && item->conditions->nelts != 0) {
3c8b3749225668f06abbb2b023a833a2cef46931brianp int i;
ccad4fdc6c75a352157a413bd3bbaf4d0c8a6f72brianp int *conds = (int *) item->conditions->elts;
785be1b6298010956622771c870ab3cd8ca57a2faaron int in_list = 0;
ccad4fdc6c75a352157a413bd3bbaf4d0c8a6f72brianp
785be1b6298010956622771c870ab3cd8ca57a2faaron for (i = 0; i < item->conditions->nelts; ++i) {
3c8b3749225668f06abbb2b023a833a2cef46931brianp if (r->status == conds[i]) {
3c8b3749225668f06abbb2b023a833a2cef46931brianp in_list = 1;
3c8b3749225668f06abbb2b023a833a2cef46931brianp break;
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick if ((item->condition_sense && in_list)
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick || (!item->condition_sense && !in_list)) {
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick return "-";
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick }
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick }
3c48210f662a2ab8ed90708989e04c09aae33cb2trawick
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* We do. Do it... */
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf cp = (*item->func) (item->want_orig ? orig : r, item->arg);
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf return cp ? cp : "-";
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanf}
2d399cd7535887fceaa9f8f116eb98ce68ddd602trawick
785be1b6298010956622771c870ab3cd8ca57a2faaron#ifdef BUFFERED_LOGS
3926b3b7716683a1241c1ff6f8dd2f9c5073665afanfstatic void flush_log(config_log_state *cls)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (cls->outcnt && cls->log_fd != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_write(cls->log_fd, cls->outbuf, &cls->outcnt);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cls->outcnt = 0;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic int config_log_transaction(request_rec *r, config_log_state *cls,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_array_header_t *default_format)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
785be1b6298010956622771c870ab3cd8ca57a2faaron log_format_item *items;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char *str, *s;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char **strs;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int *strl;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding request_rec *orig;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int i;
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_size_t len = 0;
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_array_header_t *format;
785be1b6298010956622771c870ab3cd8ca57a2faaron char *envar;
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron if (cls->fname == NULL) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return DECLINED;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /*
785be1b6298010956622771c870ab3cd8ca57a2faaron * See if we've got any conditional envariable-controlled logging decisions
785be1b6298010956622771c870ab3cd8ca57a2faaron * to make.
785be1b6298010956622771c870ab3cd8ca57a2faaron */
785be1b6298010956622771c870ab3cd8ca57a2faaron if (cls->condition_var != NULL) {
785be1b6298010956622771c870ab3cd8ca57a2faaron envar = cls->condition_var;
785be1b6298010956622771c870ab3cd8ca57a2faaron if (*envar != '!') {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (apr_table_get(r->subprocess_env, envar) == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return DECLINED;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (apr_table_get(r->subprocess_env, &envar[1]) != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return DECLINED;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding format = cls->format ? cls->format : default_format;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
785be1b6298010956622771c870ab3cd8ca57a2faaron strs = apr_palloc(r->pool, sizeof(char *) * (format->nelts));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding strl = apr_palloc(r->pool, sizeof(int) * (format->nelts));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding items = (log_format_item *) format->elts;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding orig = r;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (orig->prev) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding orig = orig->prev;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (r->next) {
e8f95a682820a599fe41b22977010636be5c2717jim r = r->next;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0; i < format->nelts; ++i) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding strs[i] = process_item(r, orig, &items[i]);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0; i < format->nelts; ++i) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding len += strl[i] = strlen(strs[i]);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#ifdef BUFFERED_LOGS
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (len + cls->outcnt > LOG_BUFSIZE) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding flush_log(cls);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
785be1b6298010956622771c870ab3cd8ca57a2faaron if (len >= LOG_BUFSIZE) {
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_size_t w;
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron str = apr_palloc(r->pool, len + 1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0, s = str; i < format->nelts; ++i) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding memcpy(s, strs[i], strl[i]);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding s += strl[i];
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding w = len;
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_file_write(cls->log_fd, str, &w);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0, s = &cls->outbuf[cls->outcnt]; i < format->nelts; ++i) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding memcpy(s, strs[i], strl[i]);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding s += strl[i];
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cls->outcnt += len;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#else
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding str = apr_palloc(r->pool, len + 1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0, s = str; i < format->nelts; ++i) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding memcpy(s, strs[i], strl[i]);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding s += strl[i];
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_file_write(cls->log_fd, str, &len);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return OK;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
dad234382d8424e1c5a30af2838e172aec9d6d1bdreidstatic int multi_log_transaction(request_rec *r)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding multi_log_state *mls = ap_get_module_config(r->server->module_config,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding &log_config_module);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding config_log_state *clsarray;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int i;
e6cc28a5eb3371ba0c38e941855e71ff0054f50erbb
c1b808d160bfb5c849263be8d4acff600853a328trawick /*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Log this transaction..
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (mls->config_logs->nelts) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding clsarray = (config_log_state *) mls->config_logs->elts;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0; i < mls->config_logs->nelts; ++i) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding config_log_state *cls = &clsarray[i];
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding config_log_transaction(r, cls, mls->default_format);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else if (mls->server_config_logs) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding clsarray = (config_log_state *) mls->server_config_logs->elts;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding for (i = 0; i < mls->server_config_logs->nelts; ++i) {
785be1b6298010956622771c870ab3cd8ca57a2faaron config_log_state *cls = &clsarray[i];
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron config_log_transaction(r, cls, mls->default_format);
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron return OK;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*****************************************************************
785be1b6298010956622771c870ab3cd8ca57a2faaron *
785be1b6298010956622771c870ab3cd8ca57a2faaron * Module glue...
785be1b6298010956622771c870ab3cd8ca57a2faaron */
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronstatic void *make_config_log_state(apr_pool_t *p, server_rec *s)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron multi_log_state *mls;
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron mls = (multi_log_state *) apr_palloc(p, sizeof(multi_log_state));
785be1b6298010956622771c870ab3cd8ca57a2faaron mls->config_logs = apr_array_make(p, 1, sizeof(config_log_state));
785be1b6298010956622771c870ab3cd8ca57a2faaron mls->default_format_string = NULL;
785be1b6298010956622771c870ab3cd8ca57a2faaron mls->default_format = NULL;
785be1b6298010956622771c870ab3cd8ca57a2faaron mls->server_config_logs = NULL;
785be1b6298010956622771c870ab3cd8ca57a2faaron mls->formats = apr_table_make(p, 4);
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_table_setn(mls->formats, "CLF", DEFAULT_LOG_FORMAT);
785be1b6298010956622771c870ab3cd8ca57a2faaron
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return mls;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Use the merger to simply add a pointer from the vhost log state
51af95bb51b5084e883bad250b2afa2838e9ceebfielding * to the log of logs specified for the non-vhost configuration. Make sure
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * vhosts inherit any globally-defined format names.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void *merge_config_log_state(apr_pool_t *p, void *basev, void *addv)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding multi_log_state *base = (multi_log_state *) basev;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding multi_log_state *add = (multi_log_state *) addv;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
dad234382d8424e1c5a30af2838e172aec9d6d1bdreid add->server_config_logs = base->config_logs;
382fa07a63096c4a1aabfed36433ea5ac9c40ad0trawick if (!add->default_format) {
c1b808d160bfb5c849263be8d4acff600853a328trawick add->default_format_string = base->default_format_string;
e6cc28a5eb3371ba0c38e941855e71ff0054f50erbb add->default_format = base->default_format;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding add->formats = apr_table_overlay(p, base->formats, add->formats);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return add;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Set the default logfile format, or define a nickname for a format string.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *log_format(cmd_parms *cmd, void *dummy, const char *fmt,
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *name)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *err_string = NULL;
785be1b6298010956622771c870ab3cd8ca57a2faaron multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
785be1b6298010956622771c870ab3cd8ca57a2faaron &log_config_module);
785be1b6298010956622771c870ab3cd8ca57a2faaron
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If we were given two arguments, the second is a name to be given to the
785be1b6298010956622771c870ab3cd8ca57a2faaron * format. This syntax just defines the nickname - it doesn't actually
785be1b6298010956622771c870ab3cd8ca57a2faaron * make the format the default.
785be1b6298010956622771c870ab3cd8ca57a2faaron */
785be1b6298010956622771c870ab3cd8ca57a2faaron if (name != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding parse_log_string(cmd->pool, fmt, &err_string);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (err_string == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_table_setn(mls->formats, name, fmt);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
51af95bb51b5084e883bad250b2afa2838e9ceebfielding else {
785be1b6298010956622771c870ab3cd8ca57a2faaron mls->default_format_string = fmt;
785be1b6298010956622771c870ab3cd8ca57a2faaron mls->default_format = parse_log_string(cmd->pool, fmt, &err_string);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return err_string;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
45acd673a68181802b112e97e84fa3813ddd3ec1stoddard
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic const char *add_custom_log(cmd_parms *cmd, void *dummy, const char *fn,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *fmt, const char *envclause)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm{
785be1b6298010956622771c870ab3cd8ca57a2faaron const char *err_string = NULL;
785be1b6298010956622771c870ab3cd8ca57a2faaron multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
785be1b6298010956622771c870ab3cd8ca57a2faaron &log_config_module);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding config_log_state *cls;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cls = (config_log_state *) apr_array_push(mls->config_logs);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cls->condition_var = NULL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (envclause != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strncasecmp(envclause, "env=", 4) != 0) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return "error in condition clause";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((envclause[4] == '\0')
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding || ((envclause[4] == '!') && (envclause[5] == '\0'))) {
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna return "missing environment variable name";
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna }
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna cls->condition_var = apr_pstrdup(cmd->pool, &envclause[4]);
e8f95a682820a599fe41b22977010636be5c2717jim }
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna cls->fname = fn;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna cls->format_string = fmt;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna if (fmt == NULL) {
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna cls->format = NULL;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna }
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna else {
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna cls->format = parse_log_string(cmd->pool, fmt, &err_string);
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna }
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna cls->log_fd = NULL;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna return err_string;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna}
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquernastatic const char *set_transfer_log(cmd_parms *cmd, void *dummy,
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna const char *fn)
e8f95a682820a599fe41b22977010636be5c2717jim{
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna return add_custom_log(cmd, dummy, fn, NULL, NULL);
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna}
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquernastatic const char *set_cookie_log(cmd_parms *cmd, void *dummy, const char *fn)
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna{
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t", NULL);
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna}
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquernastatic const command_rec config_log_cmds[] =
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna{
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquernaAP_INIT_TAKE23("CustomLog", add_custom_log, NULL, RSRC_CONF,
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna "a file name, a custom log format string or format name, "
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna "and an optional \"env=\" clause (see docs)"),
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquernaAP_INIT_TAKE1("TransferLog", set_transfer_log, NULL, RSRC_CONF,
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna "the filename of the access log"),
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquernaAP_INIT_TAKE12("LogFormat", log_format, NULL, RSRC_CONF,
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna "a log format string (see docs) and an optional format name"),
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquernaAP_INIT_TAKE1("CookieLog", set_cookie_log, NULL, RSRC_CONF,
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna "the filename of the cookie log"),
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna {NULL}
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna};
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquernastatic config_log_state *open_config_log(server_rec *s, apr_pool_t *p,
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna config_log_state *cls,
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna apr_array_header_t *default_format)
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna{
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna apr_status_t status;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna void *data;
20f1b1a67eef5ab0f3295608c89964a7dca4fdd1pquerna const char *userdata_key = "open_config_log";
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Skip opening the log the first time through. It's really
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * good to avoid starting the piped log process during preflight.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
45acd673a68181802b112e97e84fa3813ddd3ec1stoddard apr_pool_userdata_get(&data, userdata_key, s->process->pool);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (!data) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_pool_userdata_set((const void *)1, userdata_key,
8f8ec0957334f50b7ac11359f90490ee467258eedreid apr_pool_cleanup_null, s->process->pool);
382fa07a63096c4a1aabfed36433ea5ac9c40ad0trawick return cls;
f4b96a996afbc46872f57ad1450e6ee1c8f13707jorton }
17f3ba69f65182426ad4e568bb2d6f192ccd2ed5trawick
e6cc28a5eb3371ba0c38e941855e71ff0054f50erbb if (cls->log_fd != NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return cls; /* virtual config shared w/main server */
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaron if (cls->fname == NULL) {
785be1b6298010956622771c870ab3cd8ca57a2faaron return cls; /* Leave it NULL to decline. */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf if (*cls->fname == '|') {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf piped_log *pl;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
c1b808d160bfb5c849263be8d4acff600853a328trawick pl = ap_open_piped_log(p, cls->fname + 1);
e6cc28a5eb3371ba0c38e941855e71ff0054f50erbb if (pl == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding exit(1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
785be1b6298010956622771c870ab3cd8ca57a2faaron cls->log_fd = ap_piped_log_write_fd(pl);
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron else {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding const char *fname = ap_server_root_relative(p, cls->fname);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((status = apr_file_open(&cls->log_fd, fname, xfer_flags, xfer_perms, p))
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf != APR_SUCCESS) {
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf ap_log_error(APLOG_MARK, APLOG_ERR, status, s,
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf "could not open transfer log file %s.", fname);
b88f887ed5554d9050d97f9a56a89ae62bdbd906fanf exit(1);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
apr_file_set_inherit(cls->log_fd);
}
#ifdef BUFFERED_LOGS
cls->outcnt = 0;
#endif
return cls;
}
static config_log_state *open_multi_logs(server_rec *s, apr_pool_t *p)
{
int i;
multi_log_state *mls = ap_get_module_config(s->module_config,
&log_config_module);
config_log_state *clsarray;
const char *dummy;
const char *format;
if (mls->default_format_string) {
format = apr_table_get(mls->formats, mls->default_format_string);
if (format) {
mls->default_format = parse_log_string(p, format, &dummy);
}
}
if (!mls->default_format) {
mls->default_format = parse_log_string(p, DEFAULT_LOG_FORMAT, &dummy);
}
if (mls->config_logs->nelts) {
clsarray = (config_log_state *) mls->config_logs->elts;
for (i = 0; i < mls->config_logs->nelts; ++i) {
config_log_state *cls = &clsarray[i];
if (cls->format_string) {
format = apr_table_get(mls->formats, cls->format_string);
if (format) {
cls->format = parse_log_string(p, format, &dummy);
}
}
cls = open_config_log(s, p, cls, mls->default_format);
}
}
else if (mls->server_config_logs) {
clsarray = (config_log_state *) mls->server_config_logs->elts;
for (i = 0; i < mls->server_config_logs->nelts; ++i) {
config_log_state *cls = &clsarray[i];
if (cls->format_string) {
format = apr_table_get(mls->formats, cls->format_string);
if (format) {
cls->format = parse_log_string(p, format, &dummy);
}
}
cls = open_config_log(s, p, cls, mls->default_format);
}
}
return NULL;
}
#ifdef BUFFERED_LOGS
static apr_status_t flush_all_logs(void *data)
{
server_rec *s = data;
multi_log_state *mls;
apr_array_header_t *log_list;
config_log_state *clsarray;
int i;
for (; s; s = s->next) {
mls = ap_get_module_config(s->module_config, &log_config_module);
log_list = NULL;
if (mls->config_logs->nelts) {
log_list = mls->config_logs;
}
else if (mls->server_config_logs) {
log_list = mls->server_config_logs;
}
if (log_list) {
clsarray = (config_log_state *) log_list->elts;
for (i = 0; i < log_list->nelts; ++i) {
flush_log(&clsarray[i]);
}
}
}
return APR_SUCCESS;
}
#endif
static void init_config_log(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_rec *s)
{
/* First, do "physical" server, which gets default log fd and format
* for the virtual servers, if they don't override...
*/
open_multi_logs(s, p);
/* Then, virtual servers */
for (s = s->next; s; s = s->next) {
open_multi_logs(s, p);
}
}
static void init_child(apr_pool_t *p, server_rec *s)
{
#ifdef BUFFERED_LOGS
/* Now register the last buffer flush with the cleanup engine */
apr_pool_cleanup_register(p, s, flush_all_logs, flush_all_logs);
#endif
}
static void ap_register_log_handler(apr_pool_t *p, char *tag,
ap_log_handler_fn_t *handler, int def)
{
ap_log_handler *log_struct = apr_palloc(p, sizeof(*log_struct));
log_struct->func = handler;
log_struct->want_orig_default = def;
apr_hash_set(log_hash, tag, 1, (const void *)log_struct);
}
static void log_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
{
static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_pfn_register;
log_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_log_handler);
if (log_pfn_register) {
log_pfn_register(p, "h", log_remote_host, 0);
log_pfn_register(p, "a", log_remote_address, 0 );
log_pfn_register(p, "A", log_local_address, 0 );
log_pfn_register(p, "l", log_remote_logname, 0);
log_pfn_register(p, "u", log_remote_user, 0);
log_pfn_register(p, "t", log_request_time, 0);
log_pfn_register(p, "f", log_request_file, 0);
log_pfn_register(p, "b", clf_log_bytes_sent, 0);
log_pfn_register(p, "B", log_bytes_sent, 0);
log_pfn_register(p, "i", log_header_in, 0);
log_pfn_register(p, "o", log_header_out, 0);
log_pfn_register(p, "n", log_note, 0);
log_pfn_register(p, "e", log_env_var, 0);
log_pfn_register(p, "V", log_server_name, 0);
log_pfn_register(p, "v", log_virtual_host, 0);
log_pfn_register(p, "p", log_server_port, 0);
log_pfn_register(p, "P", log_child_pid, 0);
log_pfn_register(p, "H", log_request_protocol, 0);
log_pfn_register(p, "m", log_request_method, 0);
log_pfn_register(p, "q", log_request_query, 0);
log_pfn_register(p, "c", log_connection_status, 0);
log_pfn_register(p, "C", log_cookie, 0);
log_pfn_register(p, "r", log_request_line, 1);
log_pfn_register(p, "D", log_request_duration_microseconds, 1);
log_pfn_register(p, "T", log_request_duration, 1);
log_pfn_register(p, "U", log_request_uri, 1);
log_pfn_register(p, "s", log_status, 1);
}
}
static void register_hooks(apr_pool_t *p)
{
ap_hook_pre_config(log_pre_config,NULL,NULL,APR_HOOK_REALLY_FIRST);
ap_hook_child_init(init_child,NULL,NULL,APR_HOOK_MIDDLE);
ap_hook_open_logs(init_config_log,NULL,NULL,APR_HOOK_MIDDLE);
ap_hook_log_transaction(multi_log_transaction,NULL,NULL,APR_HOOK_MIDDLE);
/* Init log_hash before we register the optional function. It is
* possible for the optional function, ap_register_log_handler,
* to be called before any other mod_log_config hooks are called.
* As a policy, we should init everything required by an optional function
* before calling APR_REGISTER_OPTIONAL_FN.
*/
log_hash = apr_hash_make(p);
APR_REGISTER_OPTIONAL_FN(ap_register_log_handler);
}
module AP_MODULE_DECLARE_DATA log_config_module =
{
STANDARD20_MODULE_STUFF,
NULL, /* create per-dir config */
NULL, /* merge per-dir config */
make_config_log_state, /* server config */
merge_config_log_state, /* merge server config */
config_log_cmds, /* command apr_table_t */
register_hooks /* register hooks */
};