Added SILC Thread Queue API
[runtime.git] / apps / irssi / src / core / log.c
index 368de25fa51f361c86b7a62cc87ba5e9a3e9c0c2..4d49402e371798e8ae452729ac54dfef5667bc84 100644 (file)
@@ -30,7 +30,7 @@
 #include "lib-config/iconfig.h"
 #include "settings.h"
 
-#define DEFAULT_LOG_FILE_CREATE_MODE 644
+#define DEFAULT_LOG_FILE_CREATE_MODE 600
 
 #ifdef HAVE_FCNTL
 static struct flock lock;
@@ -47,6 +47,7 @@ static const char *log_item_types[] = {
 
 const char *log_timestamp;
 static int log_file_create_mode;
+static int log_dir_create_mode;
 static int rotate_tag;
 
 static int log_item_str2type(const char *type)
@@ -100,6 +101,8 @@ static char *log_filename(LOG_REC *log)
 
 int log_start_logging(LOG_REC *log)
 {
+       char *dir;
+
        g_return_val_if_fail(log != NULL, FALSE);
 
        if (log->handle != -1)
@@ -108,6 +111,16 @@ int log_start_logging(LOG_REC *log)
        /* Append/create log file */
        g_free_not_null(log->real_fname);
        log->real_fname = log_filename(log);
+
+       if (log->real_fname != NULL &&
+           strcmp(log->real_fname, log->fname) != 0) {
+               /* path may contain variables (%time, $vars),
+                  make sure the directory is created */
+               dir = g_dirname(log->real_fname);
+               mkpath(dir, log_dir_create_mode);
+               g_free(dir);
+       }
+
        log->handle = log->real_fname == NULL ? -1 :
                open(log->real_fname, O_WRONLY | O_APPEND | O_CREAT,
                     log_file_create_mode);
@@ -176,6 +189,8 @@ static void log_rotate_check(LOG_REC *log)
        if (strcmp(new_fname, log->real_fname) != 0) {
                /* rotate log */
                log_stop_logging(log);
+               signal_emit("log rotated", 1, log);
+
                log_start_logging(log);
        }
        g_free(new_fname);
@@ -183,6 +198,7 @@ static void log_rotate_check(LOG_REC *log)
 
 void log_write_rec(LOG_REC *log, const char *str, int level)
 {
+        char *colorstr;
        struct tm *tm;
        time_t now;
        int hour, day;
@@ -214,6 +230,11 @@ void log_write_rec(LOG_REC *log, const char *str, int level)
 
        log->last = now;
 
+       if (log->colorizer == NULL)
+               colorstr = NULL;
+        else
+                str = colorstr = log->colorizer(str);
+
         if ((level & MSGLEVEL_LASTLOG) == 0)
                log_write_timestamp(log->handle, log_timestamp, str, now);
        else
@@ -221,6 +242,19 @@ void log_write_rec(LOG_REC *log, const char *str, int level)
        write_buffer(log->handle, "\n", 1);
 
        signal_emit("log written", 2, log, str);
+
+        g_free_not_null(colorstr);
+}
+
+static int itemcmp(const char *patt, const char *item)
+{
+       /* returns 0 on match, nonzero otherwise */
+
+       if (item == NULL)
+               return g_strcasecmp(patt, "*") != 0;
+       if (*patt == '*')
+               return 0;
+        return g_strcasecmp(patt, item);
 }
 
 LOG_ITEM_REC *log_item_find(LOG_REC *log, int type, const char *item,
@@ -229,12 +263,11 @@ LOG_ITEM_REC *log_item_find(LOG_REC *log, int type, const char *item,
        GSList *tmp;
 
        g_return_val_if_fail(log != NULL, NULL);
-       g_return_val_if_fail(item != NULL, NULL);
 
        for (tmp = log->items; tmp != NULL; tmp = tmp->next) {
                LOG_ITEM_REC *rec = tmp->data;
 
-               if (rec->type == type && g_strcasecmp(rec->name, item) == 0 &&
+               if (rec->type == type && itemcmp(rec->name, item) == 0 &&
                    (rec->servertag == NULL || (servertag != NULL &&
                        g_strcasecmp(rec->servertag, servertag) == 0)))
                        return rec;
@@ -243,11 +276,11 @@ LOG_ITEM_REC *log_item_find(LOG_REC *log, int type, const char *item,
        return NULL;
 }
 
-void log_file_write(SERVER_REC *server, const char *item, int level,
+void log_file_write(const char *server_tag, const char *item, int level,
                    const char *str, int no_fallbacks)
 {
        GSList *tmp, *fallbacks;
-       char *tmpstr, *servertag;
+       char *tmpstr;
        int found;
 
        g_return_if_fail(str != NULL);
@@ -255,7 +288,6 @@ void log_file_write(SERVER_REC *server, const char *item, int level,
        if (logs == NULL)
                return;
 
-       servertag = server == NULL ? NULL : server->tag;
        fallbacks = NULL; found = FALSE;
 
        for (tmp = logs; tmp != NULL; tmp = tmp->next) {
@@ -271,13 +303,13 @@ void log_file_write(SERVER_REC *server, const char *item, int level,
                        fallbacks = g_slist_append(fallbacks, rec);
                else if (item != NULL &&
                         log_item_find(rec, LOG_ITEM_TARGET, item,
-                                      servertag) != NULL)
+                                      server_tag) != NULL)
                        log_write_rec(rec, str, level);
        }
 
        if (!found && !no_fallbacks && fallbacks != NULL) {
                /* not found from any items, so write it to all main logs */
-               tmpstr = (level & MSGLEVEL_PUBLIC) ?
+               tmpstr = (level & MSGLEVEL_PUBLIC) && item != NULL ?
                        g_strconcat(item, ": ", str, NULL) :
                        g_strdup(str);
 
@@ -343,6 +375,8 @@ static void log_update_config(LOG_REC *log)
 
        if (log->items != NULL)
                log_items_update_config(log, node);
+
+       signal_emit("log config save", 2, log, node);
 }
 
 static void log_remove_config(LOG_REC *log)
@@ -457,7 +491,8 @@ static void log_items_read_config(CONFIG_NODE *node, LOG_REC *log)
        char *item;
        int type;
 
-       for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
+       tmp = config_node_first(node->value);
+       for (; tmp != NULL; tmp = config_node_next(tmp)) {
                node = tmp->data;
 
                if (node->type != NODE_TYPE_BLOCK)
@@ -500,7 +535,8 @@ static void log_read_config(void)
        node = iconfig_node_traverse("logs", FALSE);
        if (node == NULL) return;
 
-       for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
+       tmp = config_node_first(node->value);
+       for (; tmp != NULL; tmp = config_node_next(tmp)) {
                node = tmp->data;
 
                if (node->type != NODE_TYPE_BLOCK)
@@ -514,6 +550,8 @@ static void log_read_config(void)
                log->autoopen = config_node_get_bool(node, "auto_open", FALSE);
                log->level = level2bits(config_node_get_str(node, "level", 0));
 
+               signal_emit("log config read", 2, log, node);
+
                node = config_node_section(node, "items", -1);
                if (node != NULL)
                        log_items_read_config(node, log);
@@ -530,6 +568,11 @@ static void read_settings(void)
 {
        log_timestamp = settings_get_str("log_timestamp");
        log_file_create_mode = octal2dec(settings_get_int("log_create_mode"));
+
+        log_dir_create_mode = log_file_create_mode;
+        if (log_file_create_mode & 0400) log_dir_create_mode |= 0100;
+        if (log_file_create_mode & 0040) log_dir_create_mode |= 0010;
+        if (log_file_create_mode & 0004) log_dir_create_mode |= 0001;
 }
 
 void log_init(void)
@@ -548,9 +591,9 @@ void log_init(void)
                         "--- Day changed %a %b %d %Y");
 
        read_settings();
-       log_read_config();
         signal_add("setup changed", (SIGNAL_FUNC) read_settings);
         signal_add("setup reread", (SIGNAL_FUNC) log_read_config);
+        signal_add("irssi init finished", (SIGNAL_FUNC) log_read_config);
 }
 
 void log_deinit(void)
@@ -562,4 +605,5 @@ void log_deinit(void)
 
        signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
         signal_remove("setup reread", (SIGNAL_FUNC) log_read_config);
+        signal_remove("irssi init finished", (SIGNAL_FUNC) log_read_config);
 }