Make syslog and file loggers configurable at runtime
authorTobias Brunner <tobias@strongswan.org>
Thu, 4 Oct 2012 16:07:42 +0000 (18:07 +0200)
committerTobias Brunner <tobias@strongswan.org>
Thu, 18 Oct 2012 12:42:10 +0000 (14:42 +0200)
src/charon-nm/charon-nm.c
src/charon/charon.c
src/conftest/conftest.c
src/frontends/android/jni/libandroidbridge/charonservice.c
src/libcharon/bus/listeners/file_logger.c
src/libcharon/bus/listeners/file_logger.h
src/libcharon/bus/listeners/sys_logger.c
src/libcharon/bus/listeners/sys_logger.h

index 35e9067..4857c99 100644 (file)
@@ -125,7 +125,7 @@ static void initialize_logger()
        debug_t group;
        level_t def;
 
-       sys_logger = sys_logger_create(LOG_DAEMON, FALSE);
+       sys_logger = sys_logger_create(LOG_DAEMON);
        def = lib->settings->get_int(lib->settings,
                                                                 "charon-nm.syslog.default", 1);
        for (group = 0; group < DBG_MAX; group++)
index bd36c72..ba3e8fb 100644 (file)
@@ -250,8 +250,6 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
        int loggers_defined = 0;
        debug_t group;
        level_t  def;
-       bool append, ike_name;
-       FILE *file;
 
        /* setup sysloggers */
        identifier = lib->settings->get_str(lib->settings,
@@ -266,20 +264,22 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
        {
                loggers_defined++;
 
-               ike_name = lib->settings->get_bool(lib->settings,
-                                                               "charon.syslog.%s.ike_name", FALSE, facility);
                if (streq(facility, "daemon"))
                {
-                       sys_logger = sys_logger_create(LOG_DAEMON, ike_name);
+                       sys_logger = sys_logger_create(LOG_DAEMON);
                }
                else if (streq(facility, "auth"))
                {
-                       sys_logger = sys_logger_create(LOG_AUTHPRIV, ike_name);
+                       sys_logger = sys_logger_create(LOG_AUTHPRIV);
                }
                else
                {
                        continue;
                }
+               sys_logger->set_options(sys_logger,
+                                               lib->settings->get_bool(lib->settings,
+                                                               "charon.syslog.%s.ike_name", FALSE, facility));
+
                def = lib->settings->get_int(lib->settings,
                                                                         "charon.syslog.%s.default", 1, facility);
                for (group = 0; group < DBG_MAX; group++)
@@ -300,36 +300,17 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
        while (enumerator->enumerate(enumerator, &filename))
        {
                loggers_defined++;
-               if (streq(filename, "stderr"))
-               {
-                       file = stderr;
-               }
-               else if (streq(filename, "stdout"))
-               {
-                       file = stdout;
-               }
-               else
-               {
-                       append = lib->settings->get_bool(lib->settings,
-                                                                       "charon.filelog.%s.append", TRUE, filename);
-                       file = fopen(filename, append ? "a" : "w");
-                       if (file == NULL)
-                       {
-                               DBG1(DBG_DMN, "opening file %s for logging failed: %s",
-                                        filename, strerror(errno));
-                               continue;
-                       }
-                       if (lib->settings->get_bool(lib->settings,
-                                                       "charon.filelog.%s.flush_line", FALSE, filename))
-                       {
-                               setlinebuf(file);
-                       }
-               }
-               file_logger = file_logger_create(file,
+               file_logger = file_logger_create(filename);
+               file_logger->set_options(file_logger,
                                                lib->settings->get_str(lib->settings,
                                                        "charon.filelog.%s.time_format", NULL, filename),
                                                lib->settings->get_bool(lib->settings,
                                                        "charon.filelog.%s.ike_name", FALSE, filename));
+               file_logger->open(file_logger,
+                                               lib->settings->get_bool(lib->settings,
+                                                       "charon.filelog.%s.flush_line", FALSE, filename),
+                                               lib->settings->get_bool(lib->settings,
+                                                       "charon.filelog.%s.append", TRUE, filename));
                def = lib->settings->get_int(lib->settings,
                                                                         "charon.filelog.%s.default", 1, filename);
                for (group = 0; group < DBG_MAX; group++)
@@ -349,10 +330,11 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
        if (!loggers_defined)
        {
                /* set up default stdout file_logger */
-               file_logger = file_logger_create(stdout, NULL, FALSE);
+               file_logger = file_logger_create("stdout");
+               file_logger->open(file_logger, FALSE, FALSE);
                charon->file_loggers->insert_last(charon->file_loggers, file_logger);
                /* set up default daemon sys_logger */
-               sys_logger = sys_logger_create(LOG_DAEMON, FALSE);
+               sys_logger = sys_logger_create(LOG_DAEMON);
                charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger);
                for (group = 0; group < DBG_MAX; group++)
                {
@@ -366,7 +348,7 @@ static void initialize_loggers(bool use_stderr, level_t levels[])
                charon->bus->add_logger(charon->bus, &sys_logger->logger);
 
                /* set up default auth sys_logger */
-               sys_logger = sys_logger_create(LOG_AUTHPRIV, FALSE);
+               sys_logger = sys_logger_create(LOG_AUTHPRIV);
                sys_logger->set_level(sys_logger, DBG_ANY, LEVEL_AUDIT);
                charon->sys_loggers->insert_last(charon->sys_loggers, sys_logger);
                charon->bus->add_logger(charon->bus, &sys_logger->logger);
index 8df5d6f..bb4c5ed 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "hooks/hook.h"
 
+#include <bus/listeners/file_logger.h>
 #include <threading/thread.h>
 #include <credentials/certificates/x509.h>
 
@@ -383,7 +384,6 @@ static void load_loggers(file_logger_t *logger)
 {
        enumerator_t *enumerator;
        char *section;
-       FILE *file;
 
        load_log_levels(logger, "stdout");
 
@@ -392,14 +392,9 @@ static void load_loggers(file_logger_t *logger)
        {
                if (!streq(section, "stdout"))
                {
-                       file = fopen(section, "w");
-                       if (file == NULL)
-                       {
-                               fprintf(stderr, "opening file %s for logging failed: %s",
-                                               section, strerror(errno));
-                               continue;
-                       }
-                       logger = file_logger_create(file, NULL, FALSE);
+                       logger = file_logger_create(section);
+                       logger->set_options(logger, NULL, FALSE);
+                       logger->open(logger, FALSE, FALSE);
                        load_log_levels(logger, section);
                        charon->bus->add_logger(charon->bus, &logger->logger);
                        conftest->loggers->insert_last(conftest->loggers, logger);
@@ -447,7 +442,9 @@ int main(int argc, char *argv[])
        );
        lib->credmgr->add_set(lib->credmgr, &conftest->creds->set);
 
-       logger = file_logger_create(stdout, NULL, FALSE);
+       logger = file_logger_create("stdout");
+       logger->set_options(logger, NULL, FALSE);
+       logger->open(logger, FALSE, FALSE);
        logger->set_level(logger, DBG_ANY, LEVEL_CTRL);
        charon->bus->add_logger(charon->bus, &logger->logger);
        conftest->loggers->insert_last(conftest->loggers, logger);
index 1fde988..1756eda 100644 (file)
@@ -136,20 +136,10 @@ static void initialize_logger(char *logfile)
 {
        file_logger_t *file_logger;
        debug_t group;
-       FILE *file;
 
-       /* truncate an existing file */
-       file = fopen(logfile, "w");
-       if (!file)
-       {
-               DBG1(DBG_DMN, "opening file %s for logging failed: %s",
-                        logfile, strerror(errno));
-               return;
-       }
-       /* flush each line */
-       setlinebuf(file);
-
-       file_logger = file_logger_create(file, "%b %e %T", FALSE);
+       file_logger = file_logger_create(logfile);
+       file_logger->set_options(file_logger, "%b %e %T", FALSE);
+       file_logger->open(file_logger, TRUE, FALSE);
        for (group = 0; group < DBG_MAX; group++)
        {
                file_logger->set_level(file_logger, group, ANDROID_DEBUG_LEVEL);
index 9c8458e..68a386d 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
 
 #include "file_logger.h"
 
+#include <daemon.h>
 #include <threading/mutex.h>
+#include <threading/rwlock.h>
 
 typedef struct private_file_logger_t private_file_logger_t;
 
@@ -35,7 +40,12 @@ struct private_file_logger_t {
        file_logger_t public;
 
        /**
-        * output file
+        * File name of the target
+        */
+       char *filename;
+
+       /**
+        * Current output file
         */
        FILE *out;
 
@@ -58,6 +68,11 @@ struct private_file_logger_t {
         * Mutex to ensure multi-line log messages are not torn apart
         */
        mutex_t *mutex;
+
+       /**
+        * Lock to read/write options (FD, levels, time_format, etc.)
+        */
+       rwlock_t *lock;
 };
 
 METHOD(logger_t, log_, void,
@@ -69,6 +84,12 @@ METHOD(logger_t, log_, void,
        struct tm tm;
        time_t t;
 
+       this->lock->read_lock(this->lock);
+       if (!this->out)
+       {       /* file is not open */
+               this->lock->unlock(this->lock);
+               return;
+       }
        if (this->time_format)
        {
                t = time(NULL);
@@ -117,17 +138,24 @@ METHOD(logger_t, log_, void,
                current = next + 1;
        }
        this->mutex->unlock(this->mutex);
+       this->lock->unlock(this->lock);
 }
 
 METHOD(logger_t, get_level, level_t,
        private_file_logger_t *this, debug_t group)
 {
-       return this->levels[group];
+       level_t level;
+
+       this->lock->read_lock(this->lock);
+       level = this->levels[group];
+       this->lock->unlock(this->lock);
+       return level;
 }
 
 METHOD(file_logger_t, set_level, void,
        private_file_logger_t *this, debug_t group, level_t level)
 {
+       this->lock->write_lock(this->lock);
        if (group < DBG_ANY)
        {
                this->levels[group] = level;
@@ -139,23 +167,81 @@ METHOD(file_logger_t, set_level, void,
                        this->levels[group] = level;
                }
        }
+       this->lock->unlock(this->lock);
 }
 
-METHOD(file_logger_t, destroy, void,
-       private_file_logger_t *this)
+METHOD(file_logger_t, set_options, void,
+       private_file_logger_t *this, char *time_format, bool ike_name)
 {
-       if (this->out != stdout && this->out != stderr)
+       this->lock->write_lock(this->lock);
+       free(this->time_format);
+       this->time_format = strdupnull(time_format);
+       this->ike_name = ike_name;
+       this->lock->unlock(this->lock);
+}
+
+/**
+ * Close the current file, if any
+ */
+static void close_file(private_file_logger_t *this)
+{
+       if (this->out && this->out != stdout && this->out != stderr)
        {
                fclose(this->out);
+               this->out = NULL;
+       }
+}
+
+METHOD(file_logger_t, open_, void,
+       private_file_logger_t *this, bool flush_line, bool append)
+{
+       FILE *file;
+
+       if (streq(this->filename, "stderr"))
+       {
+               file = stderr;
+       }
+       else if (streq(this->filename, "stdout"))
+       {
+               file = stdout;
+       }
+       else
+       {
+               file = fopen(this->filename, append ? "a" : "w");
+               if (file == NULL)
+               {
+                       DBG1(DBG_DMN, "opening file %s for logging failed: %s",
+                                this->filename, strerror(errno));
+                       return;
+               }
+               if (flush_line)
+               {
+                       setlinebuf(file);
+               }
        }
+       this->lock->write_lock(this->lock);
+       close_file(this);
+       this->out = file;
+       this->lock->unlock(this->lock);
+}
+
+METHOD(file_logger_t, destroy, void,
+       private_file_logger_t *this)
+{
+       this->lock->write_lock(this->lock);
+       close_file(this);
+       this->lock->unlock(this->lock);
        this->mutex->destroy(this->mutex);
+       this->lock->destroy(this->lock);
+       free(this->time_format);
+       free(this->filename);
        free(this);
 }
 
 /*
  * Described in header.
  */
-file_logger_t *file_logger_create(FILE *out, char *time_format, bool ike_name)
+file_logger_t *file_logger_create(char *filename)
 {
        private_file_logger_t *this;
 
@@ -166,16 +252,16 @@ file_logger_t *file_logger_create(FILE *out, char *time_format, bool ike_name)
                                .get_level = _get_level,
                        },
                        .set_level = _set_level,
+                       .set_options = _set_options,
+                       .open = _open_,
                        .destroy = _destroy,
                },
-               .out = out,
-               .time_format = time_format,
-               .ike_name = ike_name,
+               .filename = strdup(filename),
                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+               .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
        );
 
        set_level(this, DBG_ANY, LEVEL_SILENT);
 
        return &this->public;
 }
-
index 85a2690..9e5aed5 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2012 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -44,6 +45,22 @@ struct file_logger_t {
        void (*set_level) (file_logger_t *this, debug_t group, level_t level);
 
        /**
+        * Set options used by this logger
+        *
+        * @param time_format   format of timestamp prefix, as in strftime(), cloned
+        * @param ike_name              TRUE to prefix the name of the IKE_SA
+        */
+       void (*set_options) (file_logger_t *this, char *time_format, bool ike_name);
+
+       /**
+        * Open (or reopen) the log file according to the given parameters
+        *
+        * @param flush_line    TRUE to flush buffers after every logged line
+        * @param append                FALSE to overwrite an existing file, TRUE to append
+        */
+       void (*open) (file_logger_t *this, bool flush_line, bool append);
+
+       /**
         * Destroys a file_logger_t object.
         */
        void (*destroy) (file_logger_t *this);
@@ -52,11 +69,13 @@ struct file_logger_t {
 /**
  * Constructor to create a file_logger_t object.
  *
- * @param out                  FILE to write to
- * @param time_format  format of timestamp prefix, as in strftime()
- * @param ike_name             TRUE to prefix the name of the IKE_SA
- * @return                             file_logger_t object
+ * The logger has to be opened via file_logger_t.open() before anything is
+ * logged.
+ *
+ * @param filename     name of the log file (stderr and stdout are handled
+ *                                     specially), cloned
+ * @return                     file_logger_t object
  */
-file_logger_t *file_logger_create(FILE *out, char *time_format, bool ike_name);
+file_logger_t *file_logger_create(char *filename);
 
 #endif /** FILE_LOGGER_H_ @}*/
index 53fdefe..82e2c8e 100644 (file)
@@ -21,6 +21,7 @@
 #include "sys_logger.h"
 
 #include <threading/mutex.h>
+#include <threading/rwlock.h>
 
 typedef struct private_sys_logger_t private_sys_logger_t;
 
@@ -53,6 +54,11 @@ struct private_sys_logger_t {
         * Mutex to ensure multi-line log messages are not torn apart
         */
        mutex_t *mutex;
+
+       /**
+        * Lock to read/write options (levels, ike_name)
+        */
+       rwlock_t *lock;
 };
 
 METHOD(logger_t, log_, void,
@@ -65,6 +71,7 @@ METHOD(logger_t, log_, void,
        /* cache group name and optional name string */
        snprintf(groupstr, sizeof(groupstr), "%N", debug_names, group);
 
+       this->lock->read_lock(this->lock);
        if (this->ike_name && ike_sa)
        {
                if (ike_sa->get_peer_cfg(ike_sa))
@@ -78,6 +85,7 @@ METHOD(logger_t, log_, void,
                                ike_sa->get_unique_id(ike_sa));
                }
        }
+       this->lock->unlock(this->lock);
 
        /* do a syslog for every line */
        this->mutex->lock(this->mutex);
@@ -100,12 +108,18 @@ METHOD(logger_t, log_, void,
 METHOD(logger_t, get_level, level_t,
        private_sys_logger_t *this, debug_t group)
 {
-       return this->levels[group];
+       level_t level;
+
+       this->lock->read_lock(this->lock);
+       level = this->levels[group];
+       this->lock->unlock(this->lock);
+       return level;
 }
 
 METHOD(sys_logger_t, set_level, void,
        private_sys_logger_t *this, debug_t group, level_t level)
 {
+       this->lock->write_lock(this->lock);
        if (group < DBG_ANY)
        {
                this->levels[group] = level;
@@ -117,12 +131,21 @@ METHOD(sys_logger_t, set_level, void,
                        this->levels[group] = level;
                }
        }
+       this->lock->unlock(this->lock);
+}
+
+METHOD(sys_logger_t, set_options, void,
+       private_sys_logger_t *this, bool ike_name)
+{
+       this->lock->write_lock(this->lock);
+       this->ike_name = ike_name;
+       this->lock->unlock(this->lock);
 }
 
 METHOD(sys_logger_t, destroy, void,
        private_sys_logger_t *this)
 {
-       closelog();
+       this->lock->destroy(this->lock);
        this->mutex->destroy(this->mutex);
        free(this);
 }
@@ -130,7 +153,7 @@ METHOD(sys_logger_t, destroy, void,
 /*
  * Described in header.
  */
-sys_logger_t *sys_logger_create(int facility, bool ike_name)
+sys_logger_t *sys_logger_create(int facility)
 {
        private_sys_logger_t *this;
 
@@ -141,11 +164,12 @@ sys_logger_t *sys_logger_create(int facility, bool ike_name)
                                .get_level = _get_level,
                        },
                        .set_level = _set_level,
+                       .set_options = _set_options,
                        .destroy = _destroy,
                },
                .facility = facility,
-               .ike_name = ike_name,
                .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+               .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
        );
 
        set_level(this, DBG_ANY, LEVEL_SILENT);
index fcb6655..9a0fee0 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2012 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -44,6 +45,13 @@ struct sys_logger_t {
        void (*set_level) (sys_logger_t *this, debug_t group, level_t level);
 
        /**
+        * Set options used by this logger.
+        *
+        * @param ike_name      TRUE to prefix the name of the IKE_SA
+        */
+       void (*set_options) (sys_logger_t *this, bool ike_name);
+
+       /**
         * Destroys a sys_logger_t object.
         */
        void (*destroy) (sys_logger_t *this);
@@ -53,9 +61,8 @@ struct sys_logger_t {
  * Constructor to create a sys_logger_t object.
  *
  * @param facility     syslog facility to use
- * @param ike_name     TRUE to prefix the name of the IKE_SA
  * @return                     sys_logger_t object
  */
-sys_logger_t *sys_logger_create(int facility, bool ike_name);
+sys_logger_t *sys_logger_create(int facility);
 
 #endif /** SYS_LOGGER_H_ @}*/