log.c revision 48d7c43629323c8d5ee9f7bd0d194de0a376b391
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * The Apache Software License, Version 1.1
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 2000 The Apache Software Foundation. All rights
842ae4bd224140319ae7feec1872b93dfd491143fielding * reserved.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Redistribution and use in source and binary forms, with or without
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * modification, are permitted provided that the following conditions
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 1. Redistributions of source code must retain the above copyright
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * notice, this list of conditions and the following disclaimer.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 2. Redistributions in binary form must reproduce the above copyright
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * notice, this list of conditions and the following disclaimer in
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * the documentation and/or other materials provided with the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * distribution.
e8f95a682820a599fe41b22977010636be5c2717jim * 3. The end-user documentation included with the redistribution,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * if any, must include the following acknowledgment:
e8f95a682820a599fe41b22977010636be5c2717jim * "This product includes software developed by the
1747d30b98aa1bdbc43994c02cd46ab4cb9319e4fielding * Apache Software Foundation (http://www.apache.org/)."
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Alternately, this acknowledgment may appear in the software itself,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * if and wherever such third-party acknowledgments normally appear.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 4. The names "Apache" and "Apache Software Foundation" must
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * not be used to endorse or promote products derived from this
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * software without prior written permission. For written
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * permission, please contact apache@apache.org.
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * 5. Products derived from this software may not be called "Apache",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * nor may "Apache" appear in their name, without prior written
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * permission of the Apache Software Foundation.
5c0419d51818eb02045cf923a9fe456127a44c60wrowe * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
5c0419d51818eb02045cf923a9fe456127a44c60wrowe * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
cd3bbd6d2df78d6c75e5d159a81ef8bdd5f70df9trawick * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * SUCH DAMAGE.
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * ====================================================================
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * This software consists of voluntary contributions made by many
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * individuals on behalf of the Apache Software Foundation. For more
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * information on the Apache Software Foundation, please see
0f60998368b493f90120180a93fc2e1e74490872covener * Portions of this software are based upon public domain software
0f60998368b493f90120180a93fc2e1e74490872covener * originally written at the National Center for Supercomputing Applications,
0f60998368b493f90120180a93fc2e1e74490872covener * University of Illinois, Urbana-Champaign.
0f60998368b493f90120180a93fc2e1e74490872covener * http_log.c: Dealing with the logs and errors
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * Rob McCool
0568280364eb026393be492ebc732795c4934643jortontypedef struct {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic int log_child(ap_pool_t *p, const char *progname,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Child process code for 'ErrorLog "|..."';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * may want a common framework for this, since I expect it will
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * be common for other foo-loggers to want this sort of thing...
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* No concept of a child process on Win32 */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#endif /* ndef SIGHUP */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((ap_createprocattr_init(&procattr, p) != APR_SUCCESS) ||
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Something bad happened, give up and go away. */
cceddc0b6c0fdaed0c73abda39975bb1d388243acovener const char *pname;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener rc = ap_create_process(&procnew, pname, args, NULL, procattr, p);
60215f303c7e1ce8b6d272acb5bfa5b3d99dfd34covener ap_note_subprocess(p, &procnew, kill_after_timeout);
6683642c1e0032eeeed5f99e8c14880692ef84c5sf const char *fname;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* This starts a new process... */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener "Couldn't fork child for ErrorLog process");
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener else if (!strncasecmp(s->error_fname, "syslog", 6)) {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* Change to AP funcs. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes APR_READ | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, p) != APR_SUCCESS) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "%s: could not open error log file %s.",
55e2e59e5910072e51c870afc68b0907f41a28e0sf /* replace stderr with this new log */
55e2e59e5910072e51c870afc68b0907f41a28e0sf if ((rc = ap_dupfile(&errfile, s_main->error_log, NULL)) != APR_SUCCESS) {
55e2e59e5910072e51c870afc68b0907f41a28e0sf "unable to replace stderr with error_log");
55e2e59e5910072e51c870afc68b0907f41a28e0sf /* note that stderr may still need to be replaced with something
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * because it points to the old error log, or back to the tty
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * of the submitter.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (replace_stderr && freopen("/dev/null", "w", stderr) == NULL) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ap_log_error(APLOG_MARK, APLOG_CRIT, errno, s_main,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "unable to replace stderr with /dev/null");
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes for (virt = s_main->next; virt; virt = virt->next) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ap_dupfile(&(s->error_log), errfile, s->process->pool);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic void log_error_core(const char *file, int line, int level,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char errstr[MAX_STRING_LEN + 1]; /* + 1 to have room for '\n' */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener if (s == NULL) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * If we are doing stderr logging (startup), don't log messages that are
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * above the default server log level unless it is a startup/shutdown
54d22ed1c429b903b029bbd62621f11a9e286137minfrin else if (s->error_log) {
55e2e59e5910072e51c870afc68b0907f41a28e0sf * If we are doing normal logging, don't log messages that are
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * above the server log level unless it is a startup/shutdown notice
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (((level & APLOG_LEVELMASK) != APLOG_NOTICE) &&
55e2e59e5910072e51c870afc68b0907f41a28e0sf * If we are doing normal logging, don't log messages that are
55e2e59e5910072e51c870afc68b0907f41a28e0sf * above the server log level unless it is a startup/shutdown notice
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes#endif /* TPF */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * If we are doing syslog logging, don't log messages that are
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * above the server log level (including a startup/shutdown notice)
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim if (logf && ((level & APLOG_STARTUP) != APLOG_STARTUP)) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener "[%s] ", priorities[level & APLOG_LEVELMASK].t_name);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener if (file && (level & APLOG_LEVELMASK) == APLOG_DEBUG) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener /* In OSD/POSIX, the compiler returns for __FILE__
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * a string like: __FILE__="*POSIX(/usr/include/stdio.h)"
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * (it even returns an absolute path for sources in
185aa71728867671e105178b4c66fbc22b65ae26sf * the current directory). Here we try to strip this
707f6d077f73cc948deead8df5b40ea42c1eaa78covener * down to the basename.
707f6d077f73cc948deead8df5b40ea42c1eaa78covener if (*e == ')')
707f6d077f73cc948deead8df5b40ea42c1eaa78covener#endif /*_OSD_POSIX*/
707f6d077f73cc948deead8df5b40ea42c1eaa78covener len += ap_snprintf(errstr + len, MAX_STRING_LEN - len,
707f6d077f73cc948deead8df5b40ea42c1eaa78covener#endif /* TPF */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener if (r && r->connection) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener /* XXX: TODO: add a method of selecting whether logged client
9ad7b260be233be7d7b5576979825cac72e15498rederpj * addresses are in dotted quad or resolved form... dotted
9ad7b260be233be7d7b5576979825cac72e15498rederpj * quad is the most secure, which is why I'm implementing it
9ad7b260be233be7d7b5576979825cac72e15498rederpj * first. -djg
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf && (status != 0)) {
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf "(%d)%s: ", status, ap_strerror(status, buf, sizeof(buf)));
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf len += ap_vsnprintf(errstr + len, MAX_STRING_LEN - len, fmt, args);
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf /* NULL if we are logging to syslog */
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf /* We know that we have one more character of space available because
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf * the array is sized that way */
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf /* ap_assert(len < MAX_STRING_LEN) */
e8f95a682820a599fe41b22977010636be5c2717jimAPI_EXPORT(void) ap_log_error(const char *file, int line, int level,
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf const char *fmt, ...)
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes log_error_core(file, line, level, status, s, NULL, NULL, fmt, args);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sfAPI_EXPORT(void) ap_log_perror(const char *file, int line, int level,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf const char *fmt, ...)
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf log_error_core(file, line, level, status, NULL, NULL, p, fmt, args);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sfAPI_EXPORT(void) ap_log_rerror(const char *file, int line, int level,
185aa71728867671e105178b4c66fbc22b65ae26sf const char *fmt, ...)
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf log_error_core(file, line, level, status, r->server, r, NULL, fmt, args);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * IF the error level is 'warning' or more severe,
e8f95a682820a599fe41b22977010636be5c2717jim * AND there isn't already error text associated with this request,
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * THEN make the message text available to ErrorDocument and
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim * other error processors. This can be disabled by stuffing
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener * something, even an empty string, into the "error-notes" cell
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener * before calling this routine.
96ebb616bbf4ac2a422cc5d9770c9ad07ccecdc0covener && (ap_table_get(r->notes, "error-notes") == NULL)) {
7dbf29be626018bc389ef94c1846aeac4b72633bsf if (mypid != saved_pid && ap_stat(&finfo, fname, p) == APR_SUCCESS) {
7dbf29be626018bc389ef94c1846aeac4b72633bsf /* WINCH and HUP call this on each restart.
7dbf29be626018bc389ef94c1846aeac4b72633bsf * Only warn on first time through for this pid.
783874b86bfe13d7a4fe0922f344a3779cdccea3covener * XXX: Could just write first time through too, although
7dbf29be626018bc389ef94c1846aeac4b72633bsf * that may screw up scripts written to do something
7dbf29be626018bc389ef94c1846aeac4b72633bsf * based on the last modification time of the pid file.
7dbf29be626018bc389ef94c1846aeac4b72633bsf ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
7dbf29be626018bc389ef94c1846aeac4b72633bsf "pid file %s overwritten -- Unclean shutdown of previous Apache run?",
7dbf29be626018bc389ef94c1846aeac4b72633bsf if ((rv = ap_open(&pid_file, fname, APR_WRITE | APR_CREATE | APR_TRUNCATE,
7dbf29be626018bc389ef94c1846aeac4b72633bsf APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD, p)) != APR_SUCCESS) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, NULL,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "%s: could not log pid to file %s",
4be9c459920a7c1cfe62d654327dae5c4bb6b284sfAPI_EXPORT(void) ap_log_error_old(const char *err, server_rec *s)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "%s", err);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesAPI_EXPORT(void) ap_log_unixerr(const char *routine, const char *file,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ap_log_error(file, 0, APLOG_ERR, errno, s, "%s", msg);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesAPI_EXPORT(void) ap_log_printf(const server_rec *s, const char *fmt, ...)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes log_error_core(APLOG_MARK, APLOG_ERR, errno, s, NULL, NULL, fmt, args);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesAPI_EXPORT(void) ap_log_reason(const char *reason, const char *file, request_rec *r)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ap_log_error(APLOG_MARK, APLOG_ERR, errno, r->server,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes "access to %s failed for %s, reason: %s",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME),
4be9c459920a7c1cfe62d654327dae5c4bb6b284sfAPI_EXPORT(void) ap_log_assert(const char *szExp, const char *szFile, int nLine)
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf "[%s] file %s, line %d, assertion \"%s\" failed",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* unix assert does an abort leading to a core dump */
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener/* piped log support */
7dbf29be626018bc389ef94c1846aeac4b72633bsf/* forward declaration */
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covenerstatic void piped_log_maintenance(int reason, void *data, ap_wait_t status);
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener if (((status = ap_createprocattr_init(&procattr, pl->p)) != APR_SUCCESS) ||
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim ((status = ap_setprocattr_childin(procattr, ap_piped_log_read_fd(pl),
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /* Something bad happened, give up and go away. */
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener "piped_log_spawn: unable to setup child process '%s': %s",
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener pl->program, ap_strerror(status, buf, sizeof(buf)));
60d81cab99dccfbb0c8d378cf6aa7338be0fdb74covener const char *pname;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf rc = ap_create_process(&procnew, pname, args, NULL, procattr, pl->p);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* pjr - This no longer happens inside the child, */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* I am assuming that if ap_create_process was */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* successful that the child is running. */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf ap_register_other_child(&procnew, piped_log_maintenance, pl,
54d22ed1c429b903b029bbd62621f11a9e286137minfrinstatic void piped_log_maintenance(int reason, void *data, ap_wait_t status)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* during a restart */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* during a restart */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* what can we do? This could be the error log we're having
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * problems opening up... */
ab86c68ce36c715e93f403dde41d0b9c1522c8b0sf ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "piped_log_maintenance: unable to respawn '%s': %s",
9ad7b260be233be7d7b5576979825cac72e15498rederpjstatic ap_status_t piped_log_cleanup_for_exec(void *data)
560fd0658902ab57754616c172d8953e69fc4722bnicholesAPI_EXPORT(piped_log *) ap_open_piped_log(ap_pool_t *p, const char *program)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (ap_create_pipe(&ap_piped_log_read_fd(pl), &ap_piped_log_write_fd(pl), p) != APR_SUCCESS) {
e8f95a682820a599fe41b22977010636be5c2717jim ap_register_cleanup(p, pl, piped_log_cleanup, piped_log_cleanup_for_exec);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesAPI_EXPORT(piped_log *) ap_open_piped_log(ap_pool_t *p, const char *program)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Couldn't fork child for piped log process");