#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"
APR_HOOK_STRUCT(
APR_HOOK_LINK(error_log)
+ APR_HOOK_LINK(generate_log_id)
)
int AP_DECLARE_DATA ap_default_loglevel = DEFAULT_LOGLEVEL;
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
* 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.
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;
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);
}
/*
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);
}
}
- 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);
}
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;
}
"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;
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)