From f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227ea Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Wed, 30 Sep 2009 17:50:56 -0400 Subject: [PATCH] Added debug_log_path setting and i_debug() call. Patch by Pascal Volk. --HG-- branch : HEAD --- doc/example-config/conf.d/logging.conf | 5 +- src/lib-master/master-service-settings.c | 2 + src/lib-master/master-service-settings.h | 1 + src/lib-master/master-service.c | 4 + src/lib/failures.c | 96 +++++++++++++++++++++--- src/lib/failures.h | 12 ++- src/master/main.c | 5 +- src/master/service-process.c | 1 + 8 files changed, 111 insertions(+), 15 deletions(-) diff --git a/doc/example-config/conf.d/logging.conf b/doc/example-config/conf.d/logging.conf index 72bd76fca9..8ae8918cb9 100644 --- a/doc/example-config/conf.d/logging.conf +++ b/doc/example-config/conf.d/logging.conf @@ -6,9 +6,10 @@ # /dev/stderr can be used to log into stderr. #log_path = -# Log file to use for informational and debug messages. -# Default is the same as log_path. +# Log file to use for informational messages. Defaults to log_path. #info_log_path = +# Log file to use for debug messages. Defaults to info_log_path. +#debug_log_path = # Syslog facility to use if you're logging to syslog. Usually if you don't # want to use "mail", you'll use local0..local7. Also other standard diff --git a/src/lib-master/master-service-settings.c b/src/lib-master/master-service-settings.c index 24c9384164..1255714872 100644 --- a/src/lib-master/master-service-settings.c +++ b/src/lib-master/master-service-settings.c @@ -25,6 +25,7 @@ static struct setting_define master_service_setting_defines[] = { DEF(SET_STR, log_path), DEF(SET_STR, info_log_path), + DEF(SET_STR, debug_log_path), DEF(SET_STR, log_timestamp), DEF(SET_STR, syslog_facility), DEF(SET_BOOL, version_ignore), @@ -35,6 +36,7 @@ static struct setting_define master_service_setting_defines[] = { static struct master_service_settings master_service_default_settings = { MEMBER(log_path) "", MEMBER(info_log_path) "", + MEMBER(debug_log_path) "", MEMBER(log_timestamp) DEFAULT_FAILURE_STAMP_FORMAT, MEMBER(syslog_facility) "mail", MEMBER(version_ignore) FALSE diff --git a/src/lib-master/master-service-settings.h b/src/lib-master/master-service-settings.h index 2bafb0f609..a574e6f7ad 100644 --- a/src/lib-master/master-service-settings.h +++ b/src/lib-master/master-service-settings.h @@ -10,6 +10,7 @@ struct master_service; struct master_service_settings { const char *log_path; const char *info_log_path; + const char *debug_log_path; const char *log_timestamp; const char *syslog_facility; bool version_ignore; diff --git a/src/lib-master/master-service.c b/src/lib-master/master-service.c index a31c099173..25f1d7197b 100644 --- a/src/lib-master/master-service.c +++ b/src/lib-master/master-service.c @@ -174,6 +174,10 @@ void master_service_init_log(struct master_service *service, path = home_expand(service->set->info_log_path); if (*path != '\0') i_set_info_file(path); + + path = home_expand(service->set->debug_log_path); + if (*path != '\0') + i_set_debug_file(path); i_set_failure_timestamp_format(service->set->log_timestamp); } diff --git a/src/lib/failures.c b/src/lib/failures.c index 00b845dfeb..fbc44f7621 100644 --- a/src/lib/failures.c +++ b/src/lib/failures.c @@ -17,6 +17,7 @@ #include const char *failure_log_type_prefixes[LOG_TYPE_COUNT] = { + "Debug: ", "Info: ", "Warning: ", "Error: ", @@ -29,9 +30,11 @@ static fatal_failure_callback_t *fatal_handler ATTR_NORETURN = default_fatal_handler; static failure_callback_t *error_handler = default_error_handler; static failure_callback_t *info_handler = default_error_handler; +static failure_callback_t *debug_handler = default_error_handler; static void (*failure_exit_callback)(int *) = NULL; -static int log_fd = STDERR_FILENO, log_info_fd = STDERR_FILENO; +static int log_fd = STDERR_FILENO, log_info_fd = STDERR_FILENO, + log_debug_fd = STDERR_FILENO; static char *log_prefix = NULL, *log_stamp_format = NULL; static bool failure_ignore_errors = FALSE; @@ -175,16 +178,27 @@ void default_fatal_handler(enum log_type type, int status, void default_error_handler(enum log_type type, const char *format, va_list args) { - int fd = type == LOG_TYPE_INFO ? log_info_fd : log_fd; + int fd; + + switch (type) { + case LOG_TYPE_DEBUG: + fd = log_debug_fd; + break; + case LOG_TYPE_INFO: + fd = log_info_fd; + break; + default: + fd = log_fd; + } if (default_handler(failure_log_type_prefixes[type], fd, format, args) < 0) { if (fd == log_fd) failure_exit(FATAL_LOGWRITE); - /* we failed to log to info log, try to log the write error - to error log - maybe that'll work. */ - i_fatal_status(FATAL_LOGWRITE, - "write() failed to info log: %m"); + /* we failed to log to info/debug log, try to log the + write error to error log - maybe that'll work. */ + i_fatal_status(FATAL_LOGWRITE, "write() failed to %s log: %m", + fd == log_info_fd ? "info" : "debug"); } } @@ -194,10 +208,17 @@ void i_log_type(enum log_type type, const char *format, ...) va_start(args, format); - if (type == LOG_TYPE_INFO) + switch (type) { + case LOG_TYPE_DEBUG: + debug_handler(type, format, args); + break; + case LOG_TYPE_INFO: info_handler(type, format, args); - else + break; + default: error_handler(type, format, args); + } + va_end(args); } @@ -264,6 +285,18 @@ void i_info(const char *format, ...) errno = old_errno; } +void i_debug(const char *format, ...) +{ + int old_errno = errno; + va_list args; + + va_start(args, format); + debug_handler(LOG_TYPE_DEBUG, format, args); + va_end(args); + + errno = old_errno; +} + void i_set_fatal_handler(fatal_failure_callback_t *callback ATTR_NORETURN) { if (callback == NULL) @@ -285,13 +318,22 @@ void i_set_info_handler(failure_callback_t *callback) info_handler = callback; } +void i_set_debug_handler(failure_callback_t *callback) +{ + if (callback == NULL) + callback = default_error_handler; + debug_handler = callback; +} + void i_get_failure_handlers(fatal_failure_callback_t **fatal_callback_r, failure_callback_t **error_callback_r, - failure_callback_t **info_callback_r) + failure_callback_t **info_callback_r, + failure_callback_t **debug_callback_r) { *fatal_callback_r = fatal_handler; *error_callback_r = error_handler; *info_callback_r = info_handler; + *debug_callback_r = debug_handler; } static int ATTR_FORMAT(3, 0) @@ -331,6 +373,9 @@ void i_syslog_error_handler(enum log_type type, const char *fmt, va_list args) int level = LOG_ERR; switch (type) { + case LOG_TYPE_DEBUG: + level = LOG_DEBUG; + break; case LOG_TYPE_INFO: level = LOG_INFO; break; @@ -360,6 +405,7 @@ void i_set_failure_syslog(const char *ident, int options, int facility) i_set_fatal_handler(i_syslog_fatal_handler); i_set_error_handler(i_syslog_error_handler); i_set_info_handler(i_syslog_error_handler); + i_set_debug_handler(i_syslog_error_handler); } static void open_log_file(int *fd, const char *path) @@ -398,12 +444,22 @@ void i_set_failure_file(const char *path, const char *prefix) i_error("close(%d) failed: %m", log_info_fd); } + if (log_debug_fd != STDERR_FILENO && log_debug_fd != log_info_fd && + log_debug_fd != log_fd) { + if (close(log_debug_fd) < 0) + i_error("close(%d) failed: %m", log_debug_fd); + } + open_log_file(&log_fd, path); + /* if info/debug logs are elsewhere, i_set_info/debug_file() + overrides these later. */ log_info_fd = log_fd; + log_debug_fd = log_fd; i_set_fatal_handler(NULL); i_set_error_handler(NULL); i_set_info_handler(NULL); + i_set_debug_handler(NULL); } static void i_failure_send_option(const char *key, const char *value) @@ -546,6 +602,7 @@ void i_set_failure_internal(void) i_set_fatal_handler(i_internal_fatal_handler); i_set_error_handler(i_internal_error_handler); i_set_info_handler(i_internal_error_handler); + i_set_debug_handler(i_internal_error_handler); } void i_set_failure_ignore_errors(bool ignore) @@ -560,6 +617,19 @@ void i_set_info_file(const char *path) open_log_file(&log_info_fd, path); info_handler = default_error_handler; + /* write debug-level messages to the info_log_path, + until i_set_debug_file() was called */ + log_debug_fd = log_info_fd; + i_set_debug_handler(NULL); +} + +void i_set_debug_file(const char *path) +{ + if (log_debug_fd == log_fd || log_debug_fd == log_info_fd) + log_debug_fd = STDERR_FILENO; + + open_log_file(&log_debug_fd, path); + debug_handler = default_error_handler; } void i_set_failure_timestamp_format(const char *fmt) @@ -580,6 +650,9 @@ void i_set_failure_exit_callback(void (*callback)(int *status)) void failures_deinit(void) { + if (log_debug_fd == log_info_fd || log_debug_fd == log_fd) + log_debug_fd = STDERR_FILENO; + if (log_info_fd == log_fd) log_info_fd = STDERR_FILENO; @@ -593,6 +666,11 @@ void failures_deinit(void) log_info_fd = STDERR_FILENO; } + if (log_debug_fd != STDERR_FILENO) { + (void)close(log_debug_fd); + log_debug_fd = STDERR_FILENO; + } + i_free_and_null(log_prefix); i_free_and_null(log_stamp_format); } diff --git a/src/lib/failures.h b/src/lib/failures.h index e05b15be17..f37b1dff75 100644 --- a/src/lib/failures.h +++ b/src/lib/failures.h @@ -15,6 +15,7 @@ enum fatal_exit_status { }; enum log_type { + LOG_TYPE_DEBUG, LOG_TYPE_INFO, LOG_TYPE_WARNING, LOG_TYPE_ERROR, @@ -46,6 +47,7 @@ void i_fatal(const char *format, ...) ATTR_FORMAT(1, 2) ATTR_NORETURN ATTR_COLD; void i_error(const char *format, ...) ATTR_FORMAT(1, 2) ATTR_COLD; void i_warning(const char *format, ...) ATTR_FORMAT(1, 2); void i_info(const char *format, ...) ATTR_FORMAT(1, 2); +void i_debug(const char *format, ...) ATTR_FORMAT(1, 2); void i_fatal_status(int status, const char *format, ...) ATTR_FORMAT(2, 3) ATTR_NORETURN ATTR_COLD; @@ -59,9 +61,11 @@ void i_set_fatal_handler(fatal_failure_callback_t *callback); #endif void i_set_error_handler(failure_callback_t *callback); void i_set_info_handler(failure_callback_t *callback); +void i_set_debug_handler(failure_callback_t *callback); void i_get_failure_handlers(fatal_failure_callback_t **fatal_callback_r, failure_callback_t **error_callback_r, - failure_callback_t **info_callback_r); + failure_callback_t **info_callback_r, + failure_callback_t **debug_callback_r); /* Send failures to file. */ void default_fatal_handler(enum log_type type, int status, @@ -77,7 +81,7 @@ void i_syslog_fatal_handler(enum log_type type, int status, void i_syslog_error_handler(enum log_type type, const char *fmt, va_list args) ATTR_FORMAT(2, 0); -/* Open syslog and set failure/info handlers to use it. */ +/* Open syslog and set failure/info/debug handlers to use it. */ void i_set_failure_syslog(const char *ident, int options, int facility); /* Send failures to specified log file instead of stderr. */ @@ -93,6 +97,10 @@ void i_set_failure_ignore_errors(bool ignore); functions modify the info file too, so call this function after them. */ void i_set_info_file(const char *path); +/* Send debug-level message to the given log file. The i_set_info_file() + function modifies also the debug log file, so call this function after it. */ +void i_set_debug_file(const char *path); + /* Set the failure prefix. */ void i_set_failure_prefix(const char *prefix); /* Prefix failures with a timestamp. fmt is in strftime() format. */ diff --git a/src/master/main.c b/src/master/main.c index cba3005bc7..062486f268 100644 --- a/src/master/main.c +++ b/src/master/main.c @@ -405,6 +405,7 @@ static void main_init(bool log_error) if (log_error) { fprintf(stderr, "Writing to error logs and killing myself..\n"); + i_debug("This is Dovecot's debug log"); i_info("This is Dovecot's info log"); i_warning("This is Dovecot's warning log"); i_error("This is Dovecot's error log"); @@ -604,7 +605,7 @@ int main(int argc, char *argv[]) struct master_settings *set; unsigned int child_process_env_idx = 0; const char *getopt_str, *error, *env_tz, *doveconf_arg = NULL; - failure_callback_t *orig_info_callback; + failure_callback_t *orig_info_callback, *orig_debug_callback; void **sets; bool foreground = FALSE, ask_key_pass = FALSE, log_error = FALSE; int c, send_signal = 0; @@ -718,7 +719,7 @@ int main(int argc, char *argv[]) master_service_init_log(master_service, "master: "); i_get_failure_handlers(&orig_fatal_callback, &orig_error_callback, - &orig_info_callback); + &orig_info_callback, &orig_debug_callback); i_set_fatal_handler(startup_fatal_handler); i_set_error_handler(startup_error_handler); diff --git a/src/master/service-process.c b/src/master/service-process.c index 5d4b696380..cd3f5d8bed 100644 --- a/src/master/service-process.c +++ b/src/master/service-process.c @@ -408,6 +408,7 @@ service_process_setup_environment(struct service *service, unsigned int uid) env_put("DOVECONF_ENV=1"); env_put(t_strconcat("LOG_PATH=", set->log_path, NULL)); env_put(t_strconcat("INFO_LOG_PATH=", set->info_log_path, NULL)); + env_put(t_strconcat("DEBUG_LOG_PATH=", set->debug_log_path, NULL)); env_put(t_strconcat("LOG_TIMESTAMP=", set->log_timestamp, NULL)); env_put(t_strconcat("SYSLOG_FACILITY=", set->syslog_facility, NULL)); break; -- 2.47.3