]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added debug_log_path setting and i_debug() call.
authorTimo Sirainen <tss@iki.fi>
Wed, 30 Sep 2009 21:50:56 +0000 (17:50 -0400)
committerTimo Sirainen <tss@iki.fi>
Wed, 30 Sep 2009 21:50:56 +0000 (17:50 -0400)
Patch by Pascal Volk.

--HG--
branch : HEAD

doc/example-config/conf.d/logging.conf
src/lib-master/master-service-settings.c
src/lib-master/master-service-settings.h
src/lib-master/master-service.c
src/lib/failures.c
src/lib/failures.h
src/master/main.c
src/master/service-process.c

index 72bd76fca9066edaeff5eba912821ed4868587cc..8ae8918cb91f958c877ff5867fa415e53931b642 100644 (file)
@@ -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
index 24c9384164344d44d5c721d04779275414878ad9..1255714872faf35243ce0b634e04484ced9868cf 100644 (file)
@@ -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
index 2bafb0f609fe3f573fb0753b0ca52c30e99aa07f..a574e6f7ad7977d90e9a1d9e7c87245d07f9c646 100644 (file)
@@ -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;
index a31c099173c11ae01d9b1c93942c1045a5b96664..25f1d7197b344336ab9aea1eed9b4195be793ec4 100644 (file)
@@ -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);
 }
 
index 00b845dfebb25da0e51741c1df9e0b53244e436d..fbc44f76212b47f60721e845addeab8b00cbd61d 100644 (file)
@@ -17,6 +17,7 @@
 #include <time.h>
 
 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);
 }
index e05b15be173f8aaf454103bfff6411700f1aa4e3..f37b1dff759076279e0e1a565d037a58c833a5bc 100644 (file)
@@ -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. */
index cba3005bc78cf02ef630b742695ca8289efc5c84..062486f26809f9658a1d50cf7c930f5095db212a 100644 (file)
@@ -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);
 
index 5d4b69638031a83da963d40f418f033c365bff70..cd3f5d8bed408caa4f24524a909a505e09cc715c 100644 (file)
@@ -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;