diff options
Diffstat (limited to 'src/plugins/logger')
-rw-r--r-- | src/plugins/logger/logger-buffer.c | 55 | ||||
-rw-r--r-- | src/plugins/logger/logger-buffer.h | 6 | ||||
-rw-r--r-- | src/plugins/logger/logger-config.c | 323 | ||||
-rw-r--r-- | src/plugins/logger/logger-config.h | 4 | ||||
-rw-r--r-- | src/plugins/logger/logger-tail.c | 21 | ||||
-rw-r--r-- | src/plugins/logger/logger.c | 748 | ||||
-rw-r--r-- | src/plugins/logger/logger.h | 3 |
7 files changed, 971 insertions, 189 deletions
diff --git a/src/plugins/logger/logger-buffer.c b/src/plugins/logger/logger-buffer.c index 446d48133..bada5e47c 100644 --- a/src/plugins/logger/logger-buffer.c +++ b/src/plugins/logger/logger-buffer.c @@ -66,20 +66,29 @@ logger_buffer_valid (struct t_logger_buffer *logger_buffer) */ struct t_logger_buffer * -logger_buffer_add (struct t_gui_buffer *buffer, const char *log_filename) +logger_buffer_add (struct t_gui_buffer *buffer, int log_level) { struct t_logger_buffer *new_logger_buffer; - if (!buffer || !log_filename) + if (!buffer) return NULL; + if (logger_debug) + { + weechat_printf (NULL, + "%s: start logging for buffer \"%s\"", + LOGGER_PLUGIN_NAME, + weechat_buffer_get_string (buffer, "name")); + } + new_logger_buffer = malloc (sizeof (*new_logger_buffer)); if (new_logger_buffer) { new_logger_buffer->buffer = buffer; - new_logger_buffer->log_filename = strdup (log_filename); + new_logger_buffer->log_filename = NULL; new_logger_buffer->log_file = NULL; new_logger_buffer->log_enabled = 1; + new_logger_buffer->log_level = log_level; new_logger_buffer->prev_buffer = last_logger_buffer; new_logger_buffer->next_buffer = NULL; @@ -94,11 +103,11 @@ logger_buffer_add (struct t_gui_buffer *buffer, const char *log_filename) } /* - * logger_buffer_search: search a logger buffer by buffer pointer + * logger_buffer_search_buffer: search a logger buffer by buffer pointer */ struct t_logger_buffer * -logger_buffer_search (struct t_gui_buffer *buffer) +logger_buffer_search_buffer (struct t_gui_buffer *buffer) { struct t_logger_buffer *ptr_logger_buffer; @@ -114,6 +123,32 @@ logger_buffer_search (struct t_gui_buffer *buffer) } /* + * logger_buffer_search_log_filename: search a logger buffer by log filename + */ + +struct t_logger_buffer * +logger_buffer_search_log_filename (const char *log_filename) +{ + struct t_logger_buffer *ptr_logger_buffer; + + if (!log_filename) + return NULL; + + for (ptr_logger_buffer = logger_buffers; ptr_logger_buffer; + ptr_logger_buffer = ptr_logger_buffer->next_buffer) + { + if (ptr_logger_buffer->log_filename) + { + if (strcmp (ptr_logger_buffer->log_filename, log_filename) == 0) + return ptr_logger_buffer; + } + } + + /* logger buffer not found */ + return NULL; +} + +/* * logger_buffer_free: remove a logger buffer from list */ @@ -122,6 +157,14 @@ logger_buffer_free (struct t_logger_buffer *logger_buffer) { struct t_logger_buffer *new_logger_buffers; + if (logger_debug) + { + weechat_printf (NULL, + "%s: stop logging for buffer \"%s\"", + LOGGER_PLUGIN_NAME, + weechat_buffer_get_string (logger_buffer->buffer, "name")); + } + /* remove logger buffer */ if (last_logger_buffer == logger_buffer) last_logger_buffer = logger_buffer->prev_buffer; @@ -182,6 +225,8 @@ logger_buffer_add_to_infolist (struct t_infolist *infolist, return 0; if (!weechat_infolist_new_var_integer (ptr_item, "log_enabled", logger_buffer->log_enabled)) return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "log_level", logger_buffer->log_level)) + return 0; return 1; } diff --git a/src/plugins/logger/logger-buffer.h b/src/plugins/logger/logger-buffer.h index d2d464461..4cc715d38 100644 --- a/src/plugins/logger/logger-buffer.h +++ b/src/plugins/logger/logger-buffer.h @@ -28,6 +28,7 @@ struct t_logger_buffer char *log_filename; /* log filename */ FILE *log_file; /* log file */ int log_enabled; /* log enabled ? */ + int log_level; /* log level (0..9) */ struct t_logger_buffer *prev_buffer; /* link to previous buffer */ struct t_logger_buffer *next_buffer; /* link to next buffer */ }; @@ -37,8 +38,9 @@ extern struct t_logger_buffer *last_logger_buffer; extern int logger_buffer_valid (struct t_logger_buffer *logger_buffer); extern struct t_logger_buffer *logger_buffer_add (struct t_gui_buffer *, - const char *log_filename); -extern struct t_logger_buffer *logger_buffer_search (struct t_gui_buffer *buffer); + int log_level); +extern struct t_logger_buffer *logger_buffer_search_buffer (struct t_gui_buffer *buffer); +extern struct t_logger_buffer *logger_buffer_search_log_filename (const char *log_filename); extern void logger_buffer_free (struct t_logger_buffer *logger_buffer); extern void logger_buffer_free_all (); extern int logger_buffer_add_to_infolist (struct t_infolist *infolist, diff --git a/src/plugins/logger/logger-config.c b/src/plugins/logger/logger-config.c index 3569337c4..3183be4a5 100644 --- a/src/plugins/logger/logger-config.c +++ b/src/plugins/logger/logger-config.c @@ -28,6 +28,10 @@ struct t_config_file *logger_config_file = NULL; +struct t_config_section *logger_config_section_level = NULL; +struct t_config_section *logger_config_section_mask = NULL; + +int logger_config_loading = 0; /* logger config, look section */ @@ -38,11 +42,272 @@ struct t_config_option *logger_config_look_backlog; struct t_config_option *logger_config_file_auto_log; struct t_config_option *logger_config_file_name_lower_case; struct t_config_option *logger_config_file_path; +struct t_config_option *logger_config_file_mask; struct t_config_option *logger_config_file_info_lines; struct t_config_option *logger_config_file_time_format; /* + * logger_config_change_file_option_restart_log: called when a file option is + * changed and that logging must + * be restarted for all buffers + */ + +void +logger_config_change_file_option_restart_log (void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) data; + (void) option; + + if (!logger_config_loading) + { + logger_stop_all (); + logger_start_buffer_all (); + } +} + +/* + * logger_config_level_change: called when a level option is changed + */ + +void +logger_config_level_change (void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) data; + (void) option; + + if (!logger_config_loading) + logger_start_buffer_all (); +} + +/* + * logger_config_level_delete_option: delete option in "level" section + */ + +int +logger_config_level_delete_option (void *data, + struct t_config_file *config_file, + struct t_config_section *section, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) data; + (void) config_file; + (void) section; + + weechat_config_option_free (option); + + logger_start_buffer_all (); + + return WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED; +} + +/* + * logger_config_level_create_option: create option in "level" section + */ + +int +logger_config_level_create_option (void *data, + struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, + const char *value) +{ + struct t_config_option *ptr_option; + int rc; + + /* make C compiler happy */ + (void) data; + + rc = WEECHAT_CONFIG_OPTION_SET_ERROR; + + if (option_name) + { + ptr_option = weechat_config_search_option (config_file, section, + option_name); + if (ptr_option) + { + if (value && value[0]) + rc = weechat_config_option_set (ptr_option, value, 1); + else + { + weechat_config_option_free (ptr_option); + rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; + } + } + else + { + if (value && value[0]) + { + ptr_option = weechat_config_new_option ( + config_file, section, + option_name, "integer", + _("logging level for this buffer (0 = logging disabled, " + "1 = a few messages (most important) .. 9 = all messages)"), + NULL, 0, 9, "9", value, NULL, NULL, + &logger_config_level_change, NULL, + NULL, NULL); + rc = (ptr_option) ? + WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE : WEECHAT_CONFIG_OPTION_SET_ERROR; + } + else + rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; + } + } + + if (!logger_config_loading) + logger_start_buffer_all (); + + return rc; +} + +/* + * logger_config_get_level: get a level option + */ + +struct t_config_option * +logger_config_get_level (const char *name) +{ + return weechat_config_search_option (logger_config_file, + logger_config_section_level, + name); +} + +/* + * logger_config_set_level: set a level option + */ + +int +logger_config_set_level (const char *name, const char *value) +{ + return logger_config_level_create_option (NULL, + logger_config_file, + logger_config_section_level, + name, + value); +} + +/* + * logger_config_mask_change: called when a mask option is changed + */ + +void +logger_config_mask_change (void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) data; + (void) option; + + if (!logger_config_loading) + { + logger_stop_all (); + logger_start_buffer_all (); + } +} + +/* + * logger_config_mask_delete_option: delete option in "mask" section + */ + +int +logger_config_mask_delete_option (void *data, + struct t_config_file *config_file, + struct t_config_section *section, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) data; + (void) config_file; + (void) section; + + weechat_config_option_free (option); + + logger_stop_all (); + logger_start_buffer_all (); + + return WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED; +} + +/* + * logger_config_mask_create_option: create option in "mask" section + */ + +int +logger_config_mask_create_option (void *data, + struct t_config_file *config_file, + struct t_config_section *section, + const char *option_name, + const char *value) +{ + struct t_config_option *ptr_option; + int rc; + + /* make C compiler happy */ + (void) data; + + rc = WEECHAT_CONFIG_OPTION_SET_ERROR; + + if (option_name) + { + ptr_option = weechat_config_search_option (config_file, section, + option_name); + if (ptr_option) + { + if (value && value[0]) + rc = weechat_config_option_set (ptr_option, value, 1); + else + { + weechat_config_option_free (ptr_option); + rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; + } + } + else + { + if (value && value[0]) + { + ptr_option = weechat_config_new_option ( + config_file, section, + option_name, "string", + _("file mask for log file; local buffer variables are " + "permitted"), + NULL, 0, 0, "", value, NULL, NULL, + &logger_config_mask_change, NULL, + NULL, NULL); + rc = (ptr_option) ? + WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE : WEECHAT_CONFIG_OPTION_SET_ERROR; + } + else + rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; + } + } + + if (!logger_config_loading) + { + logger_stop_all (); + logger_start_buffer_all (); + } + + return rc; +} + +/* + * logger_config_get_mask: get a mask option + */ + +struct t_config_option * +logger_config_get_mask (const char *name) +{ + return weechat_config_search_option (logger_config_file, + logger_config_section_mask, + name); +} + +/* * logger_config_init: init logger configuration file * return: 1 if ok, 0 if error */ @@ -61,7 +326,8 @@ logger_config_init () ptr_section = weechat_config_new_section (logger_config_file, "look", 0, 0, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, + NULL, NULL); if (!ptr_section) { weechat_config_free (logger_config_file); @@ -79,7 +345,8 @@ logger_config_init () ptr_section = weechat_config_new_section (logger_config_file, "file", 0, 0, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, + NULL, NULL); if (!ptr_section) { weechat_config_free (logger_config_file); @@ -96,13 +363,23 @@ logger_config_init () logger_config_file, ptr_section, "name_lower_case", "boolean", N_("use only lower case for log filenames"), - NULL, 0, 0, "on", NULL, NULL, NULL, NULL, NULL, NULL, NULL); + NULL, 0, 0, "on", NULL, NULL, NULL, + &logger_config_change_file_option_restart_log, NULL, NULL, NULL); logger_config_file_path = weechat_config_new_option ( logger_config_file, ptr_section, "path", "string", N_("path for WeeChat log files ('%h' will be replaced by WeeChat " "home, ~/.weechat by default)"), - NULL, 0, 0, "%h/logs/", NULL, NULL, NULL, NULL, NULL, NULL, NULL); + NULL, 0, 0, "%h/logs/", NULL, NULL, NULL, + &logger_config_change_file_option_restart_log, NULL, NULL, NULL); + logger_config_file_mask = weechat_config_new_option ( + logger_config_file, ptr_section, + "mask", "string", + N_("default file name mask for log files (format is 'directory/to/file' " + "or 'file', without first '/' because 'path' option is used to " + "build complete path to file); local buffer variables are permitted"), + NULL, 0, 0, "$plugin.$name.weechatlog", NULL, NULL, NULL, + &logger_config_change_file_option_restart_log, NULL, NULL, NULL); logger_config_file_info_lines = weechat_config_new_option ( logger_config_file, ptr_section, "info_lines", "boolean", @@ -116,6 +393,36 @@ logger_config_init () "specifiers)"), NULL, 0, 0, "%Y-%m-%d %H:%M:%S", NULL, NULL, NULL, NULL, NULL, NULL, NULL); + /* level */ + ptr_section = weechat_config_new_section (logger_config_file, "level", + 1, 1, + NULL, NULL, NULL, NULL, + NULL, NULL, + &logger_config_level_create_option, NULL, + &logger_config_level_delete_option, NULL); + if (!ptr_section) + { + weechat_config_free (logger_config_file); + return 0; + } + + logger_config_section_level = ptr_section; + + /* mask */ + ptr_section = weechat_config_new_section (logger_config_file, "mask", + 1, 1, + NULL, NULL, NULL, NULL, + NULL, NULL, + &logger_config_mask_create_option, NULL, + &logger_config_mask_delete_option, NULL); + if (!ptr_section) + { + weechat_config_free (logger_config_file); + return 0; + } + + logger_config_section_mask = ptr_section; + return 1; } @@ -126,7 +433,13 @@ logger_config_init () int logger_config_read () { - return weechat_config_read (logger_config_file); + int rc; + + logger_config_loading = 1; + rc = weechat_config_read (logger_config_file); + logger_config_loading = 0; + + return rc; } /* diff --git a/src/plugins/logger/logger-config.h b/src/plugins/logger/logger-config.h index c2c1d6fa1..519542bd2 100644 --- a/src/plugins/logger/logger-config.h +++ b/src/plugins/logger/logger-config.h @@ -28,9 +28,13 @@ extern struct t_config_option *logger_config_look_backlog; extern struct t_config_option *logger_config_file_auto_log; extern struct t_config_option *logger_config_file_name_lower_case; extern struct t_config_option *logger_config_file_path; +extern struct t_config_option *logger_config_file_mask; extern struct t_config_option *logger_config_file_info_lines; extern struct t_config_option *logger_config_file_time_format; +extern struct t_config_option *logger_config_get_level (const char *name); +extern int logger_config_set_level (const char *name, const char *value); +extern struct t_config_option *logger_config_get_mask (const char *name); extern int logger_config_init (); extern int logger_config_read (); extern int logger_config_write (); diff --git a/src/plugins/logger/logger-tail.c b/src/plugins/logger/logger-tail.c index e129d2a75..2023252b3 100644 --- a/src/plugins/logger/logger-tail.c +++ b/src/plugins/logger/logger-tail.c @@ -30,6 +30,7 @@ #include <fcntl.h> #include <string.h> +#include "../weechat-plugin.h" #include "logger.h" #include "logger-tail.h" @@ -108,7 +109,7 @@ logger_tail_file (const char *filename, int n_lines) while (ptr_buf && (ptr_buf >= buf)) { pos_eol = logger_tail_last_eol (buf, ptr_buf); - if ((pos_eol && pos_eol[1]) || (!pos_eol && (file_pos == 0))) + if ((pos_eol && (pos_eol[1] || part_of_line)) || (file_pos == 0)) { /* use data and part_of_line (if existing) to build a new line */ if (!pos_eol) @@ -209,14 +210,20 @@ logger_tail_file (const char *filename, int n_lines) void logger_tail_free (struct t_logger_line *lines) { + struct t_logger_line *ptr_line, *next_line; + if (!lines) return; - - while (lines->next_line) + + ptr_line = lines; + while (ptr_line) { - if (lines->data) - free (lines->data); - lines = lines->next_line; + next_line = ptr_line->next_line; + + if (ptr_line->data) + free (ptr_line->data); + free (ptr_line); + + ptr_line = next_line; } - free (lines); } diff --git a/src/plugins/logger/logger.c b/src/plugins/logger/logger.c index 9d3bbf597..fbf947fb4 100644 --- a/src/plugins/logger/logger.c +++ b/src/plugins/logger/logger.c @@ -29,6 +29,7 @@ #include <stdio.h> #include <stdarg.h> #include <string.h> +#include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -51,10 +52,45 @@ WEECHAT_PLUGIN_LICENSE("GPL3"); struct t_weechat_plugin *weechat_logger_plugin = NULL; +int logger_debug = 0; + char *logger_buf_write = NULL; /* buffer for writing a line */ /* + * logger_debug_cb: callback for "debug" signal + */ + +int +logger_debug_cb (void *data, const char *signal, const char *type_data, + void *signal_data) +{ + /* make C compiler happy */ + (void) data; + (void) signal; + + if (strcmp (type_data, WEECHAT_HOOK_SIGNAL_STRING) == 0) + { + if (weechat_strcasecmp ((char *)signal_data, LOGGER_PLUGIN_NAME) == 0) + { + logger_debug ^= 1; + if (logger_debug) + { + weechat_printf (NULL, _("%s: debug enabled"), + LOGGER_PLUGIN_NAME); + } + else + { + weechat_printf (NULL, _("%s: debug disabled"), + LOGGER_PLUGIN_NAME); + } + } + } + + return WEECHAT_RC_OK; +} + +/* * logger_create_directory: create logger directory * return 1 if success (directory created or already * exists), 0 if failed @@ -78,13 +114,9 @@ logger_create_directory () dir2 = weechat_string_replace (dir1, "%h", weechat_dir); if (dir2) { - if (mkdir (dir2, 0755) < 0) - { - if (errno != EEXIST) - rc = 0; - } - else - chmod (dir2, 0700); + if (!weechat_mkdir_parents (dir2, 0700)) + rc = 0; + free (dir2); } else @@ -101,20 +133,179 @@ logger_create_directory () } /* + * logger_build_option_name: build option name with a buffer + */ + +char * +logger_build_option_name (struct t_gui_buffer *buffer) +{ + char *plugin_name, *name, *option_name; + int length; + + if (!buffer) + return NULL; + + plugin_name = weechat_buffer_get_string (buffer, "plugin"); + name = weechat_buffer_get_string (buffer, "name"); + + length = strlen (plugin_name) + 1 + strlen (name) + 1; + option_name = malloc (length); + if (!option_name) + return NULL; + + snprintf (option_name, length, "%s.%s", plugin_name, name); + + return option_name; +} + +/* + * logger_get_level_for_buffer: get logging level for buffer (0 = disabled, 1..9) + */ + +int +logger_get_level_for_buffer (struct t_gui_buffer *buffer) +{ + char *name, *option_name, *ptr_end; + struct t_config_option *ptr_option; + + name = logger_build_option_name (buffer); + if (!name) + return LOGGER_LEVEL_DEFAULT; + + option_name = strdup (name); + if (option_name) + { + ptr_end = option_name + strlen (option_name); + while (ptr_end >= option_name) + { + ptr_option = logger_config_get_level (option_name); + if (ptr_option) + { + free (option_name); + free (name); + return weechat_config_integer (ptr_option); + } + ptr_end--; + while ((ptr_end >= option_name) && (ptr_end[0] != '.')) + { + ptr_end--; + } + if ((ptr_end >= option_name) && (ptr_end[0] == '.')) + ptr_end[0] = '\0'; + } + ptr_option = logger_config_get_level (option_name); + + free (option_name); + free (name); + + if (ptr_option) + return weechat_config_integer (ptr_option); + } + else + free (name); + + /* nothing found => return default level */ + return LOGGER_LEVEL_DEFAULT; +} + +/* + * logger_get_mask_for_buffer: get filename mask for a buffer + * we first try with all arguments, then remove one by + * one to find mask (from specific to general mask) + */ + +char * +logger_get_mask_for_buffer (struct t_gui_buffer *buffer) +{ + char *name, *option_name, *ptr_end; + struct t_config_option *ptr_option; + + name = logger_build_option_name (buffer); + if (!name) + return NULL; + + option_name = strdup (name); + if (option_name) + { + ptr_end = option_name + strlen (option_name); + while (ptr_end >= option_name) + { + ptr_option = logger_config_get_mask (option_name); + if (ptr_option) + { + free (option_name); + free (name); + return weechat_config_string (ptr_option); + } + ptr_end--; + while ((ptr_end >= option_name) && (ptr_end[0] != '.')) + { + ptr_end--; + } + if ((ptr_end >= option_name) && (ptr_end[0] == '.')) + ptr_end[0] = '\0'; + } + ptr_option = logger_config_get_mask (option_name); + + free (option_name); + free (name); + + if (ptr_option) + return weechat_config_string (ptr_option); + } + else + free (name); + + /* nothing found => return default mask (if set) */ + if (weechat_config_string (logger_config_file_mask) + && weechat_config_string (logger_config_file_mask)[0]) + return weechat_config_string (logger_config_file_mask); + + /* no default mask set */ + return NULL; +} + +/* * logger_get_filename: build log filename for a buffer */ char * logger_get_filename (struct t_gui_buffer *buffer) { - struct t_infolist *ptr_infolist; - char *res; - char *dir_separator, *weechat_dir, *log_path, *log_path2; - char *plugin_name, *plugin_name2, *name, *name2; + char *res, *mask, *mask_decoded, *dir_separator, *weechat_dir; + char *log_path, *log_path2, *pos_last_sep; int length; res = NULL; + /* get filename mask for buffer */ + mask = logger_get_mask_for_buffer (buffer); + if (!mask) + { + weechat_printf (NULL, + _("%s%s: unable to find filename mask for buffer " + "\"%s\", logging is disabled for this buffer"), + weechat_prefix ("error"), LOGGER_PLUGIN_NAME, + weechat_buffer_get_string (buffer, "name")); + return NULL; + } + mask_decoded = weechat_buffer_string_replace_local_var (buffer, mask); + if (!mask_decoded) + return NULL; + + if (logger_debug) + { + weechat_printf (NULL, + "%s: buffer = \"%s\", mask = \"%s\", " + "decoded mask = \"%s\"", + LOGGER_PLUGIN_NAME, + weechat_buffer_get_string (buffer, "name"), + mask, mask_decoded); + } + + if (weechat_config_boolean (logger_config_file_name_lower_case)) + weechat_string_tolower (mask_decoded); + dir_separator = weechat_info_get ("dir_separator", ""); weechat_dir = weechat_info_get ("weechat_dir", ""); log_path = weechat_string_replace (weechat_config_string (logger_config_file_path), @@ -123,49 +314,17 @@ logger_get_filename (struct t_gui_buffer *buffer) if (dir_separator && weechat_dir && log_path && log_path2) { - ptr_infolist = weechat_infolist_get ("buffer", buffer, NULL); - if (ptr_infolist) + length = strlen (log_path2) + strlen (mask_decoded) + 1; + res = malloc (length); + if (res) { - plugin_name2 = NULL; - name2 = NULL; - if (weechat_infolist_next (ptr_infolist)) - { - plugin_name = weechat_infolist_string (ptr_infolist, "plugin_name"); - plugin_name2 = (plugin_name) ? - weechat_string_replace (plugin_name, dir_separator, "_") : NULL; - name = weechat_infolist_string (ptr_infolist, "name"); - name2 = (name) ? - weechat_string_replace (name, dir_separator, "_") : NULL; - } - length = strlen (log_path2); - if (plugin_name2) - length += strlen (plugin_name2) + 1; - if (name2) - length += strlen (name2) + 1; - length += 16; - res = malloc (length); - if (res) - { - strcpy (res, log_path2); - if (plugin_name2) - { - if (weechat_config_boolean (logger_config_file_name_lower_case)) - weechat_string_tolower (plugin_name2); - strcat (res, plugin_name2); - strcat (res, "."); - } - if (name2) - { - if (weechat_config_boolean (logger_config_file_name_lower_case)) - weechat_string_tolower (name2); - strcat (res, name2); - strcat (res, "."); - } - strcat (res, "weechatlog"); - } - if (name2) - free (name2); - weechat_infolist_free (ptr_infolist); + snprintf (res, length, "%s%s", log_path2, mask_decoded); + pos_last_sep = strrchr (res, dir_separator[0]); + if (pos_last_sep) + pos_last_sep[0] = '\0'; + weechat_mkdir_parents (res, 0700); + if (pos_last_sep) + pos_last_sep[0] = dir_separator[0]; } } @@ -178,6 +337,44 @@ logger_get_filename (struct t_gui_buffer *buffer) } /* + * logger_set_log_filename: set log filename for a logger buffer + */ + +void +logger_set_log_filename (struct t_logger_buffer *logger_buffer) +{ + char *log_filename; + struct t_logger_buffer *ptr_logger_buffer; + + log_filename = logger_get_filename (logger_buffer->buffer); + if (!log_filename) + { + weechat_printf (NULL, + _("%s%s: not enough memory"), + weechat_prefix ("error"), + LOGGER_PLUGIN_NAME); + return; + } + + ptr_logger_buffer = logger_buffer_search_log_filename (log_filename); + if (ptr_logger_buffer) + { + weechat_printf (NULL, + _("%s%s: unable to start logging for buffer " + "\"%s\": filename \"%s\" is already user by " + "another buffer (check your log settings)"), + weechat_prefix ("error"), + LOGGER_PLUGIN_NAME, + weechat_buffer_get_string (logger_buffer->buffer, "name"), + log_filename); + free (log_filename); + return; + } + + logger_buffer->log_filename = log_filename; +} + +/* * logger_write_line: write a line to log file */ @@ -190,75 +387,130 @@ logger_write_line (struct t_logger_buffer *logger_buffer, time_t seconds; struct tm *date_tmp; char buf_time[256]; - + if (!logger_buf_write) logger_buf_write = malloc (LOGGER_BUF_WRITE_SIZE); if (!logger_buf_write) return; - if (logger_buffer->log_filename) + charset = weechat_info_get ("charset_terminal", ""); + + if (!logger_buffer->log_file) { - charset = weechat_info_get ("charset_terminal", ""); + if (!logger_create_directory ()) + { + weechat_printf (NULL, + _("%s%s: unable to create directory for logs " + "(\"%s\")"), + weechat_prefix ("error"), LOGGER_PLUGIN_NAME, + weechat_config_string (logger_config_file_path)); + logger_buffer_free (logger_buffer); + return; + } + if (!logger_buffer->log_filename) + logger_set_log_filename (logger_buffer); - if (!logger_buffer->log_file) + if (!logger_buffer->log_filename) { - if (!logger_create_directory ()) - { - weechat_printf (NULL, - _("%s%s: unable to create directory for logs " - "(\"%s\")"), - weechat_prefix ("error"), LOGGER_PLUGIN_NAME, - weechat_config_string (logger_config_file_path)); - free (logger_buffer->log_filename); - logger_buffer->log_filename = NULL; - return; - } - logger_buffer->log_file = - fopen (logger_buffer->log_filename, "a"); - if (!logger_buffer->log_file) - { - weechat_printf (NULL, - _("%s%s: unable to write log file \"%s\""), - weechat_prefix ("error"), LOGGER_PLUGIN_NAME, - logger_buffer->log_filename); - free (logger_buffer->log_filename); - logger_buffer->log_filename = NULL; - return; - } - - if (weechat_config_boolean (logger_config_file_info_lines)) - { - seconds = time (NULL); - date_tmp = localtime (&seconds); - buf_time[0] = '\0'; - if (date_tmp) - strftime (buf_time, sizeof (buf_time) - 1, - weechat_config_string (logger_config_file_time_format), - date_tmp); - snprintf (logger_buf_write, LOGGER_BUF_WRITE_SIZE, - _("%s\t**** Beginning of log ****"), - buf_time); - message = (charset) ? - weechat_iconv_from_internal (charset, logger_buf_write) : NULL; - fprintf (logger_buffer->log_file, - "%s\n", (message) ? message : logger_buf_write); - if (message) - free (message); - } + logger_buffer_free (logger_buffer); + return; } - - va_start (argptr, format); - vsnprintf (logger_buf_write, LOGGER_BUF_WRITE_SIZE, format, argptr); - va_end (argptr); - message = (charset) ? - weechat_iconv_from_internal (charset, logger_buf_write) : NULL; + logger_buffer->log_file = + fopen (logger_buffer->log_filename, "a"); + if (!logger_buffer->log_file) + { + weechat_printf (NULL, + _("%s%s: unable to write log file \"%s\""), + weechat_prefix ("error"), LOGGER_PLUGIN_NAME, + logger_buffer->log_filename); + logger_buffer_free (logger_buffer); + return; + } - fprintf (logger_buffer->log_file, - "%s\n", (message) ? message : logger_buf_write); - fflush (logger_buffer->log_file); - if (message) - free (message); + if (weechat_config_boolean (logger_config_file_info_lines)) + { + seconds = time (NULL); + date_tmp = localtime (&seconds); + buf_time[0] = '\0'; + if (date_tmp) + strftime (buf_time, sizeof (buf_time) - 1, + weechat_config_string (logger_config_file_time_format), + date_tmp); + snprintf (logger_buf_write, LOGGER_BUF_WRITE_SIZE, + _("%s\t**** Beginning of log ****"), + buf_time); + message = (charset) ? + weechat_iconv_from_internal (charset, logger_buf_write) : NULL; + fprintf (logger_buffer->log_file, + "%s\n", (message) ? message : logger_buf_write); + if (message) + free (message); + } + } + + va_start (argptr, format); + vsnprintf (logger_buf_write, LOGGER_BUF_WRITE_SIZE, format, argptr); + va_end (argptr); + + message = (charset) ? + weechat_iconv_from_internal (charset, logger_buf_write) : NULL; + + fprintf (logger_buffer->log_file, + "%s\n", (message) ? message : logger_buf_write); + fflush (logger_buffer->log_file); + if (message) + free (message); +} + +/* + * logger_stop: stop log for a logger buffer + */ + +void +logger_stop (struct t_logger_buffer *logger_buffer, int write_info_line) +{ + time_t seconds; + struct tm *date_tmp; + char buf_time[256]; + + if (!logger_buffer) + return; + + if (logger_buffer->log_enabled && logger_buffer->log_file) + { + if (write_info_line && weechat_config_boolean (logger_config_file_info_lines)) + { + seconds = time (NULL); + date_tmp = localtime (&seconds); + buf_time[0] = '\0'; + if (date_tmp) + strftime (buf_time, sizeof (buf_time) - 1, + weechat_config_string (logger_config_file_time_format), + date_tmp); + logger_write_line (logger_buffer, + _("%s\t**** End of log ****"), + buf_time); + } + fclose (logger_buffer->log_file); + logger_buffer->log_file = NULL; + } + logger_buffer_free (logger_buffer); +} + +/* + * logger_stop_all: end log for all buffers + */ + +void +logger_stop_all () +{ + struct t_logger_buffer *ptr_logger_buffer; + + for (ptr_logger_buffer = logger_buffers; ptr_logger_buffer; + ptr_logger_buffer = ptr_logger_buffer->next_buffer) + { + logger_stop (ptr_logger_buffer, 1); } } @@ -270,28 +522,43 @@ void logger_start_buffer (struct t_gui_buffer *buffer) { struct t_logger_buffer *ptr_logger_buffer; - char *log_filename; + int log_level, log_enabled; - if (!buffer || !weechat_config_boolean (logger_config_file_auto_log)) + if (!buffer) return; - ptr_logger_buffer = logger_buffer_search (buffer); - if (!ptr_logger_buffer) + log_level = logger_get_level_for_buffer (buffer); + log_enabled = weechat_config_boolean (logger_config_file_auto_log) + && (log_level > 0); + + ptr_logger_buffer = logger_buffer_search_buffer (buffer); + + /* logging is disabled for buffer */ + if (!log_enabled) { - log_filename = logger_get_filename (buffer); - if (!log_filename) - return; - ptr_logger_buffer = logger_buffer_add (buffer, log_filename); - free (log_filename); + /* stop logger if it is active */ + if (ptr_logger_buffer) + logger_stop (ptr_logger_buffer, 1); } - if (ptr_logger_buffer) + else { - if (ptr_logger_buffer->log_filename) + /* logging is enabled for buffer */ + if (ptr_logger_buffer) + ptr_logger_buffer->log_level = log_level; + else { - if (ptr_logger_buffer->log_file) + ptr_logger_buffer = logger_buffer_add (buffer, log_level); + + if (ptr_logger_buffer) { - fclose (ptr_logger_buffer->log_file); - ptr_logger_buffer->log_file = NULL; + if (ptr_logger_buffer->log_filename) + { + if (ptr_logger_buffer->log_file) + { + fclose (ptr_logger_buffer->log_file); + ptr_logger_buffer->log_file = NULL; + } + } } } } @@ -319,54 +586,125 @@ logger_start_buffer_all () } /* - * logger_stop: stop log for a logger buffer + * logger_list: show logging status for buffers */ void -logger_stop (struct t_logger_buffer *logger_buffer, int write_info_line) +logger_list () { - time_t seconds; - struct tm *date_tmp; - char buf_time[256]; + struct t_infolist *ptr_infolist; + struct t_logger_buffer *ptr_logger_buffer; + struct t_gui_buffer *ptr_buffer; + char status[128]; - if (!logger_buffer) - return; + weechat_printf (NULL, ""); + weechat_printf (NULL, _("Logging on buffers:")); - if (logger_buffer->log_file) + ptr_infolist = weechat_infolist_get ("buffer", NULL, NULL); + if (ptr_infolist) { - if (write_info_line && weechat_config_boolean (logger_config_file_info_lines)) + while (weechat_infolist_next (ptr_infolist)) { - seconds = time (NULL); - date_tmp = localtime (&seconds); - buf_time[0] = '\0'; - if (date_tmp) - strftime (buf_time, sizeof (buf_time) - 1, - weechat_config_string (logger_config_file_time_format), - date_tmp); - logger_write_line (logger_buffer, - _("%s\t**** End of log ****"), - buf_time); + ptr_buffer = weechat_infolist_pointer (ptr_infolist, "pointer"); + if (ptr_buffer) + { + ptr_logger_buffer = logger_buffer_search_buffer (ptr_buffer); + if (ptr_logger_buffer) + { + snprintf (status, sizeof (status), + _("logging (level: %d)"), + ptr_logger_buffer->log_level); + } + else + { + snprintf (status, sizeof (status), _("not logging")); + } + weechat_printf (NULL, + " %s[%s%d%s]%s (%s) %s%s%s: %s%s%s%s", + weechat_color("chat_delimiters"), + weechat_color("chat"), + weechat_infolist_integer (ptr_infolist, "number"), + weechat_color("chat_delimiters"), + weechat_color("chat"), + weechat_infolist_string (ptr_infolist, "plugin_name"), + weechat_color("chat_buffer"), + weechat_infolist_string (ptr_infolist, "name"), + weechat_color("chat"), + status, + (ptr_logger_buffer) ? " (" : "", + (ptr_logger_buffer) ? + ((ptr_logger_buffer->log_filename) ? + ptr_logger_buffer->log_filename : _("log not started")) : "", + (ptr_logger_buffer) ? ")" : ""); + } } - fclose (logger_buffer->log_file); - logger_buffer->log_file = NULL; + weechat_infolist_free (ptr_infolist); } - logger_buffer_free (logger_buffer); } /* - * logger_stop_all: end log for all buffers + * logger_set_buffer: enable/disable log on a buffer */ void -logger_stop_all () +logger_set_buffer (struct t_gui_buffer *buffer, const char *value) { - struct t_logger_buffer *ptr_logger_buffer; + char *name; + struct t_config_option *ptr_option; - for (ptr_logger_buffer = logger_buffers; ptr_logger_buffer; - ptr_logger_buffer = ptr_logger_buffer->next_buffer) + name = logger_build_option_name (buffer); + if (!name) + return; + + if (logger_config_set_level (name, value) != WEECHAT_CONFIG_OPTION_SET_ERROR) { - logger_stop (ptr_logger_buffer, 1); + ptr_option = logger_config_get_level (name); + if (ptr_option) + { + weechat_printf (NULL, _("%s: \"%s\" => level %d"), + LOGGER_PLUGIN_NAME, name, + weechat_config_integer (ptr_option)); + } + } + + free (name); +} + +/* + * logger_command_cb: callback for /logger command + */ + +int +logger_command_cb (void *data, struct t_gui_buffer *buffer, + int argc, char **argv, char **argv_eol) +{ + /* make C compiler happy */ + (void) data; + (void) argv_eol; + + if ((argc == 1) + || ((argc == 2) && (weechat_strcasecmp (argv[1], "list") == 0))) + { + logger_list (); + return WEECHAT_RC_OK; } + + if (argc > 1) + { + if (weechat_strcasecmp (argv[1], "set") == 0) + { + if (argc > 2) + logger_set_buffer (buffer, argv[2]); + return WEECHAT_RC_OK; + } + + if (weechat_strcasecmp (argv[1], "disable") == 0) + { + logger_set_buffer (buffer, "0"); + } + } + + return WEECHAT_RC_OK; } /* @@ -400,7 +738,7 @@ logger_buffer_closing_signal_cb (void *data, const char *signal, (void) signal; (void) type_data; - logger_stop (logger_buffer_search (signal_data), 1); + logger_stop (logger_buffer_search_buffer (signal_data), 1); return WEECHAT_RC_OK; } @@ -452,9 +790,12 @@ logger_backlog (struct t_gui_buffer *buffer, const char *filename, int lines) if (last_lines) logger_tail_free (last_lines); if (num_lines > 0) + { weechat_printf (buffer, _("===\t========== End of backlog (%d lines) =========="), num_lines); + weechat_buffer_set (buffer, "unread", ""); + } } /* @@ -474,17 +815,22 @@ logger_backlog_signal_cb (void *data, const char *signal, if (weechat_config_integer (logger_config_look_backlog) >= 0) { - ptr_logger_buffer = logger_buffer_search (signal_data); - if (ptr_logger_buffer && ptr_logger_buffer->log_filename - && ptr_logger_buffer->log_enabled) + ptr_logger_buffer = logger_buffer_search_buffer (signal_data); + if (ptr_logger_buffer && ptr_logger_buffer->log_enabled) { - ptr_logger_buffer->log_enabled = 0; + if (!ptr_logger_buffer->log_filename) + logger_set_log_filename (ptr_logger_buffer); - logger_backlog (signal_data, - ptr_logger_buffer->log_filename, - weechat_config_integer (logger_config_look_backlog)); - - ptr_logger_buffer->log_enabled = 1; + if (ptr_logger_buffer->log_filename) + { + ptr_logger_buffer->log_enabled = 0; + + logger_backlog (signal_data, + ptr_logger_buffer->log_filename, + weechat_config_integer (logger_config_look_backlog)); + + ptr_logger_buffer->log_enabled = 1; + } } } @@ -524,7 +870,7 @@ logger_stop_signal_cb (void *data, const char *signal, const char *type_data, (void) signal; (void) type_data; - ptr_logger_buffer = logger_buffer_search (signal_data); + ptr_logger_buffer = logger_buffer_search_buffer (signal_data); if (ptr_logger_buffer) logger_stop (ptr_logger_buffer, 0); @@ -532,27 +878,52 @@ logger_stop_signal_cb (void *data, const char *signal, const char *type_data, } /* + * logger_line_log_level: get log level for a line (with its tags) + */ + +int +logger_line_log_level (int tags_count, const char **tags) +{ + int i; + + for (i = 0; i < tags_count; i++) + { + if (strncmp (tags[i], "log", 3) == 0) + { + if (isdigit (tags[i][3])) + { + return (tags[i][3] - '0'); + } + } + } + + return 9; +} + +/* * logger_print_cb: callback for print hook */ int logger_print_cb (void *data, struct t_gui_buffer *buffer, time_t date, - int tags_count, char **tags, + int tags_count, const char **tags, const char *prefix, const char *message) { struct t_logger_buffer *ptr_logger_buffer; struct tm *date_tmp; char buf_time[256]; + int line_log_level; /* make C compiler happy */ (void) data; - (void) tags_count; - (void) tags; - ptr_logger_buffer = logger_buffer_search (buffer); - if (ptr_logger_buffer && ptr_logger_buffer->log_filename + line_log_level = logger_line_log_level (tags_count, tags); + + ptr_logger_buffer = logger_buffer_search_buffer (buffer); + if (ptr_logger_buffer && ptr_logger_buffer->log_enabled - && (date > 0)) + && (date > 0) + && (line_log_level <= ptr_logger_buffer->log_level)) { date_tmp = localtime (&date); buf_time[0] = '\0'; @@ -592,6 +963,43 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) if (logger_config_read () < 0) return WEECHAT_RC_ERROR; + /* callback for debug */ + weechat_hook_signal ("debug", &logger_debug_cb, NULL); + + /* command /logger */ + weechat_hook_command ("logger", + N_("logger plugin configuration"), + N_("[list | set level | disable]"), + N_(" list: show logging status for open buffers\n" + " set: set logging level on current buffer\n" + " level: level for messages to be logged (0 = " + "logging disabled, 1 = a few messages (most " + "important) .. 9 = all messages)\n" + "disable: disable logging on current buffer (set " + "level to 0)\n\n" + "Options \"logger.level.*\" and \"logger.mask.*\" " + "can be used to set level or mask for a buffer, " + "or buffers beginning with name.\n\n" + "Examples:\n" + " set level to 5 for current buffer:\n" + " /logger set 5\n" + " disable logging for current buffer:\n" + " /logger disable\n\n" + " set level to 3 for all IRC buffers:\n" + " /set logger.level.irc = 3\n" + " disable logging for main WeeChat buffer:\n" + " /set logger.level.core.weechat = 0\n" + " use a directory per IRC server and a file per channel inside:\n" + " /set logger.mask.irc = $server/$channel.weechatlog\n\n" + "Log levels used by IRC plugin:\n" + " 1: user message, notice, private\n" + " 2: nick change\n" + " 3: server message\n" + " 4: join/part/quit\n" + " 9: all other messages"), + "list|set|disable", + &logger_command_cb, NULL); + logger_start_buffer_all (); weechat_hook_signal ("buffer_open", &logger_buffer_open_signal_cb, NULL); diff --git a/src/plugins/logger/logger.h b/src/plugins/logger/logger.h index a999322f0..e623a371a 100644 --- a/src/plugins/logger/logger.h +++ b/src/plugins/logger/logger.h @@ -24,6 +24,9 @@ #define LOGGER_PLUGIN_NAME "logger" #define LOGGER_BUF_WRITE_SIZE (16*1024) +#define LOGGER_LEVEL_DEFAULT 9 + +extern int logger_debug; extern struct t_weechat_plugin *weechat_logger_plugin; |