]> granicus.if.org Git - apache/blobdiff - server/log.c
use APR_STATUS_IS_TIMEUP() instead of direct comparison with APR_TIMEUP.
[apache] / server / log.c
index 80b28443fd7f434e95c3f632dfe6bd847be7965e..50d9cbcb3ede20e6fef25e00f321ee94ac19fc86 100644 (file)
@@ -41,6 +41,9 @@
 #if APR_HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#if APR_HAVE_PROCESS_H
+#include <process.h>            /* for getpid() on Win32 */
+#endif
 
 #include "ap_config.h"
 #include "httpd.h"
@@ -60,6 +63,7 @@ typedef struct {
 
 APR_HOOK_STRUCT(
     APR_HOOK_LINK(error_log)
+    APR_HOOK_LINK(generate_log_id)
 )
 
 int AP_DECLARE_DATA ap_default_loglevel = DEFAULT_LOGLEVEL;
@@ -192,16 +196,6 @@ AP_DECLARE(apr_file_t *) ap_piped_log_write_fd(piped_log *pl)
     return pl->write_fd;
 }
 
-/* clear_handle_list() is called when plog is cleared; at that
- * point we need to forget about our old list of pipe read
- * handles.  We let the plog cleanups close the actual pipes.
- */
-static apr_status_t clear_handle_list(void *v)
-{
-    read_handles = NULL;
-    return APR_SUCCESS;
-}
-
 /* remember to close this handle in the child process
  *
  * On Win32 this makes zero sense, because we don't
@@ -455,7 +449,7 @@ int ap_open_logs(apr_pool_t *pconf, apr_pool_t *p /* plog */,
      * between log phases, so we don't mind losing stderr's 
      * read_handle a little bit early.
      */
-    apr_pool_cleanup_register(p, NULL, clear_handle_list,
+    apr_pool_cleanup_register(p, &read_handles, ap_pool_cleanup_set_null,
                               apr_pool_cleanup_null);
 
     /* HERE we need a stdout log that outlives plog.
@@ -736,53 +730,73 @@ static int log_apr_status(const ap_errorlog_info *info, const char *arg,
     return len;
 }
 
-static int log_header(const ap_errorlog_info *info, const char *arg,
-                      char *buf, int buflen)
+static int log_server_name(const ap_errorlog_info *info, const char *arg,
+                           char *buf, int buflen)
+{
+    if (info->r)
+        return cpystrn(buf, ap_get_server_name((request_rec *)info->r), buflen);
+
+    return 0;
+}
+
+static int log_virtual_host(const ap_errorlog_info *info, const char *arg,
+                            char *buf, int buflen)
+{
+    if (info->s)
+        return cpystrn(buf, info->s->server_hostname, buflen);
+
+    return 0;
+}
+
+
+static int log_table_entry(const apr_table_t *table, const char *name,
+                           char *buf, int buflen)
 {
-    const char *header;
-    int len = 0;
 #ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
+    const char *value;
     char scratch[MAX_STRING_LEN];
-#endif
 
-    if ( info->r && (header = apr_table_get(info->r->headers_in, arg))
-#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
-         && ap_escape_errorlog_item(scratch, header, MAX_STRING_LEN)
-#endif
-       ) {
-        len = cpystrn(buf,
-#ifndef AP_UNSAFE_ERROR_LOG_UNESCAPED
-                           scratch,
+    if ((value = apr_table_get(table, name)) != NULL) {
+        ap_escape_errorlog_item(scratch, value, MAX_STRING_LEN);
+        return cpystrn(buf, scratch, buflen);
+    }
+
+    return 0;
 #else
-                           header,
+    return cpystrn(buf, apr_table_get(table, name), buflen);
 #endif
-                           buflen);
-    }
-    return len;
 }
 
+static int log_header(const ap_errorlog_info *info, const char *arg,
+                      char *buf, int buflen)
+{
+    if (info->r)
+        return log_table_entry(info->r->headers_in, arg, buf, buflen);
+
+    return 0;
+}
 
+static int log_note(const ap_errorlog_info *info, const char *arg,
+                      char *buf, int buflen)
+{
+    /* XXX: maybe escaping the entry is not necessary for notes? */
+    if (info->r)
+        return log_table_entry(info->r->notes, arg, buf, buflen);
 
+    return 0;
+}
 
-AP_DECLARE(void) ap_register_builtin_errorlog_handlers(apr_pool_t *p)
+static int log_env_var(const ap_errorlog_info *info, const char *arg,
+                      char *buf, int buflen)
 {
-    ap_register_errorlog_handler(p, "a", log_remote_address, 0);
-    ap_register_errorlog_handler(p, "A", log_local_address, 0);
-    ap_register_errorlog_handler(p, "E", log_apr_status, 0);
-    ap_register_errorlog_handler(p, "F", log_file_line, 0);
-    ap_register_errorlog_handler(p, "i", log_header, 0);
-    ap_register_errorlog_handler(p, "k", log_keepalives, 0);
-    ap_register_errorlog_handler(p, "l", log_loglevel, 0);
-    ap_register_errorlog_handler(p, "L", log_log_id, 0);
-    ap_register_errorlog_handler(p, "m", log_module_name, 0);
-    ap_register_errorlog_handler(p, "P", log_pid, 0);
-    ap_register_errorlog_handler(p, "t", log_ctime, 0);
-    ap_register_errorlog_handler(p, "T", log_tid, 0);
+    if (info->r)
+        return log_table_entry(info->r->subprocess_env, arg, buf, buflen);
 
-    /* XXX: TODO: envvars, notes */
+    return 0;
 }
 
-static void add_log_id(const conn_rec *c, const request_rec *r)
+static int core_generate_log_id(const conn_rec *c, const request_rec *r,
+                                 const char **idstring)
 {
     apr_uint64_t id, tmp;
     pid_t pid;
@@ -825,15 +839,48 @@ static void add_log_id(const conn_rec *c, const request_rec *r)
     apr_base64_encode(encoded, (char *)&id, sizeof(id));
 
     /* Skip the last char, it is always '=' */
-    encoded[len - 2] = '\0'; 
+    encoded[len - 2] = '\0';
+
+    *idstring = encoded;
+
+    return OK;
+}
 
+static void add_log_id(const conn_rec *c, const request_rec *r)
+{
+    const char **id;
     /* need to cast const away */
     if (r) {
-        ((request_rec *)r)->log_id = encoded;
+        id = &((request_rec *)r)->log_id;
     }
     else {
-        ((conn_rec *)c)->log_id = encoded;
+        id = &((conn_rec *)c)->log_id;
     }
+
+    ap_run_generate_log_id(c, r, id);
+}
+
+AP_DECLARE(void) ap_register_log_hooks(apr_pool_t *p)
+{
+    ap_hook_generate_log_id(core_generate_log_id, NULL, NULL,
+                            APR_HOOK_REALLY_LAST);
+
+    ap_register_errorlog_handler(p, "a", log_remote_address, 0);
+    ap_register_errorlog_handler(p, "A", log_local_address, 0);
+    ap_register_errorlog_handler(p, "e", log_env_var, 0);
+    ap_register_errorlog_handler(p, "E", log_apr_status, 0);
+    ap_register_errorlog_handler(p, "F", log_file_line, 0);
+    ap_register_errorlog_handler(p, "i", log_header, 0);
+    ap_register_errorlog_handler(p, "k", log_keepalives, 0);
+    ap_register_errorlog_handler(p, "l", log_loglevel, 0);
+    ap_register_errorlog_handler(p, "L", log_log_id, 0);
+    ap_register_errorlog_handler(p, "m", log_module_name, 0);
+    ap_register_errorlog_handler(p, "n", log_note, 0);
+    ap_register_errorlog_handler(p, "P", log_pid, 0);
+    ap_register_errorlog_handler(p, "t", log_ctime, 0);
+    ap_register_errorlog_handler(p, "T", log_tid, 0);
+    ap_register_errorlog_handler(p, "v", log_virtual_host, 0);
+    ap_register_errorlog_handler(p, "V", log_server_name, 0);
 }
 
 /*
@@ -970,6 +1017,10 @@ static int do_errorlog_format(apr_array_header_t *fmt, ap_errorlog_info *info,
         else if (skipping) {
             continue;
         }
+        else if ((int)item->min_loglevel > info->level) {
+            len = field_start;
+            skipping = 1;
+        }
         else {
             int item_len = (*item->func)(info, item->arg, buf + len,
                                          buflen - len);
@@ -1080,36 +1131,39 @@ static void log_error_core(const char *file, int line, int module_index,
             }
         }
 
-        sconf = ap_get_module_config(s->module_config, &core_module);
-        if (c && !c->log_id) {
-            add_log_id(c, NULL);
-            if (sconf->error_log_conn && sconf->error_log_conn->nelts > 0)
-                log_conn_info = 1;
-        }
-        if (r) {
-            if (r->main)
-                rmain = r->main;
-            else
-                rmain = r;
-
-            if (!rmain->log_id) {
-                /* XXX: do we need separate log ids for subrequests? */
-                if (sconf->error_log_req && sconf->error_log_req->nelts > 0)
-                    log_req_info = 1;
-                /*
-                 * XXX: potential optimization: only create log id if %L is
-                 * XXX: actually used
-                 */
-                add_log_id(c, rmain);
+        /* the faked server_rec from mod_cgid does not have s->module_config */
+        if (s->module_config) {
+            sconf = ap_get_module_config(s->module_config, &core_module);
+            if (c && !c->log_id) {
+                add_log_id(c, NULL);
+                if (sconf->error_log_conn && sconf->error_log_conn->nelts > 0)
+                    log_conn_info = 1;
+            }
+            if (r) {
+                if (r->main)
+                    rmain = r->main;
+                else
+                    rmain = r;
+
+                if (!rmain->log_id) {
+                    /* XXX: do we need separate log ids for subrequests? */
+                    if (sconf->error_log_req && sconf->error_log_req->nelts > 0)
+                        log_req_info = 1;
+                    /*
+                     * XXX: potential optimization: only create log id if %L is
+                     * XXX: actually used
+                     */
+                    add_log_id(c, rmain);
+                }
             }
         }
     }
 
     info.s             = s;
     info.c             = c;
-    info.file          = file;
-    info.line          = line;
-    info.status        = status;
+    info.file          = NULL;
+    info.line          = 0;
+    info.status        = 0;
     info.using_syslog  = (logf == NULL);
     info.startup       = ((level & APLOG_STARTUP) == APLOG_STARTUP);
 
@@ -1156,10 +1210,13 @@ static void log_error_core(const char *file, int line, int module_index,
         }
         else {
             /* the actual error message */
-            info.r = r;
-            info.rmain = rmain;
-            info.level = level_and_mask;
+            info.r            = r;
+            info.rmain        = rmain;
+            info.level        = level_and_mask;
             info.module_index = module_index;
+            info.file         = file;
+            info.line         = line;
+            info.status       = status;
             log_format = sconf ? sconf->error_log_format : NULL;
             done = 1;
         }
@@ -1304,6 +1361,25 @@ AP_DECLARE(void) ap_log_command_line(apr_pool_t *plog, server_rec *s)
                  "Command line: '%s'", result);
 }
 
+AP_DECLARE(void) ap_remove_pid(apr_pool_t *p, const char *rel_fname)
+{
+    apr_status_t rv;
+    const char *fname = ap_server_root_relative(p, rel_fname);
+
+    if (fname != NULL) {
+        rv = apr_file_remove(fname, p);
+        if (rv != APR_SUCCESS) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
+                         "failed to remove PID file %s", fname);
+        }
+        else {
+            ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf,
+                         "removed PID file %s (pid=%" APR_PID_T_FMT ")",
+                         fname, getpid());
+        }
+    }
+}
+
 AP_DECLARE(void) ap_log_pid(apr_pool_t *p, const char *filename)
 {
     apr_file_t *pid_file = NULL;
@@ -1672,3 +1748,8 @@ AP_IMPLEMENT_HOOK_VOID(error_log,
                         const request_rec *r, apr_pool_t *pool,
                         const char *errstr), (file, line, module_index, level,
                         status, s, r, pool, errstr))
+
+AP_IMPLEMENT_HOOK_RUN_FIRST(int, generate_log_id,
+                            (const conn_rec *c, const request_rec *r,
+                             const char **id),
+                            (c, r, id), DECLINED)