mod_log_config.c revision 144806982c1764b6bdd45caab786fcd620e9f3b5
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * http://www.apache.org/licenses/LICENSE-2.0
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Unless required by applicable law or agreed to in writing, software
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * distributed under the License is distributed on an "AS IS" BASIS,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * See the License for the specific language governing permissions and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * limitations under the License.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Modified by djm@va.pubnix.com:
e8f95a682820a599fe41b22977010636be5c2717jim * If no TransferLog is given explicitly, decline to log.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
e8f95a682820a599fe41b22977010636be5c2717jim * This is module implements the TransferLog directive (same as the
1747d30b98aa1bdbc43994c02cd46ab4cb9319e4fielding * common log module), and additional directives, LogFormat and CustomLog.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Syntax:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * TransferLog fn Logs transfers to fn in standard log format, unless
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * a custom format is set with LogFormat
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * LogFormat format Set a log format from TransferLog files
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * CustomLog fn format
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * Log to file fn with format given by the format
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * argument
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * CookieLog fn For backwards compatability with old Cookie
5c0419d51818eb02045cf923a9fe456127a44c60wrowe * logging module - now deprecated.
5c0419d51818eb02045cf923a9fe456127a44c60wrowe *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * There can be any number of TransferLog and CustomLog
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * commands. Each request will be logged to _ALL_ the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * named files, in the appropriate format.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * If no TransferLog or CustomLog directive appears in a VirtualHost,
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * the request will be logged to the log file(s) defined outside
cd3bbd6d2df78d6c75e5d159a81ef8bdd5f70df9trawick * the virtual host section. If a TransferLog or CustomLog directive
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * appears in the VirtualHost section, the log files defined outside
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * the VirtualHost will _not_ be used. This makes this module compatable
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * with the CLF and config log modules, where the use of TransferLog
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * inside the VirtualHost section overrides its use outside.
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf *
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * Examples:
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf *
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * TransferLog logs/access_log
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * <VirtualHost>
bede2929837dfd23863ad4b39199c63126566d61jorton * LogFormat "... custom format ..."
0f60998368b493f90120180a93fc2e1e74490872covener * TransferLog log/virtual_only
0f60998368b493f90120180a93fc2e1e74490872covener * CustomLog log/virtual_useragents "%t %{user-agent}i"
0f60998368b493f90120180a93fc2e1e74490872covener * </VirtualHost>
0f60998368b493f90120180a93fc2e1e74490872covener *
0f60998368b493f90120180a93fc2e1e74490872covener * This will log using CLF to access_log any requests handled by the
0f60998368b493f90120180a93fc2e1e74490872covener * main server, while any requests to the virtual host will be logged
0f60998368b493f90120180a93fc2e1e74490872covener * with the "... custom format..." to virtual_only _AND_ using
0f60998368b493f90120180a93fc2e1e74490872covener * the custom user-agent log to virtual_useragents.
87587593f1a53030e840acc0dec6cc881022ea40covener *
87587593f1a53030e840acc0dec6cc881022ea40covener * Note that the NCSA referer and user-agent logs are easily added with
87587593f1a53030e840acc0dec6cc881022ea40covener * CustomLog:
87587593f1a53030e840acc0dec6cc881022ea40covener * CustomLog logs/referer "%{referer}i -> %U"
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener * CustomLog logs/agent "%{user-agent}i"
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener *
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener * RefererIgnore functionality can be obtained with conditional
97cd2f98ad4abe68aaaba96b5bfc9ebf7109a2c1covener * logging (SetEnvIf and CustomLog ... env=!VAR).
97cd2f98ad4abe68aaaba96b5bfc9ebf7109a2c1covener *
97cd2f98ad4abe68aaaba96b5bfc9ebf7109a2c1covener * But using this method allows much easier modification of the
97cd2f98ad4abe68aaaba96b5bfc9ebf7109a2c1covener * log format, e.g. to log hosts along with UA:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * CustomLog logs/referer "%{referer}i %U %h"
43997561b2302d13dee973998e77743a3ddd2374trawick *
fa123db15501821e36e513afa78e839775ad2800covener * The argument to LogFormat and CustomLog is a string, which can include
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * literal characters copied into the log files, and '%' directives as
0568280364eb026393be492ebc732795c4934643jorton * follows:
0568280364eb026393be492ebc732795c4934643jorton *
0568280364eb026393be492ebc732795c4934643jorton * %...B: bytes sent, excluding HTTP headers.
0568280364eb026393be492ebc732795c4934643jorton * %...b: bytes sent, excluding HTTP headers in CLF format, i.e. a '-'
0568280364eb026393be492ebc732795c4934643jorton * when no bytes where sent (rather than a '0'.
0568280364eb026393be492ebc732795c4934643jorton * %...{FOOBAR}C: The contents of the HTTP cookie FOOBAR
0568280364eb026393be492ebc732795c4934643jorton * %...{FOOBAR}e: The contents of the environment variable FOOBAR
0568280364eb026393be492ebc732795c4934643jorton * %...f: filename
0568280364eb026393be492ebc732795c4934643jorton * %...h: remote host
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...a: remote IP-address
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...A: local IP-address
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...{Foobar}i: The contents of Foobar: header line(s) in the request
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * sent to the client.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...k: number of keepalive requests served over this connection
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...l: remote logname (from identd, if supplied)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...{Foobar}n: The contents of note "Foobar" from another module.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...{Foobar}o: The contents of Foobar: header line(s) in the reply.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...p: the canonical port for the server
796e4a7141265d8ed7036e4628161c6eafb2a789jorton * %...{format}p: the canonical port for the server, or the actual local
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * or remote port
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...P: the process ID of the child that serviced the request.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...{format}P: the process ID or thread ID of the child/thread that
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * serviced the request
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...r: first line of request
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...s: status. For requests that got internally redirected, this
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * is status of the *original* request --- %...>s for the last.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...t: time, in common log format time format
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...{format}t: The time, in the form given by format, which should
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * be in strftime(3) format.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...T: the time taken to serve the request, in seconds.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...D: the time taken to serve the request, in micro seconds.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...u: remote user (from auth; may be bogus if return status (%s) is 401)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...U: the URL path requested.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...v: the configured name of the server (i.e. which virtual host?)
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe * %...V: the server name according to the UseCanonicalName setting
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...m: the request method
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin * %...H: the request protocol
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...q: the query string prepended by "?", or empty if no query string
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...X: Status of the connection.
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin * 'X' = connection aborted before the response completed.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * '+' = connection may be kept alive after the response is sent.
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin * '-' = connection will be closed after the response is sent.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * (This directive was %...c in late versions of Apache 1.3, but
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * this conflicted with the historical ssl %...{var}c syntax.)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...L: Log-Id of the Request (or '-' if none)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * %...{c}L: Log-Id of the Connection (or '-' if none)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin * indicate conditions for inclusion of the item (which will cause it
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin * to be replaced with '-' if the condition is not met). Note that
a1790fb35c4b352dab721370985c623a9f8f5062rpluem * there is no escaping performed on the strings from %r, %...i and
713a2b68bac4aeb1e9c48785006c0732451039depquerna * %...o; some with long memories may remember that I thought this was
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * a bad idea, once upon a time, and I'm still not comfortable with
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * it, but it is difficult to see how to "do the right thing" with all
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * of '%..i', unless we URL-escape everything and break with CLF.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * The forms of condition are a list of HTTP status codes, which may
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe * or may not be preceded by '!'. Thus, '%400,501{User-agent}i' logs
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe * User-agent: on 400 errors and 501 errors (Bad Request, Not
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Implemented) only; '%!200,304,302{Referer}i' logs Referer: on all
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * requests which did *not* return some sort of normal status.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * The default LogFormat reproduces CLF; see below.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * The way this is supposed to work with virtual hosts is as follows:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * a virtual host can have its own LogFormat, or its own TransferLog.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * If it doesn't have its own LogFormat, it inherits from the main
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * server. If it doesn't have its own TransferLog, it writes to the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * same descriptor (meaning the same process for "| ...").
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes * --- rst */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr_strings.h"
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe#include "apr_lib.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr_hash.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "apr_optional.h"
fa123db15501821e36e513afa78e839775ad2800covener#include "apr_anylock.h"
fa123db15501821e36e513afa78e839775ad2800covener
fa123db15501821e36e513afa78e839775ad2800covener#define APR_WANT_STRFUNC
fa123db15501821e36e513afa78e839775ad2800covener#include "apr_want.h"
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
fa123db15501821e36e513afa78e839775ad2800covener#include "ap_config.h"
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#include "mod_log_config.h"
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#include "httpd.h"
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#include "http_config.h"
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener#include "http_core.h" /* For REMOTE_NAME */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "http_log.h"
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#include "http_protocol.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "util_time.h"
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#include "ap_mpm.h"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#if APR_HAVE_UNISTD_H
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include <unistd.h>
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#endif
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#ifdef HAVE_LIMITS_H
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include <limits.h>
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#endif
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesmodule AP_MODULE_DECLARE_DATA log_config_module;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int xfer_flags = (APR_WRITE | APR_APPEND | APR_CREATE | APR_LARGEFILE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_fileperms_t xfer_perms = APR_OS_DEFAULT;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_hash_t *log_hash;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t ap_default_log_writer(request_rec *r,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes void *handle,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char **strs,
fa123db15501821e36e513afa78e839775ad2800covener int *strl,
cceddc0b6c0fdaed0c73abda39975bb1d388243acovener int nelts,
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf apr_size_t len);
fa123db15501821e36e513afa78e839775ad2800covenerstatic apr_status_t ap_buffered_log_writer(request_rec *r,
cceddc0b6c0fdaed0c73abda39975bb1d388243acovener void *handle,
f2be127030aa4190033084f0a6add531c9bc41desf const char **strs,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener int *strl,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener int nelts,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener apr_size_t len);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s,
60215f303c7e1ce8b6d272acb5bfa5b3d99dfd34covener const char* name);
60215f303c7e1ce8b6d272acb5bfa5b3d99dfd34covenerstatic void *ap_buffered_log_writer_init(apr_pool_t *p, server_rec *s,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener const char* name);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic ap_log_writer_init* ap_log_set_writer_init(ap_log_writer_init *handle);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic ap_log_writer* ap_log_set_writer(ap_log_writer *handle);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic ap_log_writer *log_writer = ap_default_log_writer;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic ap_log_writer_init *log_writer_init = ap_default_log_writer_init;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic int buffered_logs = 0; /* default unbuffered */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic apr_array_header_t *all_buffered_logs = NULL;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
6683642c1e0032eeeed5f99e8c14880692ef84c5sf/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * is guaranteed. So we'll just guess 512 in the event the system
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * doesn't have this. Now, for file writes there is actually no limit,
6683642c1e0032eeeed5f99e8c14880692ef84c5sf * the entire write is atomic. Whether all systems implement this
6683642c1e0032eeeed5f99e8c14880692ef84c5sf * correctly is another question entirely ... so we'll just use PIPE_BUF
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * because it's probably a good guess as to what is implemented correctly
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * everywhere.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#ifdef PIPE_BUF
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#define LOG_BUFSIZE PIPE_BUF
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#else
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#define LOG_BUFSIZE (512)
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#endif
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener/*
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * multi_log_state is our per-(virtual)-server configuration. We store
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * an array of the logs we are going to use, each of type config_log_state.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * If a default log format is given by LogFormat, store in default_format
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * (backward compat. with mod_log_config). We also store for each virtual
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * server a pointer to the logs specified for the main server, so that if this
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * vhost has no logs defined, we can use the main server's logs instead.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener *
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * So, for the main server, config_logs contains a list of the log files
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * and server_config_logs is empty. For a vhost, server_config_logs
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * points to the same array as config_logs in the main server, and
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * config_logs points to the array of logs defined inside this vhost,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * which might be empty.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenertypedef struct {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener const char *default_format_string;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener apr_array_header_t *default_format;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener apr_array_header_t *config_logs;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener apr_array_header_t *server_config_logs;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener apr_table_t *formats;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener} multi_log_state;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener/*
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * config_log_state holds the status of a single log file. fname might
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * be NULL, which means this module does no logging for this
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * request. format might be NULL, in which case the default_format
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * from the multi_log_state should be used, or if that is NULL as
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * well, use the CLF.
60215f303c7e1ce8b6d272acb5bfa5b3d99dfd34covener * log_writer is NULL before the log file is opened and is
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * set to a opaque structure (usually a fd) after it is opened.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
0e05808dc59a321566303084c84b9826a4353cefrederpj */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholestypedef struct {
b08925593f214f621161742925dcf074a8047e0acovener apr_file_t *handle;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t outcnt;
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf char outbuf[LOG_BUFSIZE];
465bb68501690d7a47bfd2a6129580047d76d8f1rederpj apr_anylock_t mutex;
1ae7a5fbce5d4f65f3da355792258fe5dbc4ef55covener} buffered_log;
465bb68501690d7a47bfd2a6129580047d76d8f1rederpj
e8f95a682820a599fe41b22977010636be5c2717jimtypedef struct {
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes const char *fname;
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes const char *format_string;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin apr_array_header_t *format;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes void *log_writer;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes char *condition_var;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ap_expr_info_t *condition_expr;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes} config_log_state;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes/*
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * log_request_state holds request specific log data that is not
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * part of the request_rec.
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf */
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sftypedef struct {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes apr_time_t request_end_time;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes} log_request_state;
513b324e774c559b579896df131fd7c8471ed529rederpj
513b324e774c559b579896df131fd7c8471ed529rederpj/*
513b324e774c559b579896df131fd7c8471ed529rederpj * Format items...
513b324e774c559b579896df131fd7c8471ed529rederpj * Note that many of these could have ap_sprintfs replaced with static buffers.
513b324e774c559b579896df131fd7c8471ed529rederpj */
513b324e774c559b579896df131fd7c8471ed529rederpj
513b324e774c559b579896df131fd7c8471ed529rederpjtypedef struct {
513b324e774c559b579896df131fd7c8471ed529rederpj ap_log_handler_fn_t *func;
513b324e774c559b579896df131fd7c8471ed529rederpj char *arg;
513b324e774c559b579896df131fd7c8471ed529rederpj int condition_sense;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes int want_orig;
02fd88c85a9850109753b87612955ad372de1575sf apr_array_header_t *conditions;
02fd88c85a9850109753b87612955ad372de1575sf} log_format_item;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic char *pfmt(apr_pool_t *p, int i)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (i <= 0) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return "-";
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return apr_itoa(p, i);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const char *constant_item(request_rec *dummy, char *stuff)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return stuff;
707f6d077f73cc948deead8df5b40ea42c1eaa78covener}
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sfstatic const char *log_remote_host(request_rec *r, char *a)
707f6d077f73cc948deead8df5b40ea42c1eaa78covener{
707f6d077f73cc948deead8df5b40ea42c1eaa78covener return ap_escape_logitem(r->pool, ap_get_remote_host(r->connection,
707f6d077f73cc948deead8df5b40ea42c1eaa78covener r->per_dir_config,
707f6d077f73cc948deead8df5b40ea42c1eaa78covener REMOTE_NAME, NULL));
707f6d077f73cc948deead8df5b40ea42c1eaa78covener}
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
707f6d077f73cc948deead8df5b40ea42c1eaa78covenerstatic const char *log_remote_address(request_rec *r, char *a)
9ad7b260be233be7d7b5576979825cac72e15498rederpj{
9ad7b260be233be7d7b5576979825cac72e15498rederpj return r->connection->remote_ip;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
54d22ed1c429b903b029bbd62621f11a9e286137minfrinstatic const char *log_local_address(request_rec *r, char *a)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return r->connection->local_ip;
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const char *log_remote_logname(request_rec *r, char *a)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return ap_escape_logitem(r->pool, ap_get_remote_logname(r));
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const char *log_remote_user(request_rec *r, char *a)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes char *rvalue = r->user;
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf if (rvalue == NULL) {
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf rvalue = "-";
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else if (strlen(rvalue) == 0) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes rvalue = "\"\"";
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes rvalue = ap_escape_logitem(r->pool, rvalue);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
b08925593f214f621161742925dcf074a8047e0acovener return rvalue;
b08925593f214f621161742925dcf074a8047e0acovener}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
707f6d077f73cc948deead8df5b40ea42c1eaa78covenerstatic const char *log_request_line(request_rec *r, char *a)
707f6d077f73cc948deead8df5b40ea42c1eaa78covener{
9ad7b260be233be7d7b5576979825cac72e15498rederpj /* NOTE: If the original request contained a password, we
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * re-write the request line here to contain XXXXXX instead:
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * (note the truncation before the protocol string for HTTP/0.9 requests)
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * (note also that r->the_request contains the unmodified request)
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener return ap_escape_logitem(r->pool,
707f6d077f73cc948deead8df5b40ea42c1eaa78covener (r->parsed_uri.password)
707f6d077f73cc948deead8df5b40ea42c1eaa78covener ? apr_pstrcat(r->pool, r->method, " ",
9ad7b260be233be7d7b5576979825cac72e15498rederpj apr_uri_unparse(r->pool,
707f6d077f73cc948deead8df5b40ea42c1eaa78covener &r->parsed_uri, 0),
707f6d077f73cc948deead8df5b40ea42c1eaa78covener r->assbackwards ? NULL : " ",
707f6d077f73cc948deead8df5b40ea42c1eaa78covener r->protocol, NULL)
707f6d077f73cc948deead8df5b40ea42c1eaa78covener : r->the_request);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener}
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
707f6d077f73cc948deead8df5b40ea42c1eaa78covenerstatic const char *log_request_file(request_rec *r, char *a)
707f6d077f73cc948deead8df5b40ea42c1eaa78covener{
707f6d077f73cc948deead8df5b40ea42c1eaa78covener return ap_escape_logitem(r->pool, r->filename);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener}
707f6d077f73cc948deead8df5b40ea42c1eaa78covenerstatic const char *log_request_uri(request_rec *r, char *a)
707f6d077f73cc948deead8df5b40ea42c1eaa78covener{
707f6d077f73cc948deead8df5b40ea42c1eaa78covener return ap_escape_logitem(r->pool, r->uri);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener}
707f6d077f73cc948deead8df5b40ea42c1eaa78covenerstatic const char *log_request_method(request_rec *r, char *a)
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf{
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf return ap_escape_logitem(r->pool, r->method);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener}
707f6d077f73cc948deead8df5b40ea42c1eaa78covenerstatic const char *log_log_id(request_rec *r, char *a)
707f6d077f73cc948deead8df5b40ea42c1eaa78covener{
707f6d077f73cc948deead8df5b40ea42c1eaa78covener if (a && !strcmp(a, "c")) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener return r->connection->log_id ? r->connection->log_id : "-";
707f6d077f73cc948deead8df5b40ea42c1eaa78covener }
707f6d077f73cc948deead8df5b40ea42c1eaa78covener else {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener return r->log_id ? r->log_id : "-";
707f6d077f73cc948deead8df5b40ea42c1eaa78covener }
707f6d077f73cc948deead8df5b40ea42c1eaa78covener}
707f6d077f73cc948deead8df5b40ea42c1eaa78covenerstatic const char *log_request_protocol(request_rec *r, char *a)
707f6d077f73cc948deead8df5b40ea42c1eaa78covener{
9ad7b260be233be7d7b5576979825cac72e15498rederpj return ap_escape_logitem(r->pool, r->protocol);
9ad7b260be233be7d7b5576979825cac72e15498rederpj}
9ad7b260be233be7d7b5576979825cac72e15498rederpjstatic const char *log_request_query(request_rec *r, char *a)
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf{
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf return (r->args) ? apr_pstrcat(r->pool, "?",
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf ap_escape_logitem(r->pool, r->args), NULL)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem : "";
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf}
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sfstatic const char *log_status(request_rec *r, char *a)
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf{
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf return pfmt(r->pool, r->status);
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf}
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sfstatic const char *log_handler(request_rec *r, char *a)
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf{
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf return ap_escape_logitem(r->pool, r->handler);
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf}
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sfstatic const char *clf_log_bytes_sent(request_rec *r, char *a)
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf{
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf if (!r->sent_bodyct || !r->bytes_sent) {
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf return "-";
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf }
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf else {
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf return apr_off_t_toa(r->pool, r->bytes_sent);
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf }
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf}
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf
141e1368614dc7564e1627671361b01b4869b491bnicholesstatic const char *log_bytes_sent(request_rec *r, char *a)
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (!r->sent_bodyct || !r->bytes_sent) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf return "0";
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim else {
1ae7a5fbce5d4f65f3da355792258fe5dbc4ef55covener return apr_off_t_toa(r->pool, r->bytes_sent);
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const char *log_header_in(request_rec *r, char *a)
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return ap_escape_logitem(r->pool, apr_table_get(r->headers_in, a));
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes}
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes
4be9c459920a7c1cfe62d654327dae5c4bb6b284sfstatic APR_INLINE char *find_multiple_headers(apr_pool_t *pool,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf const apr_table_t *table,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf const char *key)
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf{
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf const apr_array_header_t *elts;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf const apr_table_entry_t *t_elt;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf const apr_table_entry_t *t_end;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf apr_size_t len;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf struct sle {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf struct sle *next;
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf const char *value;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf apr_size_t len;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf } *result_list, *rp;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf elts = apr_table_elts(table);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if (!elts->nelts) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf return NULL;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes t_elt = (const apr_table_entry_t *)elts->elts;
e8f95a682820a599fe41b22977010636be5c2717jim t_end = t_elt + elts->nelts;
783874b86bfe13d7a4fe0922f344a3779cdccea3covener len = 1; /* \0 */
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener result_list = rp = NULL;
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener do {
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener if (!strcasecmp(t_elt->key, key)) {
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener if (!result_list) {
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener result_list = rp = apr_palloc(pool, sizeof(*rp));
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener }
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener else {
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener rp = rp->next = apr_palloc(pool, sizeof(*rp));
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener len += 2; /* ", " */
783874b86bfe13d7a4fe0922f344a3779cdccea3covener }
7dbf29be626018bc389ef94c1846aeac4b72633bsf
7dbf29be626018bc389ef94c1846aeac4b72633bsf rp->next = NULL;
7dbf29be626018bc389ef94c1846aeac4b72633bsf rp->value = t_elt->val;
7dbf29be626018bc389ef94c1846aeac4b72633bsf rp->len = strlen(rp->value);
7dbf29be626018bc389ef94c1846aeac4b72633bsf
7dbf29be626018bc389ef94c1846aeac4b72633bsf len += rp->len;
7dbf29be626018bc389ef94c1846aeac4b72633bsf }
7dbf29be626018bc389ef94c1846aeac4b72633bsf ++t_elt;
7dbf29be626018bc389ef94c1846aeac4b72633bsf } while (t_elt < t_end);
7dbf29be626018bc389ef94c1846aeac4b72633bsf
7dbf29be626018bc389ef94c1846aeac4b72633bsf if (result_list) {
7dbf29be626018bc389ef94c1846aeac4b72633bsf char *result = apr_palloc(pool, len);
7dbf29be626018bc389ef94c1846aeac4b72633bsf char *cp = result;
7dbf29be626018bc389ef94c1846aeac4b72633bsf
7dbf29be626018bc389ef94c1846aeac4b72633bsf rp = result_list;
783874b86bfe13d7a4fe0922f344a3779cdccea3covener while (rp) {
7dbf29be626018bc389ef94c1846aeac4b72633bsf if (rp != result_list) {
7dbf29be626018bc389ef94c1846aeac4b72633bsf *cp++ = ',';
7dbf29be626018bc389ef94c1846aeac4b72633bsf *cp++ = ' ';
7dbf29be626018bc389ef94c1846aeac4b72633bsf }
7dbf29be626018bc389ef94c1846aeac4b72633bsf memcpy(cp, rp->value, rp->len);
783874b86bfe13d7a4fe0922f344a3779cdccea3covener cp += rp->len;
7dbf29be626018bc389ef94c1846aeac4b72633bsf rp = rp->next;
7dbf29be626018bc389ef94c1846aeac4b72633bsf }
7dbf29be626018bc389ef94c1846aeac4b72633bsf *cp = '\0';
7dbf29be626018bc389ef94c1846aeac4b72633bsf
7dbf29be626018bc389ef94c1846aeac4b72633bsf return result;
7dbf29be626018bc389ef94c1846aeac4b72633bsf }
7dbf29be626018bc389ef94c1846aeac4b72633bsf
783874b86bfe13d7a4fe0922f344a3779cdccea3covener return NULL;
7dbf29be626018bc389ef94c1846aeac4b72633bsf}
7dbf29be626018bc389ef94c1846aeac4b72633bsf
7dbf29be626018bc389ef94c1846aeac4b72633bsfstatic const char *log_header_out(request_rec *r, char *a)
7dbf29be626018bc389ef94c1846aeac4b72633bsf{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *cp = NULL;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (!strcasecmp(a, "Content-type") && r->content_type) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes cp = ap_field_noparam(r->pool, r->content_type);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else if (!strcasecmp(a, "Set-Cookie")) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes cp = find_multiple_headers(r->pool, r->headers_out, a);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes cp = apr_table_get(r->headers_out, a);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf return ap_escape_logitem(r->pool, cp);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const char *log_note(request_rec *r, char *a)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return ap_escape_logitem(r->pool, apr_table_get(r->notes, a));
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const char *log_env_var(request_rec *r, char *a)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return ap_escape_logitem(r->pool, apr_table_get(r->subprocess_env, a));
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const char *log_cookie(request_rec *r, char *a)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *cookies_entry;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /*
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * This supports Netscape version 0 cookies while being tolerant to
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * some properties of RFC2109/2965 version 1 cookies:
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * - case-insensitive match of cookie names
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * - white space between the tokens
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * It does not support the following version 1 features:
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * - quoted strings as cookie values
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * - commas to separate cookies
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((cookies_entry = apr_table_get(r->headers_in, "Cookie"))) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *cookie, *last1, *last2;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf char *cookies = apr_pstrdup(r->pool, cookies_entry);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf while ((cookie = apr_strtok(cookies, ";", &last1))) {
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener char *name = apr_strtok(cookie, "=", &last2);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener char *value;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener apr_collapse_spaces(name, name);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if (!strcasecmp(name, a) && (value = apr_strtok(NULL, "=", &last2))) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *last;
e8f95a682820a599fe41b22977010636be5c2717jim value += strspn(value, " \t"); /* Move past leading WS */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes last = value + strlen(value) - 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while (last >= value && apr_isspace(*last)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *last = '\0';
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf --last;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener }
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener return ap_escape_logitem(r->pool, value);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener }
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener cookies = NULL;
7dbf29be626018bc389ef94c1846aeac4b72633bsf }
7dbf29be626018bc389ef94c1846aeac4b72633bsf }
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener return NULL;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener}
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covenerstatic const char *log_request_time_custom(request_rec *r, char *a,
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener apr_time_exp_t *xt)
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener{
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener apr_size_t retcode;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener char tstr[MAX_STRING_LEN];
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener apr_strftime(tstr, &retcode, sizeof(tstr), a, xt);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener return apr_pstrdup(r->pool, tstr);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener}
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener#define DEFAULT_REQUEST_TIME_SIZE 32
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covenertypedef struct {
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener unsigned t;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener char timestr[DEFAULT_REQUEST_TIME_SIZE];
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener unsigned t_validate;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener} cached_request_time;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener#define TIME_FMT_CUSTOM 0
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener#define TIME_FMT_CLF 1
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener#define TIME_FMT_ABS_SEC 2
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener#define TIME_FMT_ABS_MSEC 3
9c63a05713cb83a44a1590b4af33edeebf39f118sf#define TIME_FMT_ABS_USEC 4
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener#define TIME_FMT_ABS_MSEC_FRAC 5
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener#define TIME_FMT_ABS_USEC_FRAC 6
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
9c63a05713cb83a44a1590b4af33edeebf39f118sf#define TIME_CACHE_SIZE 4
9c63a05713cb83a44a1590b4af33edeebf39f118sf#define TIME_CACHE_MASK 3
4be9c459920a7c1cfe62d654327dae5c4bb6b284sfstatic cached_request_time request_time_cache[TIME_CACHE_SIZE];
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_time_t get_request_end_time(request_rec *r)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_request_state *state = (log_request_state *)ap_get_module_config(r->request_config,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin &log_config_module);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (state->request_end_time == 0) {
9c63a05713cb83a44a1590b4af33edeebf39f118sf state->request_end_time = apr_time_now();
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return state->request_end_time;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *log_request_time(request_rec *r, char *a)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
54d22ed1c429b903b029bbd62621f11a9e286137minfrin apr_time_exp_t xt;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin apr_time_t request_time = r->request_time;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin int fmt_type = TIME_FMT_CUSTOM;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin char *fmt = a;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (fmt && *fmt) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (!strncmp(fmt, "begin", 5)) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin fmt += 5;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (!*fmt) {
e8f95a682820a599fe41b22977010636be5c2717jim fmt_type = TIME_FMT_CLF;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe }
8a03cd420b800a2428f49f4617293de9b2387b20jorton else if (*fmt == ':') {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin fmt++;
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf a = fmt;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin else if (!strncmp(fmt, "end", 3)) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin fmt += 3;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (!*fmt) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin request_time = get_request_end_time(r);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin fmt_type = TIME_FMT_CLF;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin else if (*fmt == ':') {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin fmt++;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin a = fmt;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin request_time = get_request_end_time(r);
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf }
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (!strncmp(fmt, "msec", 4)) {
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener fmt += 4;
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener if (!*fmt) {
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener fmt_type = TIME_FMT_ABS_MSEC;
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener }
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener else if (!strcmp(fmt, "_frac")) {
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener fmt_type = TIME_FMT_ABS_MSEC_FRAC;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin else if (!strncmp(fmt, "usec", 4)) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin fmt += 4;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (!*fmt) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin fmt_type = TIME_FMT_ABS_USEC;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (!strcmp(fmt, "_frac")) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fmt_type = TIME_FMT_ABS_USEC_FRAC;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (!strcmp(fmt, "sec")) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes fmt_type = TIME_FMT_ABS_SEC;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim else if (!*fmt) {
e8f95a682820a599fe41b22977010636be5c2717jim fmt_type = TIME_FMT_CLF;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim else {
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe fmt_type = TIME_FMT_CLF;
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe }
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe
f0f6f1b90ab582896f8a7d56d85bd62a55e57d90covener if (fmt_type >= TIME_FMT_ABS_SEC) { /* Absolute (micro-/milli-)second time
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe * or msec/usec fraction
54d22ed1c429b903b029bbd62621f11a9e286137minfrin */
560fd0658902ab57754616c172d8953e69fc4722bnicholes char* buf = apr_palloc(r->pool, 20);
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener switch (fmt_type) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case TIME_FMT_ABS_SEC:
e8f95a682820a599fe41b22977010636be5c2717jim apr_snprintf(buf, 20, "%" APR_TIME_T_FMT, apr_time_sec(request_time));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case TIME_FMT_ABS_MSEC:
9ad7b260be233be7d7b5576979825cac72e15498rederpj apr_snprintf(buf, 20, "%" APR_TIME_T_FMT, apr_time_as_msec(request_time));
9ad7b260be233be7d7b5576979825cac72e15498rederpj break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case TIME_FMT_ABS_USEC:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_snprintf(buf, 20, "%" APR_TIME_T_FMT, request_time);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case TIME_FMT_ABS_MSEC_FRAC:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_snprintf(buf, 20, "%03" APR_TIME_T_FMT, apr_time_msec(request_time));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf case TIME_FMT_ABS_USEC_FRAC:
560fd0658902ab57754616c172d8953e69fc4722bnicholes apr_snprintf(buf, 20, "%06" APR_TIME_T_FMT, apr_time_usec(request_time));
560fd0658902ab57754616c172d8953e69fc4722bnicholes break;
560fd0658902ab57754616c172d8953e69fc4722bnicholes default:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "-";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return buf;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (fmt_type == TIME_FMT_CUSTOM) { /* Custom format */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* The custom time formatting uses a very large temp buffer
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * on the stack. To avoid using so much stack space in the
e8f95a682820a599fe41b22977010636be5c2717jim * common case where we're not using a custom format, the code
e8f95a682820a599fe41b22977010636be5c2717jim * for the custom format in a separate function. (That's why
e8f95a682820a599fe41b22977010636be5c2717jim * log_request_time_custom is not inlined right here.)
e8f95a682820a599fe41b22977010636be5c2717jim */
e8f95a682820a599fe41b22977010636be5c2717jim ap_explode_recent_localtime(&xt, request_time);
e8f95a682820a599fe41b22977010636be5c2717jim return log_request_time_custom(r, a, &xt);
ae1981fc94adf2b231e2d0e15d2f895b2138c969covener }
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe else { /* CLF format */
7a55c294da84865fe13262ed66ffd0c5841a9da5covener /* This code uses the same technique as ap_explode_recent_localtime():
7a55c294da84865fe13262ed66ffd0c5841a9da5covener * optimistic caching with logic to detect and correct race conditions.
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener * See the comments in server/util_time.c for more information.
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener */
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener cached_request_time* cached_time = apr_palloc(r->pool,
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener sizeof(*cached_time));
54091ac5c596337658fc568231ca1a900abdc5fecovener unsigned t_seconds = (unsigned)apr_time_sec(request_time);
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener unsigned i = t_seconds & TIME_CACHE_MASK;
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener *cached_time = request_time_cache[i];
54091ac5c596337658fc568231ca1a900abdc5fecovener if ((t_seconds != cached_time->t) ||
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (t_seconds != cached_time->t_validate)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Invalid or old snapshot, so compute the proper time string
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * and store it in the cache
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char sign;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int timz;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_explode_recent_localtime(&xt, request_time);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes timz = xt.tm_gmtoff;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (timz < 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes timz = -timz;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sign = '-';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes sign = '+';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes cached_time->t = t_seconds;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_snprintf(cached_time->timestr, DEFAULT_REQUEST_TIME_SIZE,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]",
e8f95a682820a599fe41b22977010636be5c2717jim xt.tm_mday, apr_month_snames[xt.tm_mon],
560fd0658902ab57754616c172d8953e69fc4722bnicholes xt.tm_year+1900, xt.tm_hour, xt.tm_min, xt.tm_sec,
ae1981fc94adf2b231e2d0e15d2f895b2138c969covener sign, timz / (60*60), (timz % (60*60)) / 60);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe cached_time->t_validate = t_seconds;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes request_time_cache[i] = *cached_time;
7a55c294da84865fe13262ed66ffd0c5841a9da5covener }
fa123db15501821e36e513afa78e839775ad2800covener return cached_time->timestr;
fa123db15501821e36e513afa78e839775ad2800covener }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *log_request_duration(request_rec *r, char *a)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_time_t duration = get_request_end_time(r) - r->request_time;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return apr_psprintf(r->pool, "%" APR_TIME_T_FMT, apr_time_sec(duration));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *log_request_duration_microseconds(request_rec *r, char *a)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return apr_psprintf(r->pool, "%" APR_TIME_T_FMT,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (get_request_end_time(r) - r->request_time));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* These next two routines use the canonical name:port so that log
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * parsers don't need to duplicate all the vhost parsing crud.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *log_virtual_host(request_rec *r, char *a)
0e05808dc59a321566303084c84b9826a4353cefrederpj{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return ap_escape_logitem(r->pool, r->server->server_hostname);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic const char *log_server_port(request_rec *r, char *a)
0e05808dc59a321566303084c84b9826a4353cefrederpj{
ebe5305f8b22507374358f32b74d12fb50c05a25covener apr_port_t port;
ebe5305f8b22507374358f32b74d12fb50c05a25covener
ebe5305f8b22507374358f32b74d12fb50c05a25covener if (*a == '\0' || !strcasecmp(a, "canonical")) {
ebe5305f8b22507374358f32b74d12fb50c05a25covener port = r->server->port ? r->server->port : ap_default_port(r);
ebe5305f8b22507374358f32b74d12fb50c05a25covener }
ebe5305f8b22507374358f32b74d12fb50c05a25covener else if (!strcasecmp(a, "remote")) {
ebe5305f8b22507374358f32b74d12fb50c05a25covener port = r->connection->remote_addr->port;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener else if (!strcasecmp(a, "local")) {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener port = r->connection->local_addr->port;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener else {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* bogus format */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener return a;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener return apr_itoa(r->pool, (int)port);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener}
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
0e05808dc59a321566303084c84b9826a4353cefrederpj/* This respects the setting of UseCanonicalName so that
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * the dynamic mass virtual hosting trick works better.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *log_server_name(request_rec *r, char *a)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return ap_escape_logitem(r->pool, ap_get_server_name(r));
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *log_pid_tid(request_rec *r, char *a)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (*a == '\0' || !strcasecmp(a, "pid")) {
9ad7b260be233be7d7b5576979825cac72e15498rederpj return ap_append_pid(r->pool, "", "");
9ad7b260be233be7d7b5576979825cac72e15498rederpj }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin else if (!strcasecmp(a, "tid") || !strcasecmp(a, "hextid")) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin#if APR_HAS_THREADS
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf apr_os_thread_t tid = apr_os_thread_current();
54d22ed1c429b903b029bbd62621f11a9e286137minfrin#else
54d22ed1c429b903b029bbd62621f11a9e286137minfrin int tid = 0; /* APR will format "0" anyway but an arg is needed */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin#endif
560fd0658902ab57754616c172d8953e69fc4722bnicholes return apr_psprintf(r->pool,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin#if APR_MAJOR_VERSION > 1 || (APR_MAJOR_VERSION == 1 && APR_MINOR_VERSION >= 2)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* APR can format a thread id in hex */
ae1981fc94adf2b231e2d0e15d2f895b2138c969covener *a == 'h' ? "%pt" : "%pT",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#else
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener /* APR is missing the feature, so always use decimal */
7a55c294da84865fe13262ed66ffd0c5841a9da5covener "%pT",
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#endif
fa123db15501821e36e513afa78e839775ad2800covener &tid);
fa123db15501821e36e513afa78e839775ad2800covener }
fa123db15501821e36e513afa78e839775ad2800covener /* bogus format */
fa123db15501821e36e513afa78e839775ad2800covener return a;
fa123db15501821e36e513afa78e839775ad2800covener}
fa123db15501821e36e513afa78e839775ad2800covener
fa123db15501821e36e513afa78e839775ad2800covenerstatic const char *log_connection_status(request_rec *r, char *a)
fa123db15501821e36e513afa78e839775ad2800covener{
fa123db15501821e36e513afa78e839775ad2800covener if (r->connection->aborted)
fa123db15501821e36e513afa78e839775ad2800covener return "X";
fa123db15501821e36e513afa78e839775ad2800covener
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (r->connection->keepalive == AP_CONN_KEEPALIVE &&
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (!r->server->keep_alive_max ||
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (r->server->keep_alive_max - r->connection->keepalives) > 0)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "+";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "-";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *log_requests_on_connection(request_rec *r, char *a)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int num = r->connection->keepalives ? r->connection->keepalives - 1 : 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return apr_itoa(r->pool, num);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*****************************************************************
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Parsing the log format string
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
e8f95a682820a599fe41b22977010636be5c2717jimstatic char *parse_log_misc_string(apr_pool_t *p, log_format_item *it,
e8f95a682820a599fe41b22977010636be5c2717jim const char **sa)
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *d;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim it->func = constant_item;
e8f95a682820a599fe41b22977010636be5c2717jim it->conditions = NULL;
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s = *sa;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while (*s && *s != '%') {
e8f95a682820a599fe41b22977010636be5c2717jim s++;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * This might allocate a few chars extra if there's a backslash
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * escape in the format string.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes it->arg = apr_palloc(p, s - *sa + 1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe d = it->arg;
e8f95a682820a599fe41b22977010636be5c2717jim s = *sa;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe while (*s && *s != '%') {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (*s != '\\') {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *d++ = *s++;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s++;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes switch (*s) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '\\':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *d++ = '\\';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s++;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case 'r':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *d++ = '\r';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s++;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case 'n':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *d++ = '\n';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s++;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case 't':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *d++ = '\t';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s++;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes default:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* copy verbatim */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *d++ = '\\';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Allow the loop to deal with this *s in the normal
e8f95a682820a599fe41b22977010636be5c2717jim * fashion so that it handles end of string etc.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * properly.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *d = '\0';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *sa = s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
e8f95a682820a599fe41b22977010636be5c2717jim}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic char *parse_log_item(apr_pool_t *p, log_format_item *it, const char **sa)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *s = *sa;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_handler *handler;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (*s != '%') {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return parse_log_misc_string(p, it, sa);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener ++s;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener it->condition_sense = 0;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener it->conditions = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes if (*s == '%') {
43c3e6a4b559b76b750c245ee95e2782c15b4296jim it->arg = "%";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes it->func = constant_item;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *sa = ++s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener }
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf it->want_orig = -1;
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener it->arg = ""; /* For safety's sake... */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe while (*s) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe int i;
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener switch (*s) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '!':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ++s;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf it->condition_sense = !it->condition_sense;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf break;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf case '<':
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf ++s;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf it->want_orig = 1;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf break;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener case '>':
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf ++s;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf it->want_orig = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case ',':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ++s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '{':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ++s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes it->arg = ap_getword(p, &s, '}');
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '0':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '1':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '2':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '3':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '4':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '5':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '6':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '7':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '8':
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes case '9':
e8f95a682820a599fe41b22977010636be5c2717jim i = *s - '0';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while (apr_isdigit(*++s)) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe i = i * 10 + (*s) - '0';
e8f95a682820a599fe41b22977010636be5c2717jim }
e8f95a682820a599fe41b22977010636be5c2717jim if (!it->conditions) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe it->conditions = apr_array_make(p, 4, sizeof(int));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *(int *) apr_array_push(it->conditions) = i;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes default:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes handler = (ap_log_handler *)apr_hash_get(log_hash, s++, 1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!handler) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char dummy[2];
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dummy[0] = s[-1];
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dummy[1] = '\0';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return apr_pstrcat(p, "Unrecognized LogFormat directive %",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dummy, NULL);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim it->func = handler->func;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (it->want_orig == -1) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem it->want_orig = handler->want_orig_default;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *sa = s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe }
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe }
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "Ran off end of LogFormat parsing args to some directive";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
e8f95a682820a599fe41b22977010636be5c2717jim
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_array_header_t *parse_log_string(apr_pool_t *p, const char *s, const char **err)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_array_header_t *a = apr_array_make(p, 30, sizeof(log_format_item));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char *res;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while (*s) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe if ((res = parse_log_item(p, (log_format_item *) apr_array_push(a), &s))) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe *err = res;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s = APR_EOL_STR;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes parse_log_item(p, (log_format_item *) apr_array_push(a), &s);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return a;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*****************************************************************
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Actually logging.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic const char *process_item(request_rec *r, request_rec *orig,
e8f95a682820a599fe41b22977010636be5c2717jim log_format_item *item)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *cp;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* First, see if we need to process this thing at all... */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj if (item->conditions && item->conditions->nelts != 0) {
e8f95a682820a599fe41b22977010636be5c2717jim int i;
e8f95a682820a599fe41b22977010636be5c2717jim int *conds = (int *) item->conditions->elts;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe int in_list = 0;
e8f95a682820a599fe41b22977010636be5c2717jim
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (i = 0; i < item->conditions->nelts; ++i) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (r->status == conds[i]) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes in_list = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((item->condition_sense && in_list)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes || (!item->condition_sense && !in_list)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return "-";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* We do. Do it... */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes cp = (*item->func) (item->want_orig ? orig : r, item->arg);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return cp ? cp : "-";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void flush_log(buffered_log *buf)
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj{
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj if (buf->outcnt && buf->handle != NULL) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj apr_file_write(buf->handle, buf->outbuf, &buf->outcnt);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj buf->outcnt = 0;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int config_log_transaction(request_rec *r, config_log_state *cls,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_array_header_t *default_format)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_format_item *items;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char **strs;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener int *strl;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes request_rec *orig;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int i;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj apr_size_t len = 0;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener apr_array_header_t *format;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener char *envar;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener apr_status_t rv;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes if (cls->fname == NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return DECLINED;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener * See if we've got any conditional envariable-controlled logging decisions
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener * to make.
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener */
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener if (cls->condition_var != NULL) {
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener envar = cls->condition_var;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (*envar != '!') {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (apr_table_get(r->subprocess_env, envar) == NULL) {
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes return DECLINED;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if (apr_table_get(r->subprocess_env, &envar[1]) != NULL) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf return DECLINED;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf else if (cls->condition_expr != NULL) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf const char *err;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener int rc = ap_expr_exec(r, cls->condition_expr, &err);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if (rc < 0)
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Error evaluating log condition: %s", err);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (rc <= 0)
e8f95a682820a599fe41b22977010636be5c2717jim return DECLINED;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes format = cls->format ? cls->format : default_format;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes strs = apr_palloc(r->pool, sizeof(char *) * (format->nelts));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes strl = apr_palloc(r->pool, sizeof(int) * (format->nelts));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes items = (log_format_item *) format->elts;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj orig = r;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while (orig->prev) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe orig = orig->prev;
e8f95a682820a599fe41b22977010636be5c2717jim }
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe while (r->next) {
e8f95a682820a599fe41b22977010636be5c2717jim r = r->next;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe }
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim for (i = 0; i < format->nelts; ++i) {
e8f95a682820a599fe41b22977010636be5c2717jim strs[i] = process_item(r, orig, &items[i]);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe }
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj for (i = 0; i < format->nelts; ++i) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj len += strl[i] = strlen(strs[i]);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (!log_writer) {
9c63a05713cb83a44a1590b4af33edeebf39f118sf ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "log writer isn't correctly setup");
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf return HTTP_INTERNAL_SERVER_ERROR;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = log_writer(r, cls->log_writer, strs, strl, format->nelts, len);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* xxx: do we return an error on log_writer? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return OK;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int multi_log_transaction(request_rec *r)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes multi_log_state *mls = ap_get_module_config(r->server->module_config,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes &log_config_module);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes config_log_state *clsarray;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int i;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Initialize per request state
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_request_state *state = apr_pcalloc(r->pool, sizeof(log_request_state));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_set_module_config(r->request_config, &log_config_module, state);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Log this transaction..
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (mls->config_logs->nelts) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes clsarray = (config_log_state *) mls->config_logs->elts;
8869662bb1a4078297020e94ae5e928626d877c6rederpj for (i = 0; i < mls->config_logs->nelts; ++i) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem config_log_state *cls = &clsarray[i];
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem config_log_transaction(r, cls, mls->default_format);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem else if (mls->server_config_logs) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem clsarray = (config_log_state *) mls->server_config_logs->elts;
8869662bb1a4078297020e94ae5e928626d877c6rederpj for (i = 0; i < mls->server_config_logs->nelts; ++i) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj config_log_state *cls = &clsarray[i];
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj config_log_transaction(r, cls, mls->default_format);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener return OK;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener}
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem/*****************************************************************
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem *
8869662bb1a4078297020e94ae5e928626d877c6rederpj * Module glue...
8869662bb1a4078297020e94ae5e928626d877c6rederpj */
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpjstatic void *make_config_log_state(apr_pool_t *p, server_rec *s)
8869662bb1a4078297020e94ae5e928626d877c6rederpj{
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem multi_log_state *mls;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem mls = (multi_log_state *) apr_palloc(p, sizeof(multi_log_state));
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener mls->config_logs = apr_array_make(p, 1, sizeof(config_log_state));
8869662bb1a4078297020e94ae5e928626d877c6rederpj mls->default_format_string = NULL;
8869662bb1a4078297020e94ae5e928626d877c6rederpj mls->default_format = NULL;
8869662bb1a4078297020e94ae5e928626d877c6rederpj mls->server_config_logs = NULL;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener mls->formats = apr_table_make(p, 4);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener apr_table_setn(mls->formats, "CLF", DEFAULT_LOG_FORMAT);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener return mls;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener}
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj/*
8869662bb1a4078297020e94ae5e928626d877c6rederpj * Use the merger to simply add a pointer from the vhost log state
8869662bb1a4078297020e94ae5e928626d877c6rederpj * to the log of logs specified for the non-vhost configuration. Make sure
8869662bb1a4078297020e94ae5e928626d877c6rederpj * vhosts inherit any globally-defined format names.
8869662bb1a4078297020e94ae5e928626d877c6rederpj */
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpjstatic void *merge_config_log_state(apr_pool_t *p, void *basev, void *addv)
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf{
6733d943c9e8d0f27dd077a04037e8c49eb090ffcovener multi_log_state *base = (multi_log_state *) basev;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem multi_log_state *add = (multi_log_state *) addv;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8869662bb1a4078297020e94ae5e928626d877c6rederpj add->server_config_logs = base->config_logs;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener if (!add->default_format) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj add->default_format_string = base->default_format_string;
8869662bb1a4078297020e94ae5e928626d877c6rederpj add->default_format = base->default_format;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf add->formats = apr_table_overlay(p, base->formats, add->formats);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf return add;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf}
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf/*
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener * Set the default logfile format, or define a nickname for a format string.
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sfstatic const char *log_format(cmd_parms *cmd, void *dummy, const char *fmt,
8869662bb1a4078297020e94ae5e928626d877c6rederpj const char *name)
8869662bb1a4078297020e94ae5e928626d877c6rederpj{
8869662bb1a4078297020e94ae5e928626d877c6rederpj const char *err_string = NULL;
8869662bb1a4078297020e94ae5e928626d877c6rederpj multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
8869662bb1a4078297020e94ae5e928626d877c6rederpj &log_config_module);
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /*
8869662bb1a4078297020e94ae5e928626d877c6rederpj * If we were given two arguments, the second is a name to be given to the
8869662bb1a4078297020e94ae5e928626d877c6rederpj * format. This syntax just defines the nickname - it doesn't actually
8869662bb1a4078297020e94ae5e928626d877c6rederpj * make the format the default.
8869662bb1a4078297020e94ae5e928626d877c6rederpj */
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (name != NULL) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj parse_log_string(cmd->pool, fmt, &err_string);
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (err_string == NULL) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj apr_table_setn(mls->formats, name, fmt);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj else {
8869662bb1a4078297020e94ae5e928626d877c6rederpj mls->default_format_string = fmt;
8869662bb1a4078297020e94ae5e928626d877c6rederpj mls->default_format = parse_log_string(cmd->pool, fmt, &err_string);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj return err_string;
8869662bb1a4078297020e94ae5e928626d877c6rederpj}
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemstatic const char *add_custom_log(cmd_parms *cmd, void *dummy, const char *fn,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem const char *fmt, const char *envclause)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem{
8869662bb1a4078297020e94ae5e928626d877c6rederpj const char *err_string = NULL;
8869662bb1a4078297020e94ae5e928626d877c6rederpj multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
8869662bb1a4078297020e94ae5e928626d877c6rederpj &log_config_module);
8869662bb1a4078297020e94ae5e928626d877c6rederpj config_log_state *cls;
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem cls = (config_log_state *) apr_array_push(mls->config_logs);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem cls->condition_var = NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem cls->condition_expr = NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (envclause != NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (strncasecmp(envclause, "env=", 4) == 0) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if ((envclause[4] == '\0')
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem || ((envclause[4] == '!') && (envclause[5] == '\0'))) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj return "missing environment variable name";
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj cls->condition_var = apr_pstrdup(cmd->pool, &envclause[4]);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj else if (strncasecmp(envclause, "expr=", 5) == 0) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj const char *err;
8869662bb1a4078297020e94ae5e928626d877c6rederpj if ((envclause[5] == '\0'))
8869662bb1a4078297020e94ae5e928626d877c6rederpj return "missing condition";
8869662bb1a4078297020e94ae5e928626d877c6rederpj cls->condition_expr = ap_expr_parse_cmd(cmd, &envclause[5], &err,
8869662bb1a4078297020e94ae5e928626d877c6rederpj NULL);
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (err)
8869662bb1a4078297020e94ae5e928626d877c6rederpj return err;
8869662bb1a4078297020e94ae5e928626d877c6rederpj cls->condition_expr->module_index = APLOG_MODULE_INDEX;
8869662bb1a4078297020e94ae5e928626d877c6rederpj cls->condition_expr->flags |= AP_EXPR_FLAGS_DONT_VARY;
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj else {
8869662bb1a4078297020e94ae5e928626d877c6rederpj return "error in condition clause";
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj cls->fname = fn;
8869662bb1a4078297020e94ae5e928626d877c6rederpj cls->format_string = fmt;
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (fmt == NULL) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj cls->format = NULL;
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem else {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem cls->format = parse_log_string(cmd->pool, fmt, &err_string);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj cls->log_writer = NULL;
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj return err_string;
8869662bb1a4078297020e94ae5e928626d877c6rederpj}
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpjstatic const char *set_transfer_log(cmd_parms *cmd, void *dummy,
8869662bb1a4078297020e94ae5e928626d877c6rederpj const char *fn)
8869662bb1a4078297020e94ae5e928626d877c6rederpj{
8869662bb1a4078297020e94ae5e928626d877c6rederpj return add_custom_log(cmd, dummy, fn, NULL, NULL);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj}
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemstatic const char *set_cookie_log(cmd_parms *cmd, void *dummy, const char *fn)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem{
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t", NULL);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem}
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpjstatic const char *set_buffered_logs_on(cmd_parms *parms, void *dummy, int flag)
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj{
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem buffered_logs = flag;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (buffered_logs) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_log_set_writer_init(ap_buffered_log_writer_init);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_log_set_writer(ap_buffered_log_writer);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem}
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemstatic const command_rec config_log_cmds[] =
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem{
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemAP_INIT_TAKE23("CustomLog", add_custom_log, NULL, RSRC_CONF,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "a file name, a custom log format string or format name, "
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "and an optional \"env=\" or \"expr=\" clause (see docs)"),
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemAP_INIT_TAKE1("TransferLog", set_transfer_log, NULL, RSRC_CONF,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "the filename of the access log"),
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemAP_INIT_TAKE12("LogFormat", log_format, NULL, RSRC_CONF,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "a log format string (see docs) and an optional format name"),
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemAP_INIT_TAKE1("CookieLog", set_cookie_log, NULL, RSRC_CONF,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "the filename of the cookie log"),
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemAP_INIT_FLAG("BufferedLogs", set_buffered_logs_on, NULL, RSRC_CONF,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "Enable Buffered Logging (experimental)"),
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem {NULL}
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem};
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemstatic config_log_state *open_config_log(server_rec *s, apr_pool_t *p,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem config_log_state *cls,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem apr_array_header_t *default_format)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem{
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (cls->log_writer != NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return cls; /* virtual config shared w/main server */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (cls->fname == NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return cls; /* Leave it NULL to decline. */
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj }
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem cls->log_writer = log_writer_init(p, s, cls->fname);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (cls->log_writer == NULL)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj return cls;
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj}
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj
11ca38a20ab9b2d00258f745620e2724838e7e21rederpjstatic int open_multi_logs(server_rec *s, apr_pool_t *p)
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj{
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj int i;
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj multi_log_state *mls = ap_get_module_config(s->module_config,
0e05808dc59a321566303084c84b9826a4353cefrederpj &log_config_module);
a9c4332dc6241dc11dd104826bd179d42ccc0f12fuankg config_log_state *clsarray;
a9c4332dc6241dc11dd104826bd179d42ccc0f12fuankg const char *dummy;
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj const char *format;
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj if (mls->default_format_string) {
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj format = apr_table_get(mls->formats, mls->default_format_string);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (format) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem mls->default_format = parse_log_string(p, format, &dummy);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (!mls->default_format) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem mls->default_format = parse_log_string(p, DEFAULT_LOG_FORMAT, &dummy);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if (mls->config_logs->nelts) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj clsarray = (config_log_state *) mls->config_logs->elts;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj for (i = 0; i < mls->config_logs->nelts; ++i) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj config_log_state *cls = &clsarray[i];
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (cls->format_string) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem format = apr_table_get(mls->formats, cls->format_string);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (format) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem cls->format = parse_log_string(p, format, &dummy);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj if (!open_config_log(s, p, cls, mls->default_format)) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* Failure already logged by open_config_log */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj return DONE;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj else if (mls->server_config_logs) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj clsarray = (config_log_state *) mls->server_config_logs->elts;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj for (i = 0; i < mls->server_config_logs->nelts; ++i) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj config_log_state *cls = &clsarray[i];
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (cls->format_string) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem format = apr_table_get(mls->formats, cls->format_string);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (format) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj cls->format = parse_log_string(p, format, &dummy);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj if (!open_config_log(s, p, cls, mls->default_format)) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* Failure already logged by open_config_log */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj return DONE;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj return OK;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj}
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpjstatic apr_status_t flush_all_logs(void *data)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem{
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem server_rec *s = data;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj multi_log_state *mls;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj apr_array_header_t *log_list;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem config_log_state *clsarray;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem buffered_log *buf;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem int i;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
0e05808dc59a321566303084c84b9826a4353cefrederpj if (!buffered_logs)
0e05808dc59a321566303084c84b9826a4353cefrederpj return APR_SUCCESS;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj for (; s; s = s->next) {
0e05808dc59a321566303084c84b9826a4353cefrederpj mls = ap_get_module_config(s->module_config, &log_config_module);
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf log_list = NULL;
0e05808dc59a321566303084c84b9826a4353cefrederpj if (mls->config_logs->nelts) {
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf log_list = mls->config_logs;
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj else if (mls->server_config_logs) {
0e05808dc59a321566303084c84b9826a4353cefrederpj log_list = mls->server_config_logs;
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj if (log_list) {
0e05808dc59a321566303084c84b9826a4353cefrederpj clsarray = (config_log_state *) log_list->elts;
0e05808dc59a321566303084c84b9826a4353cefrederpj for (i = 0; i < log_list->nelts; ++i) {
0e05808dc59a321566303084c84b9826a4353cefrederpj buf = clsarray[i].log_writer;
0e05808dc59a321566303084c84b9826a4353cefrederpj flush_log(buf);
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj return APR_SUCCESS;
0e05808dc59a321566303084c84b9826a4353cefrederpj}
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpjstatic int init_config_log(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_rec *s)
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj{
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj int res;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /* First init the buffered logs array, which is needed when opening the logs. */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if (buffered_logs) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem all_buffered_logs = apr_array_make(p, 5, sizeof(buffered_log *));
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* Next, do "physical" server, which gets default log fd and format
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * for the virtual servers, if they don't override...
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj */
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf res = open_multi_logs(s, p);
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* Then, virtual servers */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj for (s = s->next; (res == OK) && s; s = s->next) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem res = open_multi_logs(s, p);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj return res;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj}
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpjstatic void init_child(apr_pool_t *p, server_rec *s)
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj{
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj int mpm_threads;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj ap_mpm_query(AP_MPMQ_MAX_THREADS, &mpm_threads);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* Now register the last buffer flush with the cleanup engine */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (buffered_logs) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj int i;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj buffered_log **array = (buffered_log **)all_buffered_logs->elts;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
0e05808dc59a321566303084c84b9826a4353cefrederpj apr_pool_cleanup_register(p, s, flush_all_logs, flush_all_logs);
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj for (i = 0; i < all_buffered_logs->nelts; i++) {
0e05808dc59a321566303084c84b9826a4353cefrederpj buffered_log *this = array[i];
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
0e05808dc59a321566303084c84b9826a4353cefrederpj#if APR_HAS_THREADS
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf if (mpm_threads > 1) {
0e05808dc59a321566303084c84b9826a4353cefrederpj apr_status_t rv;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj this->mutex.type = apr_anylock_threadmutex;
0e05808dc59a321566303084c84b9826a4353cefrederpj rv = apr_thread_mutex_create(&this->mutex.lock.tm,
0e05808dc59a321566303084c84b9826a4353cefrederpj APR_THREAD_MUTEX_DEFAULT,
0e05808dc59a321566303084c84b9826a4353cefrederpj p);
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf if (rv != APR_SUCCESS) {
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf "could not initialize buffered log mutex, "
0e05808dc59a321566303084c84b9826a4353cefrederpj "transfer log may become corrupted");
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj this->mutex.type = apr_anylock_none;
0e05808dc59a321566303084c84b9826a4353cefrederpj }
40a1aee60a66f7c8dbd0835fdd4f09334e12fc15rpluem }
0e05808dc59a321566303084c84b9826a4353cefrederpj else
0e05808dc59a321566303084c84b9826a4353cefrederpj#endif
40a1aee60a66f7c8dbd0835fdd4f09334e12fc15rpluem {
0e05808dc59a321566303084c84b9826a4353cefrederpj this->mutex.type = apr_anylock_none;
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj}
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpjstatic void ap_register_log_handler(apr_pool_t *p, char *tag,
0e05808dc59a321566303084c84b9826a4353cefrederpj ap_log_handler_fn_t *handler, int def)
0e05808dc59a321566303084c84b9826a4353cefrederpj{
0e05808dc59a321566303084c84b9826a4353cefrederpj ap_log_handler *log_struct = apr_palloc(p, sizeof(*log_struct));
0e05808dc59a321566303084c84b9826a4353cefrederpj log_struct->func = handler;
0e05808dc59a321566303084c84b9826a4353cefrederpj log_struct->want_orig_default = def;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj apr_hash_set(log_hash, tag, 1, (const void *)log_struct);
0e05808dc59a321566303084c84b9826a4353cefrederpj}
0e05808dc59a321566303084c84b9826a4353cefrederpjstatic ap_log_writer_init* ap_log_set_writer_init(ap_log_writer_init *handle)
0e05808dc59a321566303084c84b9826a4353cefrederpj{
0e05808dc59a321566303084c84b9826a4353cefrederpj ap_log_writer_init *old = log_writer_init;
0e05808dc59a321566303084c84b9826a4353cefrederpj log_writer_init = handle;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj return old;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj}
0e05808dc59a321566303084c84b9826a4353cefrederpjstatic ap_log_writer *ap_log_set_writer(ap_log_writer *handle)
0e05808dc59a321566303084c84b9826a4353cefrederpj{
0e05808dc59a321566303084c84b9826a4353cefrederpj ap_log_writer *old = log_writer;
0e05808dc59a321566303084c84b9826a4353cefrederpj log_writer = handle;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj return old;
0e05808dc59a321566303084c84b9826a4353cefrederpj}
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpjstatic apr_status_t ap_default_log_writer( request_rec *r,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem void *handle,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem const char **strs,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem int *strl,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem int nelts,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem apr_size_t len)
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj{
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj char *str;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj char *s;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj int i;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj apr_status_t rv;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj str = apr_palloc(r->pool, len + 1);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem for (i = 0, s = str; i < nelts; ++i) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem memcpy(s, strs[i], strl[i]);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem s += strl[i];
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem rv = apr_file_write((apr_file_t*)handle, str, &len);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return rv;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem}
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sfstatic void *ap_default_log_writer_init(apr_pool_t *p, server_rec *s,
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf const char* name)
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf{
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf if (*name == '|') {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj piped_log *pl;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem pl = ap_open_piped_log(p, name + 1);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (pl == NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return NULL;;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf return ap_piped_log_write_fd(pl);
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf }
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf else {
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf const char *fname = ap_server_root_relative(p, name);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj apr_file_t *fd;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem apr_status_t rv;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (!fname) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_log_error(APLOG_MARK, APLOG_ERR, APR_EBADPATH, s,
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj "invalid transfer log path %s.", name);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj return NULL;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj rv = apr_file_open(&fd, fname, xfer_flags, xfer_perms, p);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj if (rv != APR_SUCCESS) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj "could not open transfer log file %s.", fname);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj return NULL;
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe }
e8f95a682820a599fe41b22977010636be5c2717jim return fd;
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe }
e8f95a682820a599fe41b22977010636be5c2717jim}
8113dac419143273351446c3ad653f3fe5ba5cfdwrowestatic void *ap_buffered_log_writer_init(apr_pool_t *p, server_rec *s,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char* name)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
8bdea88407c848c1c2693655e2f8b23abde12307bnicholes buffered_log *b;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes b = apr_pcalloc(p, sizeof(buffered_log));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes b->handle = ap_default_log_writer_init(p, s, name);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (b->handle) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *(buffered_log **)apr_array_push(all_buffered_logs) = b;
f05787953018140838ad51456c86c965d6a86267jim return b;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
f05787953018140838ad51456c86c965d6a86267jim else
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t ap_buffered_log_writer(request_rec *r,
e8f95a682820a599fe41b22977010636be5c2717jim void *handle,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char **strs,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int *strl,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int nelts,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t len)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
e8f95a682820a599fe41b22977010636be5c2717jim char *str;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe char *s;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int i;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_status_t rv;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes buffered_log *buf = (buffered_log*)handle;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((rv = APR_ANYLOCK_LOCK(&buf->mutex)) != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return rv;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim if (len + buf->outcnt > LOG_BUFSIZE) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe flush_log(buf);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim if (len >= LOG_BUFSIZE) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t w;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim str = apr_palloc(r->pool, len + 1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (i = 0, s = str; i < nelts; ++i) {
e8f95a682820a599fe41b22977010636be5c2717jim memcpy(s, strs[i], strl[i]);
e8f95a682820a599fe41b22977010636be5c2717jim s += strl[i];
e8f95a682820a599fe41b22977010636be5c2717jim }
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe w = len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = apr_file_write(buf->handle, str, &w);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (i = 0, s = &buf->outbuf[buf->outcnt]; i < nelts; ++i) {
e8f95a682820a599fe41b22977010636be5c2717jim memcpy(s, strs[i], strl[i]);
e8f95a682820a599fe41b22977010636be5c2717jim s += strl[i];
e8f95a682820a599fe41b22977010636be5c2717jim }
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe buf->outcnt += len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = APR_SUCCESS;
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener }
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener APR_ANYLOCK_UNLOCK(&buf->mutex);
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener return rv;
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener}
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covenerstatic int log_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_pfn_register;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_log_handler);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (log_pfn_register) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "h", log_remote_host, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "a", log_remote_address, 0 );
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "A", log_local_address, 0 );
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "l", log_remote_logname, 0);
e8f95a682820a599fe41b22977010636be5c2717jim log_pfn_register(p, "u", log_remote_user, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "t", log_request_time, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "f", log_request_file, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "b", clf_log_bytes_sent, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "B", log_bytes_sent, 0);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe log_pfn_register(p, "i", log_header_in, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "o", log_header_out, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "n", log_note, 0);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener log_pfn_register(p, "L", log_log_id, 1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "e", log_env_var, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "V", log_server_name, 0);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener log_pfn_register(p, "v", log_virtual_host, 0);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener log_pfn_register(p, "p", log_server_port, 0);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener log_pfn_register(p, "P", log_pid_tid, 0);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener log_pfn_register(p, "H", log_request_protocol, 0);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener log_pfn_register(p, "m", log_request_method, 0);
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes log_pfn_register(p, "q", log_request_query, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "X", log_connection_status, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "C", log_cookie, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "k", log_requests_on_connection, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes log_pfn_register(p, "r", log_request_line, 1);
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener log_pfn_register(p, "D", log_request_duration_microseconds, 1);
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener log_pfn_register(p, "T", log_request_duration, 1);
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener log_pfn_register(p, "U", log_request_uri, 1);
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf log_pfn_register(p, "s", log_status, 1);
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener log_pfn_register(p, "R", log_handler, 1);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes return OK;
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void register_hooks(apr_pool_t *p)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_pre_config(log_pre_config,NULL,NULL,APR_HOOK_REALLY_FIRST);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_child_init(init_child,NULL,NULL,APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_open_logs(init_config_log,NULL,NULL,APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_hook_log_transaction(multi_log_transaction,NULL,NULL,APR_HOOK_MIDDLE);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Init log_hash before we register the optional function. It is
e8f95a682820a599fe41b22977010636be5c2717jim * possible for the optional function, ap_register_log_handler,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * to be called before any other mod_log_config hooks are called.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * As a policy, we should init everything required by an optional function
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * before calling APR_REGISTER_OPTIONAL_FN.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
e8f95a682820a599fe41b22977010636be5c2717jim log_hash = apr_hash_make(p);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes APR_REGISTER_OPTIONAL_FN(ap_register_log_handler);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes APR_REGISTER_OPTIONAL_FN(ap_log_set_writer_init);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes APR_REGISTER_OPTIONAL_FN(ap_log_set_writer);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwroweAP_DECLARE_MODULE(log_config) =
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes STANDARD20_MODULE_STUFF,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NULL, /* create per-dir config */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes NULL, /* merge per-dir config */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes make_config_log_state, /* server config */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes merge_config_log_state, /* merge server config */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes config_log_cmds, /* command apr_table_t */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes register_hooks /* register hooks */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes