log.c revision b0f20a4a26bcfa85724b1c2e5ec6a077f12ef44c
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/* ====================================================================
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Copyright (c) 1995-1999 The Apache Group. All rights reserved.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Redistribution and use in source and binary forms, with or without
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * modification, are permitted provided that the following conditions
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 1. Redistributions of source code must retain the above copyright
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * notice, this list of conditions and the following disclaimer.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 2. Redistributions in binary form must reproduce the above copyright
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * notice, this list of conditions and the following disclaimer in
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * the documentation and/or other materials provided with the
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * distribution.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 3. All advertising materials mentioning features or use of this
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * software must display the following acknowledgment:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * "This product includes software developed by the Apache Group
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * for use in the Apache HTTP server project (http://www.apache.org/)."
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 4. The names "Apache Server" and "Apache Group" must not be used to
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * endorse or promote products derived from this software without
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * prior written permission. For written permission, please contact
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * apache@apache.org.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 5. Products derived from this software may not be called "Apache"
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * nor may "Apache" appear in their names without prior written
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * permission of the Apache Group.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 6. Redistributions of any form whatsoever must retain the following
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * acknowledgment:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * "This product includes software developed by the Apache Group
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * for use in the Apache HTTP server project (http://www.apache.org/)."
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * OF THE POSSIBILITY OF SUCH DAMAGE.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * ====================================================================
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * This software consists of voluntary contributions made by many
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * individuals on behalf of the Apache Group and was originally based
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * on public domain software written at the National Center for
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Supercomputing Applications, University of Illinois, Urbana-Champaign.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * For more information on the Apache Group and the Apache HTTP server
f4c310fd2555c6faca1f980f00b161eadb089023gstein * project, please see <http://www.apache.org/>.
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein * http_log.c: Dealing with the logs and errors
8a46775d163c06a8c51d1b0a3f2edfde945cb1d8stoddard * Rob McCool
f4c310fd2555c6faca1f980f00b161eadb089023gsteintypedef struct {
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int log_child(ap_context_t *p, const char *progname,
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein /* Child process code for 'ErrorLog "|..."';
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein * may want a common framework for this, since I expect it will
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein * be common for other foo-loggers to want this sort of thing...
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein /* No concept of a child process on Win32 */
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein#endif /* ndef SIGHUP */
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein if ((ap_createprocattr_init(&procattr, p) != APR_SUCCESS) ||
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein (ap_setprocattr_dir(procattr, progname) != APR_SUCCESS)) {
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein /* Something bad happened, give up and go away. */
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein rc = ap_create_process(&procnew, progname, NULL, NULL, procattr, p);
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gsteinstatic void open_error_log(server_rec *s, ap_context_t *p)
0e8fe062a6ec71b4207d1a125ee6b44b7fd30857gstein const char *fname;
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This starts a new process... */
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein "Couldn't fork child for ErrorLog process");
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (!strncasecmp(s->error_fname, "syslog", 6)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID,
f4c310fd2555c6faca1f980f00b161eadb089023gstein openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Change to AP funcs. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein APR_READ | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, p) != APR_SUCCESS) {
49bf4df23d9e5281abcd83005550bda818b17b08wrowe ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "%s: could not open error log file %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gsteinvoid ap_open_logs(server_rec *s_main, ap_context_t *p)
53dafcfda483886730db8e57bf6f94cff36f0047stoddard /* replace stderr with this new log */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (ap_dupfile(&errfile, s_main->error_log) != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein "unable to replace stderr with error_log");
f71d4ec448449837beefe21cf7c9f8d9b6bd4654gstein /* note that stderr may still need to be replaced with something
f71d4ec448449837beefe21cf7c9f8d9b6bd4654gstein * because it points to the old error log, or back to the tty
f4c310fd2555c6faca1f980f00b161eadb089023gstein * of the submitter.
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (replace_stderr && freopen("/dev/null", "w", stderr) == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein "unable to replace stderr with /dev/null");
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void log_error_core(const char *file, int line, int level,
f4c310fd2555c6faca1f980f00b161eadb089023gstein char errstr[MAX_STRING_LEN + 1]; /* + 1 to have room for '\n' */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if (s == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein * If we are doing stderr logging (startup), don't log messages that are
f4c310fd2555c6faca1f980f00b161eadb089023gstein * above the default server log level unless it is a startup/shutdown
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm else if (s->error_log) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * If we are doing normal logging, don't log messages that are
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * above the server log level unless it is a startup/shutdown notice
f4c310fd2555c6faca1f980f00b161eadb089023gstein * If we are doing normal logging, don't log messages that are
f4c310fd2555c6faca1f980f00b161eadb089023gstein * above the server log level unless it is a startup/shutdown notice
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm#endif /* TPF */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * If we are doing syslog logging, don't log messages that are
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * above the server log level (including a startup/shutdown notice)
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (logf && ((level & APLOG_STARTUP) != APLOG_STARTUP)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein len += ap_snprintf(errstr + len, MAX_STRING_LEN - len,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "[%s] ", priorities[level & APLOG_LEVELMASK].t_name);
1f6e6566a4ce31a0b95d5400c36d0aaff7a6e94agstein if (file && (level & APLOG_LEVELMASK) == APLOG_DEBUG) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* In OSD/POSIX, the compiler returns for __FILE__
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * a string like: __FILE__="*POSIX(/usr/include/stdio.h)"
f4c310fd2555c6faca1f980f00b161eadb089023gstein * (it even returns an absolute path for sources in
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the current directory). Here we try to strip this
f4c310fd2555c6faca1f980f00b161eadb089023gstein * down to the basename.
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*e == ')')
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /*_OSD_POSIX*/
f4c310fd2555c6faca1f980f00b161eadb089023gstein len += ap_snprintf(errstr + len, MAX_STRING_LEN - len,
f4c310fd2555c6faca1f980f00b161eadb089023gstein#endif /* TPF */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r && r->connection) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX: TODO: add a method of selecting whether logged client
f4c310fd2555c6faca1f980f00b161eadb089023gstein * addresses are in dotted quad or resolved form... dotted
f4c310fd2555c6faca1f980f00b161eadb089023gstein * quad is the most secure, which is why I'm implementing it
f4c310fd2555c6faca1f980f00b161eadb089023gstein * first. -djg
f4c310fd2555c6faca1f980f00b161eadb089023gstein len += ap_snprintf(errstr + len, MAX_STRING_LEN - len,
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* XXX - need an APRized strerror() */
f4c310fd2555c6faca1f980f00b161eadb089023gstein && (status != 0)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein len += ap_snprintf(errstr + len, MAX_STRING_LEN - len,
f4c310fd2555c6faca1f980f00b161eadb089023gstein len += ap_vsnprintf(errstr + len, MAX_STRING_LEN - len, fmt, args);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* NULL if we are logging to syslog */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* We know that we have one more character of space available because
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * the array is sized that way */
4c449c30215bd5e8bad122a4118f5a7b0e995472wrowe /* ap_assert(len < MAX_STRING_LEN) */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmAPI_EXPORT(void) ap_log_error(const char *file, int line, int level,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *fmt, ...)
33397e35239f202a595837571561468f02b2e806gstein log_error_core(file, line, level, status, s, NULL, fmt, args);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(void) ap_log_rerror(const char *file, int line, int level,
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *fmt, ...)
f4c310fd2555c6faca1f980f00b161eadb089023gstein log_error_core(file, line, level, status, r->server, r, fmt, args);
f4c310fd2555c6faca1f980f00b161eadb089023gstein * IF the error level is 'warning' or more severe,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * AND there isn't already error text associated with this request,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * THEN make the message text available to ErrorDocument and
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein * other error processors. This can be disabled by stuffing
f4c310fd2555c6faca1f980f00b161eadb089023gstein * something, even an empty string, into the "error-notes" cell
f4c310fd2555c6faca1f980f00b161eadb089023gstein * before calling this routine.
f4c310fd2555c6faca1f980f00b161eadb089023gstein && (ap_table_get(r->notes, "error-notes") == NULL)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (mypid != saved_pid && ap_stat(&finfo, fname, p) == APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* WINCH and HUP call this on each restart.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * Only warn on first time through for this pid.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * XXX: Could just write first time through too, although
f4c310fd2555c6faca1f980f00b161eadb089023gstein * that may screw up scripts written to do something
f4c310fd2555c6faca1f980f00b161eadb089023gstein * based on the last modification time of the pid file.
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "pid file %s overwritten -- Unclean shutdown of previous Apache run?",
f4c310fd2555c6faca1f980f00b161eadb089023gstein if(ap_open(&pid_file, fname, APR_WRITE | APR_CREATE, APR_OS_DEFAULT, p) != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "%s: could not log pid to file %s",
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(void) ap_log_error_old(const char *err, server_rec *s)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, errno, s, "%s", err);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(void) ap_log_unixerr(const char *routine, const char *file,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(file, 0, APLOG_ERR, errno, s, "%s", msg);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(void) ap_log_printf(const server_rec *s, const char *fmt, ...)
f4c310fd2555c6faca1f980f00b161eadb089023gstein log_error_core(APLOG_MARK, APLOG_ERR, errno, s, NULL, fmt, args);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(void) ap_log_reason(const char *reason, const char *file, request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_ERR, errno, r->server,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "access to %s failed for %s, reason: %s",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME),
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(void) ap_log_assert(const char *szExp, const char *szFile, int nLine)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "[%s] file %s, line %d, assertion \"%s\" failed",
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* unix assert does an abort leading to a core dump */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* piped log support */
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* forward declaration */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void piped_log_maintenance(int reason, void *data, ap_wait_t status);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* pjr - calls to block and unblock alarms weren't here before, was this */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* an oversight or intentional? */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/* ap_block_alarms(); */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((ap_createprocattr_init(&procattr, pl->p) != APR_SUCCESS) ||
f4c310fd2555c6faca1f980f00b161eadb089023gstein (ap_setprocattr_dir(procattr, pl->program) != APR_SUCCESS) ||
f4c310fd2555c6faca1f980f00b161eadb089023gstein (ap_set_childin(procattr, ap_piped_log_read_fd(pl), ap_piped_log_write_fd(pl)) != APR_SUCCESS)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Something bad happened, give up and go away. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "piped_log_spawn: unable to exec '%s': %s",
f4c310fd2555c6faca1f980f00b161eadb089023gstein rc = ap_create_process(&procnew, pl->program, NULL, NULL, procattr, pl->p);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (rc == APR_SUCCESS) { /* pjr - This no longer happens inside the child, */
f4c310fd2555c6faca1f980f00b161eadb089023gstein RAISE_SIGSTOP(PIPED_LOG_SPAWN); /* I am assuming that if ap_create_process was */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* successful that the child is running. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_register_other_child(pid, piped_log_maintenance, pl, ap_piped_log_write_fd(pl));
33397e35239f202a595837571561468f02b2e806gstein/* ap_unblock_alarms(); */
49bf4df23d9e5281abcd83005550bda818b17b08wrowestatic void piped_log_maintenance(int reason, void *data, ap_wait_t status)
ba2ad3b1bb4a729278ad8e8846d34ddd27b6551cgstein /* during a restart */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* what can we do? This could be the error log we're having
f4c310fd2555c6faca1f980f00b161eadb089023gstein * problems opening up... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "piped_log_maintenance: unable to respawn '%s': %s",
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic ap_status_t piped_log_cleanup_for_exec(void *data)
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(piped_log *) ap_open_piped_log(ap_context_t *p, const char *program)
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_create_pipe(&ap_piped_log_read_fd(pl), &ap_piped_log_write_fd(pl), p) != APR_SUCCESS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_register_cleanup(p, pl, piped_log_cleanup, piped_log_cleanup_for_exec);
f4c310fd2555c6faca1f980f00b161eadb089023gsteinAPI_EXPORT(piped_log *) ap_open_piped_log(ap_context_t *p, const char *program)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Couldn't fork child for piped log process");