diff options
author | Jan Kaluža <jkaluza@apache.org> | 2013-09-23 16:02:27 +0200 |
---|---|---|
committer | Jan Kaluža <jkaluza@apache.org> | 2013-09-23 16:02:27 +0200 |
commit | 59bb55791ea12704a2bf0af6f4cbd9e0178e1d4d (patch) | |
tree | eaf00fbe767bdec8d0bf48e2302735e73bda1106 | |
parent | add a note about sub-group searching and large groups. (diff) | |
download | apache2-59bb55791ea12704a2bf0af6f4cbd9e0178e1d4d.tar.xz apache2-59bb55791ea12704a2bf0af6f4cbd9e0178e1d4d.zip |
Add ap_errorlog_provider to make ErrorLog logging modular. Move
syslog support from core to new mod_syslog.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1525597 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | docs/manual/mod/core.xml | 11 | ||||
-rw-r--r-- | include/http_core.h | 28 | ||||
-rw-r--r-- | include/httpd.h | 4 | ||||
-rw-r--r-- | server/core.c | 50 | ||||
-rw-r--r-- | server/log.c | 128 |
6 files changed, 109 insertions, 115 deletions
@@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) core: Add ap_errorlog_provider to make ErrorLog logging modular. Move + syslog support from core to new mod_syslog. [Jan Kaluza] + *) mod_proxy_fcgi: Handle reading protocol data that is split between packets. [Jeff Trawick] diff --git a/docs/manual/mod/core.xml b/docs/manual/mod/core.xml index 06e6a4ec1a..ecd588653d 100644 --- a/docs/manual/mod/core.xml +++ b/docs/manual/mod/core.xml @@ -1298,16 +1298,19 @@ ErrorDocument 404 /cgi-bin/bad_urls.pl more information.</p> <p>Using <code>syslog</code> instead of a filename enables logging - via syslogd(8) if the system supports it. The default is to use - syslog facility <code>local7</code>, but you can override this by - using the <code>syslog:<var>facility</var></code> syntax where - <var>facility</var> can be one of the names usually documented in + via syslogd(8) if the system supports it and if <module>mod_syslog</module> + is loaded. The default is to use syslog facility <code>local7</code>, + but you can override this by using the <code>syslog:<var>facility</var></code> + syntax where <var>facility</var> can be one of the names usually documented in syslog(1). The facility is effectively global, and if it is changed in individual virtual hosts, the final facility specified affects the entire server.</p> <highlight language="config">ErrorLog syslog:user</highlight> + <p>Additional modules can provide their own ErrorLog providers. The syntax + is similar to <code>syslog</code> example above.</p> + <p>SECURITY: See the <a href="../misc/security_tips.html#serverroot">security tips</a> document for details on why your security could be compromised diff --git a/include/http_core.h b/include/http_core.h index 80ce6cdd96..a31aa054a1 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -833,8 +833,8 @@ typedef struct ap_errorlog_info { /** apr error status related to the log message, 0 if no error */ apr_status_t status; - /** 1 if logging to syslog, 0 otherwise */ - int using_syslog; + /** 1 if logging using provider, 0 otherwise */ + int using_provider; /** 1 if APLOG_STARTUP was set for the log message, 0 otherwise */ int startup; @@ -842,6 +842,30 @@ typedef struct ap_errorlog_info { const char *format; } ap_errorlog_info; +#define AP_ERRORLOG_PROVIDER_GROUP "error_log_writer" +#define AP_ERRORLOG_PROVIDER_VERSION "0" +#define AP_ERRORLOG_DEFAULT_PROVIDER "file" + +typedef struct ap_errorlog_provider ap_errorlog_provider; + +struct ap_errorlog_provider { + /** Initializes the error log writer. + * @param p The pool to create any storage from + * @param s Server for which the logger is initialized + * @return Pointer to handle passed later to writer() function + */ + void * (*init)(apr_pool_t *p, server_rec *s); + + /** Logs the error message to external error log. + * @param info Context of the error message + * @param handle Handle created by init() function + * @param errstr Error message + * @param len Length of the error message + */ + apr_status_t (*writer)(const ap_errorlog_info *info, void *handle, + const char *errstr, int len); +}; + /** * callback function prototype for a external errorlog handler * @note To avoid unbounded memory usage, these functions must not allocate diff --git a/include/httpd.h b/include/httpd.h index 175c7d867f..0439e97e27 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -1245,6 +1245,10 @@ struct server_rec { apr_file_t *error_log; /** The log level configuration */ struct ap_logconf log; + /** External error log writer provider */ + struct ap_errorlog_provider *errorlog_provider; + /** Handle to be passed to external log provider's logging method */ + void *errorlog_provider_handle; /* Module-specific configuration for server, and defaults... */ diff --git a/server/core.c b/server/core.c index 9e01154dc3..de7997952c 100644 --- a/server/core.c +++ b/server/core.c @@ -48,6 +48,7 @@ #include "mod_core.h" #include "mod_proxy.h" #include "ap_listen.h" +#include "ap_provider.h" #include "mod_so.h" /* for ap_find_loaded_module_symbol */ @@ -3955,6 +3956,49 @@ static apr_array_header_t *parse_errorlog_string(apr_pool_t *p, return a; } +static const char *set_errorlog(cmd_parms *cmd, void *dummy, const char *arg1, + const char *arg2) +{ + ap_errorlog_provider *provider; + cmd->server->errorlog_provider = NULL; + + if (!arg2) { + /* Stay backward compatible and check for "syslog" */ + if (strncmp("syslog", arg1, 6) == 0) { + arg2 = arg1 + 7; /* skip the ':' if any */ + arg1 = "syslog"; + } + else { + /* Admin can define only "ErrorLog provider" and we should + * still handle that using the defined provider, but with empty + * error_fname. */ + provider = ap_lookup_provider(AP_ERRORLOG_PROVIDER_GROUP, arg1, + AP_ERRORLOG_PROVIDER_VERSION); + if (provider) { + arg2 = ""; + } + else { + return set_server_string_slot(cmd, dummy, arg1); + } + } + } + + if (strcmp("file", arg1) == 0) { + return set_server_string_slot(cmd, dummy, arg2); + } + + provider = ap_lookup_provider(AP_ERRORLOG_PROVIDER_GROUP, arg1, + AP_ERRORLOG_PROVIDER_VERSION); + if (!provider) { + return apr_psprintf(cmd->pool, + "Unknown ErrorLog provider: %s", + arg1); + } + + cmd->server->errorlog_provider = provider; + return set_server_string_slot(cmd, dummy, arg2); +} + static const char *set_errorlog_format(cmd_parms *cmd, void *dummy, const char *arg1, const char *arg2) { @@ -4118,7 +4162,7 @@ AP_INIT_TAKE1("ServerRoot", set_server_root, NULL, RSRC_CONF | EXEC_ON_READ, "Common directory of server-related files (logs, confs, etc.)"), AP_INIT_TAKE1("DefaultRuntimeDir", set_runtime_dir, NULL, RSRC_CONF | EXEC_ON_READ, "Common directory for run-time files (shared memory, locks, etc.)"), -AP_INIT_TAKE1("ErrorLog", set_server_string_slot, +AP_INIT_TAKE12("ErrorLog", set_errorlog, (void *)APR_OFFSETOF(server_rec, error_fname), RSRC_CONF, "The filename of the error log"), AP_INIT_TAKE12("ErrorLogFormat", set_errorlog_format, NULL, RSRC_CONF, @@ -4560,7 +4604,7 @@ AP_DECLARE(int) ap_sys_privileges_handlers(int inc) static int check_errorlog_dir(apr_pool_t *p, server_rec *s) { if (!s->error_fname || s->error_fname[0] == '|' - || strcmp(s->error_fname, "syslog") == 0) { + || s->errorlog_provider != NULL) { return APR_SUCCESS; } else { @@ -4986,7 +5030,7 @@ static void core_dump_config(apr_pool_t *p, server_rec *s) apr_file_printf(out, "ServerRoot: \"%s\"\n", ap_server_root); tmp = ap_server_root_relative(p, sconf->ap_document_root); apr_file_printf(out, "Main DocumentRoot: \"%s\"\n", tmp); - if (s->error_fname[0] != '|' && strcmp(s->error_fname, "syslog") != 0) + if (s->error_fname[0] != '|' && s->errorlog_provider == NULL) tmp = ap_server_root_relative(p, s->error_fname); else tmp = s->error_fname; diff --git a/server/log.c b/server/log.c index 161cc9d334..0185124169 100644 --- a/server/log.c +++ b/server/log.c @@ -53,6 +53,7 @@ #include "http_main.h" #include "util_time.h" #include "ap_mpm.h" +#include "ap_provider.h" #if HAVE_GETTID #include <sys/syscall.h> @@ -75,71 +76,6 @@ APR_HOOK_STRUCT( int AP_DECLARE_DATA ap_default_loglevel = DEFAULT_LOGLEVEL; -#ifdef HAVE_SYSLOG - -static const TRANS facilities[] = { - {"auth", LOG_AUTH}, -#ifdef LOG_AUTHPRIV - {"authpriv",LOG_AUTHPRIV}, -#endif -#ifdef LOG_CRON - {"cron", LOG_CRON}, -#endif -#ifdef LOG_DAEMON - {"daemon", LOG_DAEMON}, -#endif -#ifdef LOG_FTP - {"ftp", LOG_FTP}, -#endif -#ifdef LOG_KERN - {"kern", LOG_KERN}, -#endif -#ifdef LOG_LPR - {"lpr", LOG_LPR}, -#endif -#ifdef LOG_MAIL - {"mail", LOG_MAIL}, -#endif -#ifdef LOG_NEWS - {"news", LOG_NEWS}, -#endif -#ifdef LOG_SYSLOG - {"syslog", LOG_SYSLOG}, -#endif -#ifdef LOG_USER - {"user", LOG_USER}, -#endif -#ifdef LOG_UUCP - {"uucp", LOG_UUCP}, -#endif -#ifdef LOG_LOCAL0 - {"local0", LOG_LOCAL0}, -#endif -#ifdef LOG_LOCAL1 - {"local1", LOG_LOCAL1}, -#endif -#ifdef LOG_LOCAL2 - {"local2", LOG_LOCAL2}, -#endif -#ifdef LOG_LOCAL3 - {"local3", LOG_LOCAL3}, -#endif -#ifdef LOG_LOCAL4 - {"local4", LOG_LOCAL4}, -#endif -#ifdef LOG_LOCAL5 - {"local5", LOG_LOCAL5}, -#endif -#ifdef LOG_LOCAL6 - {"local6", LOG_LOCAL6}, -#endif -#ifdef LOG_LOCAL7 - {"local7", LOG_LOCAL7}, -#endif - {NULL, -1}, -}; -#endif - static const TRANS priorities[] = { {"emerg", APLOG_EMERG}, {"alert", APLOG_ALERT}, @@ -395,29 +331,10 @@ static int open_error_log(server_rec *s, int is_main, apr_pool_t *p) s->error_log = dummy; } - -#ifdef HAVE_SYSLOG - else if (!strncasecmp(s->error_fname, "syslog", 6)) { - if ((fname = strchr(s->error_fname, ':'))) { - const TRANS *fac; - - fname++; - for (fac = facilities; fac->t_name; fac++) { - if (!strcasecmp(fname, fac->t_name)) { - openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, - fac->t_val); - s->error_log = NULL; - return OK; - } - } - } - else { - openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7); - } - + else if (s->errorlog_provider) { + s->errorlog_provider_handle = s->errorlog_provider->init(p, s); s->error_log = NULL; } -#endif else { fname = ap_server_root_relative(p, s->error_fname); if (!fname) { @@ -904,7 +821,7 @@ AP_DECLARE(void) ap_register_log_hooks(apr_pool_t *p) /* * This is used if no error log format is defined and during startup. - * It automatically omits the timestamp if logging to syslog. + * It automatically omits the timestamp if logging using provider. */ static int do_errorlog_default(const ap_errorlog_info *info, char *buf, int buflen, int *errstr_start, int *errstr_end, @@ -917,7 +834,7 @@ static int do_errorlog_default(const ap_errorlog_info *info, char *buf, char scratch[MAX_STRING_LEN]; #endif - if (!info->using_syslog && !info->startup) { + if (!info->using_provider && !info->startup) { buf[len++] = '['; len += log_ctime(info, "u", buf + len, buflen - len); buf[len++] = ']'; @@ -1076,22 +993,14 @@ static int do_errorlog_format(apr_array_header_t *fmt, ap_errorlog_info *info, static void write_logline(char *errstr, apr_size_t len, apr_file_t *logf, int level) { - /* NULL if we are logging to syslog */ - if (logf) { - /* Truncate for the terminator (as apr_snprintf does) */ - if (len > MAX_STRING_LEN - sizeof(APR_EOL_STR)) { - len = MAX_STRING_LEN - sizeof(APR_EOL_STR); - } - strcpy(errstr + len, APR_EOL_STR); - apr_file_puts(errstr, logf); - apr_file_flush(logf); - } -#ifdef HAVE_SYSLOG - else { - syslog(level < LOG_PRIMASK ? level : APLOG_DEBUG, "%.*s", - (int)len, errstr); + + /* Truncate for the terminator (as apr_snprintf does) */ + if (len > MAX_STRING_LEN - sizeof(APR_EOL_STR)) { + len = MAX_STRING_LEN - sizeof(APR_EOL_STR); } -#endif + strcpy(errstr + len, APR_EOL_STR); + apr_file_puts(errstr, logf); + apr_file_flush(logf); } static void log_error_core(const char *file, int line, int module_index, @@ -1152,7 +1061,7 @@ static void log_error_core(const char *file, int line, int module_index, } else { /* - * If we are doing syslog logging, don't log messages that are + * If we are doing logging using provider, don't log messages that are * above the module's log level (including a startup/shutdown notice) */ if (level_and_mask > configured_level) { @@ -1194,7 +1103,7 @@ static void log_error_core(const char *file, int line, int module_index, info.file = NULL; info.line = 0; info.status = 0; - info.using_syslog = (logf == NULL); + info.using_provider= (logf == NULL); info.startup = ((level & APLOG_STARTUP) == APLOG_STARTUP); info.format = fmt; @@ -1272,7 +1181,14 @@ static void log_error_core(const char *file, int line, int module_index, */ continue; } - write_logline(errstr, len, logf, level_and_mask); + + if (logf) { + write_logline(errstr, len, logf, level_and_mask); + } + else { + s->errorlog_provider->writer(&info, s->errorlog_provider_handle, + errstr, len); + } if (done) { /* |