Add features (incomplete, highly experimental), fix DundiLookup app, debug improvemen...
[asterisk/asterisk.git] / logger.c
index e11dd61..7f32b70 100755 (executable)
--- a/logger.c
+++ b/logger.c
 #include <asterisk/config.h>
 #include <asterisk/term.h>
 #include <asterisk/cli.h>
+#include <asterisk/utils.h>
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
-#include <pthread.h>
 #include <sys/stat.h>
 #include "asterisk.h"
 #include "astconf.h"
@@ -39,31 +39,43 @@ static int syslog_level_map[] = {
        LOG_NOTICE,
        LOG_WARNING,
        LOG_ERR,
-        LOG_DEBUG
+       LOG_DEBUG
 };
+
 #define SYSLOG_NLEVELS 6
 
 #include <asterisk/logger.h>
 
 #define MAX_MSG_QUEUE 200
 
-static ast_mutex_t msglist_lock = AST_MUTEX_INITIALIZER;
-static ast_mutex_t loglock = AST_MUTEX_INITIALIZER;
+#ifdef __linux__
+#include <asm/unistd.h>
+#define GETTID() syscall(__NR_gettid)
+#else
+#define GETTID() getpid()
+#endif
+
+static char dateformat[256] = "%b %e %T";              /* Original Asterisk Format */
+AST_MUTEX_DEFINE_STATIC(msglist_lock);
+AST_MUTEX_DEFINE_STATIC(loglock);
 static int pending_logger_reload = 0;
+static int global_logmask = -1;
 
 static struct msglist {
        char *msg;
        struct msglist *next;
 } *list = NULL, *last = NULL;
 
+static char hostname[256];
+
 struct logchannel {
-        int logmask;
-        int facility; /* syslog */
+       int logmask;
+       int facility; /* syslog */
        int syslog; /* syslog flag */
-        int console;  /* console logging */
+       int console;  /* console logging */
        FILE *fileptr; /* logfile logging */
        char filename[256];
-        struct logchannel *next;
+       struct logchannel *next;
 };
 
 static struct logchannel *logchannels = NULL;
@@ -73,21 +85,21 @@ static int msgcnt = 0;
 static FILE *eventlog = NULL;
 
 static char *levels[] = {
-       "DEBUG",
-       "EVENT",
-       "NOTICE",
-       "WARNING",
-       "ERROR",
-       "VERBOSE"
+       "DEBUG",
+       "EVENT",
+       "NOTICE",
+       "WARNING",
+       "ERROR",
+       "VERBOSE"
 };
 
 static int colors[] = {
-       COLOR_BRGREEN,
-       COLOR_BRBLUE,
-       COLOR_YELLOW,
-       COLOR_BRRED,
-       COLOR_RED,
-       COLOR_GREEN
+       COLOR_BRGREEN,
+       COLOR_BRBLUE,
+       COLOR_YELLOW,
+       COLOR_BRRED,
+       COLOR_RED,
+       COLOR_GREEN
 };
 
 static int make_components(char *s, int lineno)
@@ -126,7 +138,7 @@ static struct logchannel *make_logchannel(char *channel, char *components, int l
        char *facility;
        CODE *cptr;
 
-       if (!strlen(channel))
+       if (ast_strlen_zero(channel))
                return NULL;
        chan = malloc(sizeof(struct logchannel));
 
@@ -165,10 +177,19 @@ static struct logchannel *make_logchannel(char *channel, char *components, int l
                    chan->syslog = 1;
                    openlog("asterisk", LOG_PID, chan->facility);
                } else {
-                       if (channel[0] == '/') 
-                               strncpy(chan->filename, channel, sizeof(chan->filename) - 1);
-                       else
+                       if (channel[0] == '/') {
+                               if(!ast_strlen_zero(hostname)) { 
+                                       snprintf(chan->filename, sizeof(chan->filename) - 1,"%s.%s", channel, hostname);
+                               } else {
+                                       strncpy(chan->filename, channel, sizeof(chan->filename) - 1);
+                               }
+                       }                 
+                       
+                       if(!ast_strlen_zero(hostname)) {
+                               snprintf(chan->filename, sizeof(chan->filename), "%s/%s.%s",(char *)ast_config_AST_LOG_DIR, channel, hostname);
+                       } else {
                                snprintf(chan->filename, sizeof(chan->filename), "%s/%s", (char *)ast_config_AST_LOG_DIR, channel);
+                       }
                        chan->fileptr = fopen(chan->filename, "a");
                        if (!chan->fileptr) {
                                /* Can't log here, since we're called with a lock */
@@ -185,6 +206,7 @@ static void init_logger_chain(void)
        struct logchannel *chan, *cur;
        struct ast_config *cfg;
        struct ast_variable *var;
+       char *s;
 
        /* delete our list of log channels */
        ast_mutex_lock(&loglock);
@@ -196,23 +218,39 @@ static void init_logger_chain(void)
        }
        logchannels = NULL;
        ast_mutex_unlock(&loglock);
-
+       
+       global_logmask = 0;
        /* close syslog */
        closelog();
-
+       
        cfg = ast_load("logger.conf");
        
        /* If no config file, we're fine */
        if (!cfg)
            return;
-
+       
        ast_mutex_lock(&loglock);
+       if ((s = ast_variable_retrieve(cfg, "general", "appendhostname"))) {
+               if(ast_true(s)) {
+                       if(gethostname(hostname, sizeof(hostname))) {
+                               strncpy(hostname, "unknown", sizeof(hostname)-1);
+                               ast_log(LOG_WARNING, "What box has no hostname???\n");
+                       }
+               } else
+                       hostname[0] = '\0';
+       } else
+               hostname[0] = '\0';
+       if ((s = ast_variable_retrieve(cfg, "general", "dateformat"))) {
+               strncpy(dateformat, s, sizeof(dateformat) - 1);
+       } else
+               strncpy(dateformat, "%b %e %T", sizeof(dateformat) - 1);
        var = ast_variable_browse(cfg, "logfiles");
        while(var) {
                chan = make_logchannel(var->name, var->value, var->lineno);
                if (chan) {
                        chan->next = logchannels;
                        logchannels = chan;
+                       global_logmask |= chan->logmask;
                }
                var = var->next;
        }
@@ -222,7 +260,7 @@ static void init_logger_chain(void)
 }
 
 static FILE *qlog = NULL;
-static ast_mutex_t qloglock = AST_MUTEX_INITIALIZER;
+AST_MUTEX_DEFINE_STATIC(qloglock);
 
 void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt, ...)
 {
@@ -260,7 +298,7 @@ static void queue_log_init(void)
 
 int reload_logger(int rotate)
 {
-       char old[AST_CONFIG_MAX_PATH];
+       char old[AST_CONFIG_MAX_PATH] = "";
        char new[AST_CONFIG_MAX_PATH];
        struct logchannel *f;
        FILE *myf;
@@ -301,7 +339,7 @@ int reload_logger(int rotate)
                        fclose(f->fileptr);
                        f->fileptr = NULL;
                        if(rotate) {
-                               strncpy(old, f->filename, sizeof(old));
+                               strncpy(old, f->filename, sizeof(old) - 1);
        
                                for(x=0;;x++) {
                                        snprintf(new, sizeof(new), "%s.%d", f->filename, x);
@@ -371,7 +409,7 @@ static char logger_reload_help[] =
 "       Reloads the logger subsystem state.  Use after restarting syslogd(8)\n";
 
 static char logger_rotate_help[] =
-"Usage: logger reload\n"
+"Usage: logger rotate\n"
 "       Rotates and Reopens the log files.\n";
 
 static struct ast_cli_entry reload_logger_cli = 
@@ -384,10 +422,11 @@ static struct ast_cli_entry rotate_logger_cli =
        handle_logger_rotate, "Rotates and reopens the log files",
        logger_rotate_help };
 
-static int handle_SIGXFSZ(int sig) {
+static int handle_SIGXFSZ(int sig) 
+{
        /* Indicate need to reload */
        pending_logger_reload = 1;
-    return 0;
+       return 0;
 }
 
 int init_logger(void)
@@ -417,30 +456,49 @@ int init_logger(void)
        } else 
                ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno));
 
-       init_logger_chain();
-
        /* create log channels */
        init_logger_chain();
        return -1;
 }
 
-static void ast_log_vsyslog(int level, const char *file, int line, const char *function, const char *fmt, va_list args) {
-    char buf[BUFSIZ];
+void close_logger(void)
+{
+       struct msglist *m, *tmp;
 
-    if(level >= SYSLOG_NLEVELS) {
-           /* we are locked here, so cannot ast_log() */
-           fprintf(stderr, "ast_log_vsyslog called with bogus level: %d\n", level);
-           return;
-    }
-    if(level == __LOG_VERBOSE) {
-       snprintf(buf, sizeof(buf), "VERBOSE[%ld]: ", (long)pthread_self());
-       level = __LOG_DEBUG;
-    } else {
-       snprintf(buf, sizeof(buf), "%s[%ld]: %s:%d in %s: ",
-                levels[level], (long)pthread_self(), file, line, function);
-    }
-    vsnprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), fmt, args);
-    syslog(syslog_level_map[level], "%s", buf);
+       ast_mutex_lock(&msglist_lock);
+       m = list;
+       while(m) {
+               if (m->msg) {
+                       free(m->msg);
+               }
+               tmp = m->next;
+               free(m);
+               m = tmp;
+       }
+       list = last = NULL;
+       msgcnt = 0;
+       ast_mutex_unlock(&msglist_lock);
+       return;
+}
+
+static void ast_log_vsyslog(int level, const char *file, int line, const char *function, const char *fmt, va_list args) 
+{
+       char buf[BUFSIZ];
+
+       if (level >= SYSLOG_NLEVELS) {
+               /* we are locked here, so cannot ast_log() */
+               fprintf(stderr, "ast_log_vsyslog called with bogus level: %d\n", level);
+               return;
+       }
+       if (level == __LOG_VERBOSE) {
+               snprintf(buf, sizeof(buf), "VERBOSE[%ld]: ", (long)GETTID());
+               level = __LOG_DEBUG;
+       } else {
+               snprintf(buf, sizeof(buf), "%s[%ld]: %s:%d in %s: ",
+                       levels[level], (long)GETTID(), file, line, function);
+       }
+       vsnprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), fmt, args);
+       syslog(syslog_level_map[level], "%s", buf);
 }
 
 /*
@@ -448,97 +506,99 @@ static void ast_log_vsyslog(int level, const char *file, int line, const char *f
  */
 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
 {
-    struct logchannel *chan;
-    char buf[BUFSIZ];
-    time_t t;
-    struct tm tm;
-    char date[256];
+       struct logchannel *chan;
+       char buf[BUFSIZ];
+       time_t t;
+       struct tm tm;
+       char date[256];
 
-    va_list ap;
+       va_list ap;
        
-    if (!option_verbose && !option_debug && (level == __LOG_DEBUG)) {
-       return;
-    }
-
-    /* begin critical section */
-    ast_mutex_lock(&loglock);
-
-    time(&t);
-    localtime_r(&t, &tm);
-    strftime(date, sizeof(date), "%b %e %T", &tm);
+       if (!option_verbose && !option_debug && (level == __LOG_DEBUG)) {
+               return;
+       }
+       /* Ignore anything that never gets logged anywhere */
+       if (!(global_logmask & (1 << level)))
+               return;
 
+       /* begin critical section */
+       ast_mutex_lock(&loglock);
 
-    if (level == __LOG_EVENT) {
-           va_start(ap, fmt);
+       time(&t);
+       localtime_r(&t, &tm);
+       strftime(date, sizeof(date), dateformat, &tm);
 
-           fprintf(eventlog, "%s asterisk[%d]: ", date, getpid());
-           vfprintf(eventlog, fmt, ap);
-           fflush(eventlog);
+       if (level == __LOG_EVENT) {
+               va_start(ap, fmt);
 
-           va_end(ap);
-           ast_mutex_unlock(&loglock);
-           return;
-    }
+               fprintf(eventlog, "%s asterisk[%d]: ", date, getpid());
+               vfprintf(eventlog, fmt, ap);
+               fflush(eventlog);
 
-    if (logchannels) {
-       chan = logchannels;
-       while(chan) {
-           if (chan->syslog && (chan->logmask & (1 << level))) {
-               va_start(ap, fmt);
-               ast_log_vsyslog(level, file, line, function, fmt, ap);
                va_end(ap);
-           } else if ((chan->logmask & (1 << level)) && (chan->console)) {
-               char linestr[128];
-               char tmp1[80], tmp2[80], tmp3[80], tmp4[80];
-
-               if(level != __LOG_VERBOSE) {
-                   sprintf(linestr, "%d", line);
-                   snprintf(buf, sizeof(buf), "%s %s[%ld]: %s:%s %s: ",
-                            date,
-                            term_color(tmp1, levels[level], colors[level], 0, sizeof(tmp1)),
-                            (long)pthread_self(),
-                            term_color(tmp2, file, COLOR_BRWHITE, 0, sizeof(tmp2)),
-                            term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)),
-                            term_color(tmp4, function, COLOR_BRWHITE, 0, sizeof(tmp4)));
+               ast_mutex_unlock(&loglock);
+               return;
+       }
+
+       if (logchannels) {
+               chan = logchannels;
+               while(chan) {
+                       if (chan->syslog && (chan->logmask & (1 << level))) {
+                               va_start(ap, fmt);
+                               ast_log_vsyslog(level, file, line, function, fmt, ap);
+                               va_end(ap);
+                       } else if ((chan->logmask & (1 << level)) && (chan->console)) {
+                               char linestr[128];
+                               char tmp1[80], tmp2[80], tmp3[80], tmp4[80];
+
+                               if (level != __LOG_VERBOSE) {
+                                       sprintf(linestr, "%d", line);
+                                       snprintf(buf, sizeof(buf), "%s %s[%ld]: %s:%s %s: ",
+                                               date,
+                                               term_color(tmp1, levels[level], colors[level], 0, sizeof(tmp1)),
+                                               (long)GETTID(),
+                                               term_color(tmp2, file, COLOR_BRWHITE, 0, sizeof(tmp2)),
+                                               term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)),
+                                               term_color(tmp4, function, COLOR_BRWHITE, 0, sizeof(tmp4)));
                    
-                   ast_console_puts(buf);
-                   va_start(ap, fmt);
-                   vsnprintf(buf, sizeof(buf), fmt, ap);
-                   va_end(ap);
-                   ast_console_puts(buf);
+                                       ast_console_puts(buf);
+                                       va_start(ap, fmt);
+                                       vsnprintf(buf, sizeof(buf), fmt, ap);
+                                       va_end(ap);
+                                       ast_console_puts(buf);
+                               }
+                       } else if ((chan->logmask & (1 << level)) && (chan->fileptr)) {
+                               snprintf(buf, sizeof(buf), "%s %s[%ld]: ", date,
+                                       levels[level], (long)GETTID());
+                               fprintf(chan->fileptr, buf);
+                               va_start(ap, fmt);
+                               vsnprintf(buf, sizeof(buf), fmt, ap);
+                               va_end(ap);
+                               fputs(buf, chan->fileptr);
+                               fflush(chan->fileptr);
+                       }
+                       chan = chan->next;
                }
-           } else if ((chan->logmask & (1 << level)) && (chan->fileptr)) {
-                   snprintf(buf, sizeof(buf), "%s %s[%ld]: ", date,
-                            levels[level], (long)pthread_self());
-                   fprintf(chan->fileptr, buf);
-                   va_start(ap, fmt);
-                   vsnprintf(buf, sizeof(buf), fmt, ap);
-                   va_end(ap);
-                   fputs(buf, chan->fileptr);
-                   fflush(chan->fileptr);
-           }
-           chan = chan->next;
-       }
-    } else {
-           /* 
-            * we don't have the logger chain configured yet,
-            * so just log to stdout 
-            */
+       } else {
+               /* 
+                * we don't have the logger chain configured yet,
+                * so just log to stdout 
+               */
                if (level != __LOG_VERBOSE) {
-                   va_start(ap, fmt);
-                   vsnprintf(buf, sizeof(buf), fmt, ap);
-                   va_end(ap);
-                   fputs(buf, stdout);
+                       va_start(ap, fmt);
+                       vsnprintf(buf, sizeof(buf), fmt, ap);
+                       va_end(ap);
+                       fputs(buf, stdout);
                }
-    }
+       }
 
-    ast_mutex_unlock(&loglock);
-    /* end critical section */
+       ast_mutex_unlock(&loglock);
+       /* end critical section */
        if (pending_logger_reload) {
-           reload_logger(1);
-           ast_log(LOG_EVENT,"Rotated Logs Per SIGXFSZ\n");
-           if (option_verbose)
-                   ast_verbose("Rotated Logs Per SIGXFSZ\n");
+               reload_logger(1);
+               ast_log(LOG_EVENT,"Rotated Logs Per SIGXFSZ\n");
+               if (option_verbose)
+                       ast_verbose("Rotated Logs Per SIGXFSZ\n");
        }
 }
 
@@ -609,8 +669,8 @@ extern void ast_verbose(const char *fmt, ...)
 int ast_verbose_dmesg(void (*v)(const char *string, int opos, int replacelast, int complete))
 {
        struct msglist *m;
-       m = list;
        ast_mutex_lock(&msglist_lock);
+       m = list;
        while(m) {
                /* Send all the existing entries that we have queued (i.e. they're likely to have missed) */
                v(m->msg, 0, 0, 1);