diff options
-rw-r--r-- | src/core/log.c | 144 | ||||
-rw-r--r-- | src/core/log.h | 25 | ||||
-rw-r--r-- | src/fe-common/core/fe-log.c | 169 | ||||
-rw-r--r-- | src/irc/core/irc-log.c | 2 | ||||
-rw-r--r-- | src/perl/common/Log.xs | 53 | ||||
-rw-r--r-- | src/perl/common/module.h | 1 | ||||
-rw-r--r-- | src/perl/common/typemap | 1 |
7 files changed, 289 insertions, 106 deletions
diff --git a/src/core/log.c b/src/core/log.c index b6c6fba4..02238a6b 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -23,6 +23,7 @@ #include "commands.h" #include "levels.h" #include "misc.h" +#include "servers.h" #include "log.h" #include "lib-config/iconfig.h" @@ -36,10 +37,29 @@ static struct flock lock; GSList *logs; +static const char *log_item_types[] = { + "target", + "window", + + NULL +}; + const char *log_timestamp; static int log_file_create_mode; static int rotate_tag; +static int log_item_str2type(const char *type) +{ + int n; + + for (n = 0; log_item_types[n] != NULL; n++) { + if (g_strcasecmp(log_item_types[n], type) == 0) + return n; + } + + return -1; +} + static void log_write_timestamp(int handle, const char *format, const char *suffix, time_t stamp) { @@ -194,7 +214,27 @@ void log_write_rec(LOG_REC *log, const char *str) signal_emit("log written", 2, log, str); } -static void log_file_write(const char *item, int level, +LOG_ITEM_REC *log_item_find(LOG_REC *log, int type, const char *item, + SERVER_REC *server) +{ + 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 && + (rec->servertag == NULL || (server != NULL && + g_strcasecmp(rec->servertag, server->tag) == 0))) + return rec; + } + + return NULL; +} + +static void log_file_write(SERVER_REC *server, const char *item, int level, const char *str, int no_fallbacks) { GSList *tmp, *fallbacks; @@ -216,7 +256,8 @@ static void log_file_write(const char *item, int level, if (rec->items == NULL) fallbacks = g_slist_append(fallbacks, rec); - else if (item != NULL && strarray_find(rec->items, item) != -1) + else if (item != NULL && log_item_find(rec, LOG_ITEM_TARGET, + item, server) != NULL) log_write_rec(rec, str); } @@ -233,11 +274,6 @@ static void log_file_write(const char *item, int level, g_slist_free(fallbacks); } -void log_write(const char *item, int level, const char *str) -{ - log_file_write(item, level, str, TRUE); -} - LOG_REC *log_find(const char *fname) { GSList *tmp; @@ -252,7 +288,23 @@ LOG_REC *log_find(const char *fname) return NULL; } -static void log_set_config(LOG_REC *log) +static void log_items_update_config(LOG_REC *log, CONFIG_NODE *parent) +{ + GSList *tmp; + CONFIG_NODE *node; + + parent = config_node_section(parent, "items", NODE_TYPE_LIST); + for (tmp = log->items; tmp != NULL; tmp = tmp->next) { + LOG_ITEM_REC *rec = tmp->data; + + node = config_node_section(parent, NULL, NODE_TYPE_BLOCK); + iconfig_node_set_str(node, "type", log_item_types[rec->type]); + iconfig_node_set_str(node, "name", rec->name); + iconfig_node_set_str(node, "server", rec->servertag); + } +} + +static void log_update_config(LOG_REC *log) { CONFIG_NODE *node; char *levelstr; @@ -274,10 +326,8 @@ static void log_set_config(LOG_REC *log) iconfig_node_set_str(node, "items", NULL); - if (log->items != NULL && *log->items != NULL) { - node = config_node_section(node, "items", NODE_TYPE_LIST); - config_node_add_list(node, log->items); - } + if (log->items != NULL) + log_items_update_config(log, node); } static void log_remove_config(LOG_REC *log) @@ -285,7 +335,7 @@ static void log_remove_config(LOG_REC *log) iconfig_set_str("logs", log->fname, NULL); } -LOG_REC *log_create_rec(const char *fname, int level, const char *items) +LOG_REC *log_create_rec(const char *fname, int level) { LOG_REC *rec; @@ -296,16 +346,31 @@ LOG_REC *log_create_rec(const char *fname, int level, const char *items) rec = g_new0(LOG_REC, 1); rec->fname = g_strdup(fname); rec->handle = -1; - } else { - g_strfreev(rec->items); } - rec->items = items == NULL || *items == '\0' ? NULL : - g_strsplit(items, " ", -1); rec->level = level; return rec; } +void log_item_add(LOG_REC *log, int type, const char *name, + SERVER_REC *server) +{ + LOG_ITEM_REC *rec; + + g_return_if_fail(log != NULL); + g_return_if_fail(name != NULL); + + if (log_item_find(log, type, name, server)) + return; + + rec = g_new0(LOG_ITEM_REC, 1); + rec->type = type; + rec->name = g_strdup(name); + rec->servertag = server == NULL ? NULL : g_strdup(server->tag); + + log->items = g_slist_append(log->items, rec); +} + void log_update(LOG_REC *log) { g_return_if_fail(log != NULL); @@ -315,10 +380,19 @@ void log_update(LOG_REC *log) log->handle = -1; } - log_set_config(log); + log_update_config(log); signal_emit("log new", 1, log); } +void log_item_destroy(LOG_REC *log, LOG_ITEM_REC *item) +{ + log->items = g_slist_remove(log->items, item); + + g_free(item->name); + g_free_not_null(item->servertag); + g_free(item); +} + static void log_destroy(LOG_REC *log) { g_return_if_fail(log != NULL); @@ -329,7 +403,8 @@ static void log_destroy(LOG_REC *log) logs = g_slist_remove(logs, log); signal_emit("log remove", 1, log); - if (log->items != NULL) g_strfreev(log->items); + while (log->items != NULL) + log_item_destroy(log, log->items->data); g_free(log->fname); g_free_not_null(log->real_fname); g_free(log); @@ -343,7 +418,7 @@ void log_close(LOG_REC *log) log_destroy(log); } -static void sig_printtext_stripped(void *window, void *server, +static void sig_printtext_stripped(void *window, SERVER_REC *server, const char *item, gpointer levelp, const char *str) { @@ -357,12 +432,12 @@ static void sig_printtext_stripped(void *window, void *server, return; if (item == NULL) - log_file_write(NULL, level, str, FALSE); + log_file_write(server, NULL, level, str, FALSE); else { /* there can be multiple items separated with comma */ items = g_strsplit(item, ",", -1); for (tmp = items; *tmp != NULL; tmp++) - log_file_write(*tmp, level, str, FALSE); + log_file_write(server, *tmp, level, str, FALSE); g_strfreev(items); } } @@ -383,6 +458,28 @@ static int sig_rotate_check(void) return 1; } +static void log_items_read_config(CONFIG_NODE *node, LOG_REC *log) +{ + LOG_ITEM_REC *rec; + GSList *tmp; + char *item; + int type; + + for (tmp = node->value; tmp != NULL; tmp = tmp->next) { + node = tmp->data; + + item = config_node_get_str(node, "name", NULL); + type = log_item_str2type(config_node_get_str(node, "type", NULL)); + if (item == NULL || type == -1) + continue; + + rec = g_new0(LOG_ITEM_REC, 1); + rec->type = type; + rec->name = g_strdup(item); + rec->servertag = g_strdup(config_node_get_str(node, "server", NULL)); + } +} + static void log_read_config(void) { CONFIG_NODE *node; @@ -421,7 +518,8 @@ static void log_read_config(void) log->level = level2bits(config_node_get_str(node, "level", 0)); node = config_node_section(node, "items", -1); - if (node != NULL) log->items = config_node_get_list(node); + if (node != NULL) + log_items_read_config(node, log); if (log->autoopen || gslist_find_string(fnames, log->fname)) log_start_logging(log); diff --git a/src/core/log.h b/src/core/log.h index b8fef2ac..ffb00eb8 100644 --- a/src/core/log.h +++ b/src/core/log.h @@ -1,6 +1,19 @@ #ifndef __LOG_H #define __LOG_H +#include "servers.h" + +enum { + LOG_ITEM_TARGET, /* channel, query, .. */ + LOG_ITEM_WINDOW_REFNUM +}; + +typedef struct { + int type; + char *name; + char *servertag; +} LOG_ITEM_REC; + typedef struct { char *fname; /* file name, in strftime() format */ char *real_fname; /* the current expanded file name */ @@ -8,7 +21,7 @@ typedef struct { time_t opened; int level; /* log only these levels */ - char **items; /* log only on these items (channels, queries, window refnums) */ + GSList *items; /* log only on these items */ time_t last; /* when last message was written */ @@ -21,13 +34,17 @@ extern GSList *logs; /* Create log record - you still need to call log_update() to actually add it into log list */ -LOG_REC *log_create_rec(const char *fname, int level, const char *items); +LOG_REC *log_create_rec(const char *fname, int level); void log_update(LOG_REC *log); void log_close(LOG_REC *log); - LOG_REC *log_find(const char *fname); -void log_write(const char *item, int level, const char *str); +void log_item_add(LOG_REC *log, int type, const char *name, + SERVER_REC *server); +void log_item_destroy(LOG_REC *log, LOG_ITEM_REC *item); +LOG_ITEM_REC *log_item_find(LOG_REC *log, int type, const char *item, + SERVER_REC *server); + void log_write_rec(LOG_REC *log, const char *str); int log_start_logging(LOG_REC *log); diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index ccde5e1c..0efb1ff6 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -41,6 +41,21 @@ static int autolog_level; static int autoremove_tag; static const char *autolog_path; +static void log_add_targets(LOG_REC *log, const char *targets) +{ + char **tmp, **items; + + g_return_if_fail(log != NULL); + g_return_if_fail(targets != NULL); + + items = g_strsplit(targets, " ", -1); + + for (tmp = items; *tmp != NULL; tmp++) + log_item_add(log, LOG_ITEM_TARGET, *tmp, NULL); + + g_strfreev(items); +} + /* SYNTAX: LOG OPEN [-noopen] [-autoopen] [-targets <targets>] [-window] <fname> [<levels>] */ static void cmd_log_open(const char *data) @@ -55,34 +70,33 @@ static void cmd_log_open(const char *data) if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS | PARAM_FLAG_GETREST, "log open", &optlist, &fname, &levels)) return; - - targetarg = g_hash_table_lookup(optlist, "targets"); - if (*fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); level = level2bits(levels); - if (level == 0) level = MSGLEVEL_ALL; + log = log_create_rec(fname, level != 0 ? level : MSGLEVEL_ALL); if (g_hash_table_lookup(optlist, "window")) { /* log by window ref# */ ltoa(window, active_win->refnum); - targetarg = window; + log_item_add(log, LOG_ITEM_WINDOW_REFNUM, window, NULL); + } else { + targetarg = g_hash_table_lookup(optlist, "targets"); + if (targetarg != NULL && *targetarg != '\0') + log_add_targets(log, targetarg); } - log = log_create_rec(fname, level, targetarg); - if (log != NULL) { - if (g_hash_table_lookup(optlist, "autoopen")) - log->autoopen = TRUE; - log_update(log); + if (g_hash_table_lookup(optlist, "autoopen")) + log->autoopen = TRUE; + + log_update(log); - if (log->handle == -1 && g_hash_table_lookup(optlist, "noopen") == NULL) { - /* start logging */ - if (log_start_logging(log)) { - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, - IRCTXT_LOG_OPENED, fname); - } else { - log_close(log); - } + if (log->handle == -1 && g_hash_table_lookup(optlist, "noopen") == NULL) { + /* start logging */ + if (log_start_logging(log)) { + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + IRCTXT_LOG_OPENED, fname); + } else { + log_close(log); } } @@ -141,6 +155,28 @@ static void cmd_log_stop(const char *data) } } +static char *log_items_get_list(LOG_REC *log) +{ + GSList *tmp; + GString *str; + char *ret; + + g_return_val_if_fail(log != NULL, NULL); + g_return_val_if_fail(log->items != NULL, NULL); + + str = g_string_new(NULL); + for (tmp = log->items; tmp != NULL; tmp = tmp->next) { + LOG_ITEM_REC *rec = tmp->data; + + g_string_sprintfa(str, "%s, ", rec->name); + } + g_string_truncate(str, str->len-2); + + ret = str->str; + g_string_free(str, FALSE); + return ret; +} + /* SYNTAX: LOG LIST */ static void cmd_log_list(void) { @@ -154,7 +190,7 @@ static void cmd_log_list(void) levelstr = bits2level(rec->level); items = rec->items == NULL ? NULL : - g_strjoinv(",", rec->items); + log_items_get_list(rec); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_LOG_LIST, index, rec->fname, items != NULL ? items : "", @@ -174,15 +210,20 @@ static void cmd_log(const char *data, SERVER_REC *server, void *item) command_runsub("log", data, server, item); } -static LOG_REC *log_find_item(const char *item) +static LOG_REC *logs_find_item(int type, const char *item, + SERVER_REC *server, LOG_ITEM_REC **ret_item) { + LOG_ITEM_REC *logitem; GSList *tmp; for (tmp = logs; tmp != NULL; tmp = tmp->next) { - LOG_REC *rec = tmp->data; + LOG_REC *log = tmp->data; - if (rec->items != NULL && strarray_find(rec->items, item) != -1) - return rec; + logitem = log_item_find(log, type, item, server); + if (logitem != NULL) { + if (ret_item != NULL) *ret_item = logitem; + return log; + } } return NULL; @@ -200,7 +241,7 @@ static void cmd_window_log(const char *data) return; ltoa(window, active_win->refnum); - log = log_find_item(window); + log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, window, NULL, NULL); open_log = close_log = FALSE; if (g_strcasecmp(set, "ON") == 0) @@ -222,8 +263,9 @@ static void cmd_window_log(const char *data) g_strdup_printf("~/irc.log.%s%s", active_win->name != NULL ? active_win->name : "Window", active_win->name != NULL ? "" : window); - log = log_create_rec(fname, MSGLEVEL_ALL, window); - if (log != NULL) log_update(log); + log = log_create_rec(fname, MSGLEVEL_ALL); + log_item_add(log, LOG_ITEM_WINDOW_REFNUM, window, NULL); + log_update(log); g_free(fname); } @@ -246,18 +288,18 @@ static void cmd_window_logfile(const char *data) char window[MAX_INT_STRLEN]; ltoa(window, active_win->refnum); - log = log_find_item(window); + log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, window, NULL, NULL); if (log != NULL) { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_WINDOWLOG_FILE_LOGGING); return; } - log = log_create_rec(data, MSGLEVEL_ALL, window); - if (log == NULL) - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_WINDOWLOG_FILE, data); - else - log_update(log); + log = log_create_rec(data, MSGLEVEL_ALL); + log_item_add(log, LOG_ITEM_WINDOW_REFNUM, window, NULL); + log_update(log); + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_WINDOWLOG_FILE, data); } /* window's refnum changed - update the logs to log the new window refnum */ @@ -265,15 +307,16 @@ static void sig_window_refnum_changed(WINDOW_REC *window, gpointer old_refnum) { char winnum[MAX_INT_STRLEN]; LOG_REC *log; + LOG_ITEM_REC *item; ltoa(winnum, GPOINTER_TO_INT(old_refnum)); - log = log_find_item(winnum); + log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, winnum, NULL, &item); if (log != NULL) { ltoa(winnum, window->refnum); - g_strfreev(log->items); - log->items = g_strsplit(winnum, " ", -1); + g_free(item->name); + item->name = g_strdup(winnum); } } @@ -294,7 +337,7 @@ static void autolog_log(void *server, const char *target) LOG_REC *log; char *fname, *dir, *str; - log = log_find_item(target); + log = logs_find_item(LOG_ITEM_TARGET, target, server, NULL); if (log != NULL && !log->failed) { log_start_logging(log); return; @@ -309,12 +352,12 @@ static void autolog_log(void *server, const char *target) mkpath(dir, LOG_DIR_CREATE_MODE); g_free(dir); - log = log_create_rec(fname, autolog_level, target); - if (log != NULL) { - log->temp = TRUE; - log_update(log); - log_start_logging(log); - } + log = log_create_rec(fname, autolog_level); + log_item_add(log, LOG_ITEM_TARGET, target, server); + + log->temp = TRUE; + log_update(log); + log_start_logging(log); } g_free(fname); } @@ -343,48 +386,42 @@ static void sig_printtext_stripped(WINDOW_REC *window, void *server, /* save to log created with /WINDOW LOG */ ltoa(windownum, window->refnum); - log = log_find_item(windownum); + log = logs_find_item(LOG_ITEM_WINDOW_REFNUM, windownum, NULL, NULL); if (log != NULL) log_write_rec(log, text); } static int sig_autoremove(void) { + SERVER_REC *server; + LOG_ITEM_REC *logitem; GSList *tmp, *next; time_t removetime; removetime = time(NULL)-AUTOLOG_INACTIVITY_CLOSE; for (tmp = logs; tmp != NULL; tmp = next) { - LOG_REC *rec = tmp->data; + LOG_REC *log = tmp->data; next = tmp->next; - /* FIXME: here is a small kludge - We don't want autolog to - automatically close the logs with channels, only with - private messages. However, this is CORE module and we - don't know how to figure out if item is a channel or not, - so just assume that channels are everything that don't - start with alphanumeric character. */ - if (!rec->temp || rec->last > removetime || - rec->items == NULL || !isalnum(**rec->items)) - continue; - - log_close(rec); + + if (!log->temp || log->last > removetime || log->items == NULL) + continue; + + /* Close only logs with private messages */ + logitem = log->items->data; + server = server_find_tag(logitem->servertag); + if (logitem->type == LOG_ITEM_TARGET && + server != NULL && !server->ischannel(*logitem->name)) + log_close(log); } return 1; } static void sig_window_item_remove(WINDOW_REC *window, WI_ITEM_REC *item) { - GSList *tmp; - - for (tmp = logs; tmp != NULL; tmp = tmp->next) { - LOG_REC *rec = tmp->data; + LOG_REC *log; - if (rec->temp && rec->items != NULL && - g_strcasecmp(rec->items[0], item->name) == 0) { - log_close(rec); - break; - } - } + log = logs_find_item(LOG_ITEM_TARGET, item->name, item->server, NULL); + if (log != NULL) log_close(log); } static void sig_log_locked(LOG_REC *log) @@ -435,7 +472,7 @@ void fe_log_init(void) autoremove_tag = g_timeout_add(60000, (GSourceFunc) sig_autoremove, NULL); settings_add_str("log", "autolog_path", "~/irclogs/$tag/$0.log"); - settings_add_str("log", "autolog_level", "all -crap"); + settings_add_str("log", "autolog_level", "all -crap -clientcrap"); settings_add_bool("log", "autolog", FALSE); autolog_level = 0; diff --git a/src/irc/core/irc-log.c b/src/irc/core/irc-log.c index abe557c5..cfb5afb8 100644 --- a/src/irc/core/irc-log.c +++ b/src/irc/core/irc-log.c @@ -55,7 +55,7 @@ static void event_away(const char *data, IRC_SERVER_REC *server) return; /* already open */ if (log == NULL) { - log = log_create_rec(fname, level, NULL); + log = log_create_rec(fname, level); log->temp = TRUE; log_update(log); } diff --git a/src/perl/common/Log.xs b/src/perl/common/Log.xs index 06b72d0b..c341cf30 100644 --- a/src/perl/common/Log.xs +++ b/src/perl/common/Log.xs @@ -12,21 +12,14 @@ PPCODE: } Irssi::Log -log_create_rec(fname, level, items) +log_create_rec(fname, level) char *fname int level - char *items Irssi::Log log_find(fname) char *fname -void -log_write(item, level, str) - char *item - int level - char *str - #******************************* MODULE = Irssi PACKAGE = Irssi::Log PREFIX = log_ #******************************* @@ -35,9 +28,9 @@ void values(log) Irssi::Log log PREINIT: - HV *hv; + HV *hv, *stash; AV *av; - char **tmp; + GSList *tmp; PPCODE: hv = newHV(); hv_store(hv, "fname", 5, new_pv(log->fname), 0); @@ -45,16 +38,37 @@ PPCODE: hv_store(hv, "level", 5, newSViv(log->level), 0); hv_store(hv, "last", 4, newSViv(log->last), 0); hv_store(hv, "autoopen", 8, newSViv(log->autoopen), 0); + hv_store(hv, "failed", 6, newSViv(log->failed), 0); hv_store(hv, "temp", 4, newSViv(log->temp), 0); + stash = gv_stashpv("Irssi::LogItem", 0); av = newAV(); - for (tmp = log->items; *tmp != NULL; tmp++) { - av_push(av, new_pv(*tmp)); + for (tmp = log->items; tmp != NULL; tmp = tmp->next) { + av_push(av, sv_2mortal(sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(tmp->data))), stash))); } hv_store(hv, "items", 4, newRV_noinc((SV*)av), 0); XPUSHs(sv_2mortal(newRV_noinc((SV*)hv))); void +log_item_add(log, type, name, server) + Irssi::Log log + int type + char *name + Irssi::Server server + +void +log_item_destroy(log, item) + Irssi::Log log + Irssi::LogItem item + +Irssi::LogItem +log_item_find(log, type, item, server) + Irssi::Log log + int type + char *item + Irssi::Server server + +void log_update(log) Irssi::Log log @@ -74,3 +88,18 @@ log_start_logging(log) void log_stop_logging(log) Irssi::Log log + +#******************************* +MODULE = Irssi PACKAGE = Irssi::LogItem +#******************************* + +void +values(item) + Irssi::LogItem item +PREINIT: + HV *hv; +PPCODE: + hv = newHV(); + hv_store(hv, "type", 4, newSViv(item->type), 0); + hv_store(hv, "name", 4, new_pv(item->name), 0); + hv_store(hv, "servertag", 9, new_pv(item->servertag), 0); diff --git a/src/perl/common/module.h b/src/perl/common/module.h index a47728e6..fec283f0 100644 --- a/src/perl/common/module.h +++ b/src/perl/common/module.h @@ -25,6 +25,7 @@ typedef COMMAND_REC *Irssi__Command; typedef LOG_REC *Irssi__Log; +typedef LOG_ITEM_REC *Irssi__LogItem; typedef RAWLOG_REC *Irssi__Rawlog; typedef IGNORE_REC *Irssi__Ignore; diff --git a/src/perl/common/typemap b/src/perl/common/typemap index c7de4903..7e2cf17e 100644 --- a/src/perl/common/typemap +++ b/src/perl/common/typemap @@ -8,6 +8,7 @@ Irssi::Command T_PTROBJ Irssi::Nick T_PTROBJ Irssi::Ignore T_PTROBJ Irssi::Log T_PTROBJ +Irssi::LogItem T_PTROBJ Irssi::Rawlog T_PTROBJ Irssi::Window T_PTROBJ Irssi::Windowitem T_PTROBJ |