Add logging to file
authorfatbob313 <martin@fatbob.nu>
Sun, 13 Feb 2011 16:44:45 +0000 (16:44 +0000)
committerfatbob313 <martin@fatbob.nu>
Sun, 13 Feb 2011 16:44:45 +0000 (16:44 +0000)
src/conf.c
src/conf.h
src/log.c
src/log.h
src/main.c

index 35926473f9cbd81faffc24964a335e1801ca7b5d..9e5006359b2bbc92846f508f7631532ef1da5f7d 100644 (file)
@@ -158,6 +158,17 @@ const char *getStrConf(param_t param)
                        return "";
                }
                break;
+       case LOGFILE:
+               setting = config_lookup(&configuration, "logfile");
+               if (!setting)
+                       return NULL;
+               else {
+                       if ((strsetting = config_setting_get_string(setting)) != NULL)
+                               return strsetting;
+                       else
+                       return NULL;
+               }
+               break;
        default:
                doAssert(false);
                break;
index 6e0a6662a8e106894905987dadea2903d1b577c7..6d7bacffd258484e67976666b09b96ce42cf156b 100644 (file)
@@ -45,6 +45,7 @@ typedef enum param {
        DEFAULT_CHANNEL,
        USERNAME,
        GROUPNAME,
+       LOGFILE,
 } param_t;
 
 typedef struct {
index 5d2af2b8bf295e2b80f1fc0c7c6dfcdd540c8563..39b9cf9e48bc3f8fcc0bf943735d9ce2c798bcfd 100644 (file)
--- a/src/log.c
+++ b/src/log.c
 #include <stdlib.h>
 #include <syslog.h>
 #include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include "log.h"
+#include "conf.h"
 
 #define STRSIZE 254
 
-static bool_t termprint;
+static bool_t termprint, init;
+static FILE *logfile;
+
+static void openlogfile(const char *logfilename)
+{
+       int fd, flags;
+       logfile = fopen(logfilename, "a");
+       if (logfile == NULL) {
+               Log_fatal("Failed to open log file '%s' for writing: %s\n", logfilename, strerror(errno));
+       }
+
+       /* XXX - Is it neccessary/appropriate that logging to file is non-blocking?
+        * If not, there's a risk that execution blocks, meaning that voice blocks
+        * as well since uMurmur is single threaded by design. OTOH, what could
+        * cause a block? If the disk causes blocking, it is probably br0ken. but
+        * the log could be on a nfs or smb share, so let's set it up as
+        * non-blocking and we'll see what happens.
+        */
+       fd = fileno(logfile);
+       flags = fcntl(fd, F_GETFL, 0);
+       fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+}
 
 void Log_init(bool_t terminal)
 {
-       termprint = terminal;
-       if (!termprint)
-               openlog("uMurmurd", LOG_PID, LOG_DAEMON);
+       const char *logfilename;
+       
+       termprint = terminal;           
+       if (termprint)
+               return;
+       
+       logfilename = getStrConf(LOGFILE);
+       if (logfilename != NULL) {
+               openlogfile(logfilename);
+       }
+       else openlog("uMurmurd", LOG_PID, LOG_DAEMON);
+       init = true;
 }
 
 void Log_free()
 {
-       if (!termprint)
+       if (termprint)
+               return;
+       else if (logfile)
+               fclose(logfile);
+       else 
                closelog();
 }
                
+void Log_reset()
+{
+       const char *logfilename;
+       
+       if (logfile) {
+               logfilename = getStrConf(LOGFILE);
+               fclose(logfile);
+               openlogfile(logfilename);
+       }
+}
 
 void logthis(const char *logstring, ...)
 {
@@ -65,6 +112,8 @@ void logthis(const char *logstring, ...)
        va_end(argp);
        if (termprint)
                fprintf(stderr, "%s\n", buf);
+       else if (logfile)
+               fprintf(logfile, "%s\n", buf);
        else
                syslog(LOG_INFO, "%s", buf);
 }
@@ -81,6 +130,8 @@ void Log_warn(const char *logstring, ...)
        va_end(argp);
        if (termprint)
                fprintf(stderr, "%s\n", buf);
+       else if (logfile)
+               fprintf(logfile, "%s\n", buf);
        else
                syslog(LOG_WARNING, "%s", buf);
 }
@@ -97,9 +148,14 @@ void Log_info(const char *logstring, ...)
        va_end(argp);
        if (termprint)
                fprintf(stderr, "%s\n", buf);
+       else if (logfile) {
+               fprintf(logfile, "%s\n", buf);
+               fflush(logfile);
+       }
        else
                syslog(LOG_INFO, "%s", buf);
 }
+
 void Log_info_client(client_t *client, const char *logstring, ...)
 {
        va_list argp;
@@ -117,9 +173,10 @@ void Log_info_client(client_t *client, const char *logstring, ...)
                                           ntohs(client->remote_tcp.sin_port));
        if (termprint)
                fprintf(stderr, "%s\n", buf);
+       else if (logfile)
+               fprintf(logfile, "%s\n", buf);
        else
                syslog(LOG_INFO, "%s", buf);
-       
 }
 
 #ifdef DEBUG
@@ -135,6 +192,8 @@ void Log_debug(const char *logstring, ...)
        va_end(argp);
        if (termprint)
                fprintf(stderr, "%s\n", buf);
+       else if (logfile)
+               fprintf(logfile, "%s\n", buf);
        else
                syslog(LOG_DEBUG, "%s", buf);
 }
@@ -151,7 +210,15 @@ void Log_fatal(const char *logstring, ...)
        va_end(argp);
        if (termprint)
                fprintf(stderr, "%s\n", buf);
-       else
+       else if (logfile)
+               fprintf(logfile, "%s\n", buf);
+       else { /* If logging subsystem is not initialized, fall back to syslog logging
+                       * for fatal errors. Only config file reading that needs this currently.
+                       */
+               if (!init)
+                       openlog("uMurmurd", LOG_PID, LOG_DAEMON);
                syslog(LOG_CRIT, "%s", buf);
+       }
+       
        exit(1);
 }
index 3d74722e0b52503ce4ad63fbd73a69ddb16b230b..8bfc5b66692acc76686bb6a3143e2d3e70026f6e 100644 (file)
--- a/src/log.h
+++ b/src/log.h
@@ -56,6 +56,7 @@ void Log_info_client(client_t *client, const char *logstring, ...);
 void Log_fatal(const char *logstring, ...);
 
 void Log_init(bool_t terminal);
+void Log_reset();
 void Log_free();
 
 #endif
index cef4f605a4d2e88877d7e488dbb83302e378f962..aaf1e0d3efc7caaa49a355e695a574ea15065cdf 100644 (file)
@@ -163,8 +163,8 @@ void signal_handler(int sig)
 {
        switch(sig) {
        case SIGHUP:
-               /* XXX - do stuff? */
-               Log_info("HUP signal");
+               Log_info("HUP signal received.");
+               Log_reset();
                break;
        case SIGTERM:
                Log_info("TERM signal. Shutting down.");
@@ -277,28 +277,29 @@ int main(int argc, char **argv)
                        break;
                }
        }
-
-       /* Logging to terminal if not daemonizing, otherwise to syslog.
-        * Need to initialize logging before calling Conf_init()
-        */
-       if (!nodaemon)
-               Log_init(false);
-       else
-               Log_init(true);
        
        /* Initialize the config subsystem early;
-        * switch_user() will need to read some config variables.
+        * switch_user() will need to read some config variables as well as logging.
         */
        Conf_init(conffile);
-
+       
+       /* Logging to terminal if not daemonizing, otherwise to syslog or log file.
+        */
        if (!nodaemon) {
                daemonize();
+               Log_init(false);
                if (pidfile != NULL)
                        lockfile(pidfile);
 
                switch_user();
-       }
 
+               /* Reopen log file. If user switch results in access denied, we catch
+                * it early.
+                */
+               Log_reset(); 
+       }
+       else Log_init(true);
+       
        signal(SIGCHLD, SIG_IGN); /* ignore child */
        signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
        signal(SIGTTOU, SIG_IGN);