diff options
author | Timo Sirainen <cras@irssi.org> | 2000-04-26 08:03:38 +0000 |
---|---|---|
committer | cras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2000-04-26 08:03:38 +0000 |
commit | c95034c6de1bf72536595e1e3431d8ec64b9880e (patch) | |
tree | e51aa4528257ed8aa9d53640649519f299aaf0c7 /src/fe-common/core/fe-log.c | |
parent | d01b094151705d433bc43cae9eeb304e6f110a17 (diff) | |
download | irssi-c95034c6de1bf72536595e1e3431d8ec64b9880e.zip |
..adding new files..
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@171 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'src/fe-common/core/fe-log.c')
-rw-r--r-- | src/fe-common/core/fe-log.c | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c new file mode 100644 index 00000000..560e0f35 --- /dev/null +++ b/src/fe-common/core/fe-log.c @@ -0,0 +1,402 @@ +/* + fe-log.c : irssi + + Copyright (C) 1999 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "module-formats.h" +#include "signals.h" +#include "commands.h" +#include "server.h" +#include "levels.h" +#include "misc.h" +#include "log.h" +#include "special-vars.h" +#include "settings.h" + +#include "windows.h" +#include "window-items.h" + +/* close autologs after 5 minutes of inactivity */ +#define AUTOLOG_INACTIVITY_CLOSE (60*5) + +#define LOG_DIR_CREATE_MODE 0770 + +static int autolog_level; +static int autoremove_tag; +static const char *autolog_path; + +static void cmd_log_open(const char *data) +{ + /* /LOG OPEN [-noopen] [-autoopen] [-channels <channels>] [-window] + [-rotate hour|day|week|month] <fname> [<levels>] */ + char *params, *args, *itemarg, *rotatearg, *fname, *levels; + char window[MAX_INT_STRLEN]; + LOG_REC *log; + int opened, level, rotate; + + args = "channels rotate"; + params = cmd_get_params(data, 5 | PARAM_FLAG_MULTIARGS | PARAM_FLAG_GETREST, + &args, &itemarg, &rotatearg, &fname, &levels); + if (*fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + rotate = LOG_ROTATE_NEVER; + if (stristr(args, "-rotate")) { + rotate = log_str2rotate(rotatearg); + if (rotate < 0) rotate = LOG_ROTATE_NEVER; + } + + level = level2bits(levels); + if (level == 0) level = MSGLEVEL_ALL; + + if (stristr(args, "-window")) { + /* log by window ref# */ + ltoa(window, active_win->refnum); + itemarg = window; + } + + log = log_create_rec(fname, level, itemarg); + if (log != NULL && log->handle == -1 && stristr(args, "-noopen") == NULL) { + /* start logging */ + opened = log_start_logging(log); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + opened ? IRCTXT_LOG_OPENED : + IRCTXT_LOG_CREATE_FAILED, fname); + if (!opened) log_close(log); + } + if (log != NULL) { + if (stristr(args, "-autoopen")) + log->autoopen = TRUE; + log->rotate = rotate; + log_update(log); + } + + g_free(params); +} + +static void cmd_log_close(const char *data) +{ + LOG_REC *log; + + log = log_find(data); + if (log == NULL) + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_LOG_NOT_OPEN, data); + else { + log_close(log); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_CLOSED, data); + } +} + +static void cmd_log_start(const char *data) +{ + LOG_REC *log; + + log = log_find(data); + if (log != NULL) { + log_start_logging(log); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_OPENED, data); + } +} + +static void cmd_log_stop(const char *data) +{ + LOG_REC *log; + + log = log_find(data); + if (log == NULL || log->handle == -1) + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_LOG_NOT_OPEN, data); + else { + log_stop_logging(log); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_CLOSED, data); + } +} + +static void cmd_log_list(void) +{ + GSList *tmp; + char *levelstr, *items, *rotate; + + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_LOG_LIST_HEADER); + for (tmp = logs; tmp != NULL; tmp = tmp->next) { + LOG_REC *rec = tmp->data; + + levelstr = bits2level(rec->level); + items = rec->items == NULL ? NULL : + g_strjoinv(",", rec->items); + rotate = rec->rotate == 0 ? NULL : + g_strdup_printf(" -rotate %s", log_rotate2str(rec->rotate)); + + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_LOG_LIST, + rec->fname, items != NULL ? items : "", + levelstr, rotate != NULL ? rotate : "", + rec->autoopen ? " -autoopen" : ""); + + g_free_not_null(rotate); + g_free_not_null(items); + g_free(levelstr); + } + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_LOG_LIST_FOOTER); +} + +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) +{ + GSList *tmp; + + for (tmp = logs; tmp != NULL; tmp = tmp->next) { + LOG_REC *rec = tmp->data; + + if (rec->items != NULL && strarray_find(rec->items, item) != -1) + return rec; + } + + return NULL; +} + +static void cmd_window_log(const char *data) +{ + /* /WINDOW LOG ON|OFF|TOGGLE [<filename>] */ + LOG_REC *log; + char *params, *set, *fname, window[MAX_INT_STRLEN]; + int open_log, close_log; + + params = cmd_get_params(data, 2, &set, &fname); + + ltoa(window, active_win->refnum); + log = log_find_item(window); + + open_log = close_log = FALSE; + if (g_strcasecmp(set, "ON") == 0) + open_log = TRUE; + else if (g_strcasecmp(set, "OFF") == 0) { + close_log = TRUE; + } else if (g_strcasecmp(set, "TOGGLE") == 0) { + open_log = log == NULL; + close_log = log != NULL; + } else { + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_NOT_TOGGLE); + g_free(params); + return; + } + + if (open_log && log == NULL) { + /* irc.log.<windowname> or irc.log.Window<ref#> */ + fname = *fname != '\0' ? g_strdup(fname) : + 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); + g_free(fname); + } + + if (open_log && log != NULL) { + log_start_logging(log); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_OPENED, log->fname); + } else if (close_log && log != NULL && log->handle != -1) { + log_stop_logging(log); + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_LOG_CLOSED, log->fname); + } + + g_free(params); +} + +/* Create log file entry to window, but don't start logging */ +static void cmd_window_logfile(const char *data) +{ + LOG_REC *log; + char window[MAX_INT_STRLEN]; + + ltoa(window, active_win->refnum); + log = log_find_item(window); + + if (log != NULL) { + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_WINDOWLOG_FILE_LOGGING); + return; + } + + log = log_create_rec(data, MSGLEVEL_ALL, window); + if (log == NULL) + printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_WINDOWLOG_FILE, data); + else + log_update(log); +} + +static void autologs_close_all(void) +{ + GSList *tmp, *next; + + for (tmp = logs; tmp != NULL; tmp = next) { + LOG_REC *rec = tmp->data; + + next = tmp->next; + if (rec->temp) log_close(rec); + } +} + +static void autolog_log(void *server, const char *target) +{ + LOG_REC *log; + char *fname, *dir, *str; + + log = log_find_item(target); + if (log != NULL) return; + + fname = parse_special_string(autolog_path, server, NULL, target, NULL); + if (log_find(fname) == NULL) { + str = convert_home(fname); + dir = g_dirname(str); + g_free(str); + + mkdir(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); + } + } + g_free(fname); +} + +/* write to logs created with /WINDOW LOG */ +static void sig_printtext_stripped(void *server, const char *target, gpointer levelp, const char *text) +{ + char windownum[MAX_INT_STRLEN]; + WINDOW_REC *window; + LOG_REC *log; + int level; + + level = GPOINTER_TO_INT(levelp); + if ((autolog_level & level) && target != NULL && *target != '\0') + autolog_log(server, target); + + window = window_find_closest(server, target, level); + if (window != NULL) { + ltoa(windownum, window->refnum); + + log = log_find_item(windownum); + if (log != NULL) log_write_rec(log, text); + } +} + +static int sig_autoremove(void) +{ + GSList *tmp, *next; + time_t removetime; + + removetime = time(NULL)-AUTOLOG_INACTIVITY_CLOSE; + for (tmp = logs; tmp != NULL; tmp = next) { + LOG_REC *rec = 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); + } + 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; + + if (rec->temp && g_strcasecmp(rec->items[0], item->name) == 0) { + log_close(rec); + break; + } + } +} + +static void sig_log_locked(LOG_REC *log) +{ + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, + IRCTXT_LOG_LOCKED, log->fname); +} + +static void read_settings(void) +{ + int old_autolog = autolog_level; + + autolog_path = settings_get_str("autolog_path"); + autolog_level = !settings_get_bool("autolog") ? 0 : + level2bits(settings_get_str("autolog_level")); + + if (old_autolog && !autolog_level) + autologs_close_all(); +} + +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"); + settings_add_bool("log", "autolog", FALSE); + + autolog_level = 0; + read_settings(); + + command_bind("log", NULL, (SIGNAL_FUNC) cmd_log); + command_bind("log open", NULL, (SIGNAL_FUNC) cmd_log_open); + command_bind("log close", NULL, (SIGNAL_FUNC) cmd_log_close); + command_bind("log start", NULL, (SIGNAL_FUNC) cmd_log_start); + command_bind("log stop", NULL, (SIGNAL_FUNC) cmd_log_stop); + command_bind("log ", NULL, (SIGNAL_FUNC) cmd_log_list); + command_bind("window log", NULL, (SIGNAL_FUNC) cmd_window_log); + command_bind("window logfile", NULL, (SIGNAL_FUNC) cmd_window_logfile); + signal_add_first("print text stripped", (SIGNAL_FUNC) sig_printtext_stripped); + signal_add("window item remove", (SIGNAL_FUNC) sig_window_item_remove); + signal_add("log locked", (SIGNAL_FUNC) sig_log_locked); + signal_add("setup changed", (SIGNAL_FUNC) read_settings); +} + +void fe_log_deinit(void) +{ + g_source_remove(autoremove_tag); + + command_unbind("log", (SIGNAL_FUNC) cmd_log); + command_unbind("log open", (SIGNAL_FUNC) cmd_log_open); + command_unbind("log close", (SIGNAL_FUNC) cmd_log_close); + command_unbind("log start", (SIGNAL_FUNC) cmd_log_start); + command_unbind("log stop", (SIGNAL_FUNC) cmd_log_stop); + command_unbind("log ", (SIGNAL_FUNC) cmd_log_list); + command_unbind("window log", (SIGNAL_FUNC) cmd_window_log); + command_unbind("window logfile", (SIGNAL_FUNC) cmd_window_logfile); + signal_remove("print text stripped", (SIGNAL_FUNC) sig_printtext_stripped); + signal_remove("window item remove", (SIGNAL_FUNC) sig_window_item_remove); + signal_remove("log locked", (SIGNAL_FUNC) sig_log_locked); + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); +} |