diff --git a/src/plugins/logger/logger-buffer.c b/src/plugins/logger/logger-buffer.c index b9d59d5..cdc76b0 100644 --- a/src/plugins/logger/logger-buffer.c +++ b/src/plugins/logger/logger-buffer.c @@ -28,10 +28,13 @@ #include #include #include +#include +#include #include "../weechat-plugin.h" #include "logger.h" #include "logger-buffer.h" +#include "logger-config.h" struct t_logger_buffer *logger_buffers = NULL; @@ -77,10 +80,11 @@ logger_buffer_add (struct t_gui_buffer *buffer, int log_level) if (weechat_logger_plugin->debug) { - weechat_printf (NULL, - "%s: start logging for buffer \"%s\"", - LOGGER_PLUGIN_NAME, - weechat_buffer_get_string (buffer, "name")); + weechat_printf_tags (NULL, + "no_log", + "%s: start logging for buffer \"%s\"", + LOGGER_PLUGIN_NAME, + weechat_buffer_get_string (buffer, "name")); } new_logger_buffer = malloc (sizeof (*new_logger_buffer)); @@ -92,6 +96,8 @@ logger_buffer_add (struct t_gui_buffer *buffer, int log_level) new_logger_buffer->log_enabled = 1; new_logger_buffer->log_level = log_level; new_logger_buffer->write_start_info_line = 1; + new_logger_buffer->lines_count = 0; + new_logger_buffer->lines_array = NULL; new_logger_buffer->prev_buffer = last_logger_buffer; new_logger_buffer->next_buffer = NULL; @@ -152,6 +158,458 @@ logger_buffer_search_log_filename (const char *log_filename) } /* + * logger_buffer_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) + */ + +const char * +logger_buffer_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_buffer_get_mask_expanded: get expanded mask for a buffer, special + * vars are replaced: + * - local variables of buffer ($plugin, + * $name, ..) + * - date/time specifiers (see man strftime) + * note: returned value has to be free() after + * use + */ + +char * +logger_buffer_get_mask_expanded (struct t_logger_buffer *logger_buffer, + const char *mask) +{ + char *mask2, *mask_decoded, *mask_decoded2, *mask_decoded3, *mask_decoded4; + const char *dir_separator; + int length; + time_t seconds; + struct tm *date_tmp; + + mask2 = NULL; + mask_decoded = NULL; + mask_decoded2 = NULL; + mask_decoded3 = NULL; + mask_decoded4 = NULL; + + dir_separator = weechat_info_get ("dir_separator", ""); + if (!dir_separator) + return NULL; + + /* + * we first replace directory separator (commonly '/') by \01 because + * buffer mask can contain this char, and will be replaced by replacement + * char ('_' by default) + */ + mask2 = weechat_string_replace (mask, dir_separator, "\01"); + if (!mask2) + goto end; + + mask_decoded = weechat_buffer_string_replace_local_var (logger_buffer->buffer, + mask2); + if (!mask_decoded) + goto end; + + mask_decoded2 = weechat_string_replace (mask_decoded, + dir_separator, + weechat_config_string (logger_config_file_replacement_char)); + if (!mask_decoded2) + goto end; + + /* restore directory separator */ + mask_decoded3 = weechat_string_replace (mask_decoded2, + "\01", dir_separator); + if (!mask_decoded3) + goto end; + + /* replace date/time specifiers in mask */ + length = strlen (mask_decoded3) + 256 + 1; + mask_decoded4 = malloc (length); + if (!mask_decoded4) + goto end; + seconds = time (NULL); + date_tmp = localtime (&seconds); + mask_decoded4[0] = '\0'; + strftime (mask_decoded4, length - 1, mask_decoded3, date_tmp); + + /* convert to lower case? */ + if (weechat_config_boolean (logger_config_file_name_lower_case)) + weechat_string_tolower (mask_decoded4); + + if (weechat_logger_plugin->debug) + { + weechat_printf_tags (NULL, + "no_log", + "%s: buffer = \"%s\", mask = \"%s\", " + "decoded mask = \"%s\"", + LOGGER_PLUGIN_NAME, + weechat_buffer_get_string (logger_buffer->buffer, + "name"), + mask, mask_decoded4); + } + +end: + if (mask2) + free (mask2); + if (mask_decoded) + free (mask_decoded); + if (mask_decoded2) + free (mask_decoded2); + if (mask_decoded3) + free (mask_decoded3); + + return mask_decoded4; +} + +/* + * logger_buffer_get_filename: build log filename for a buffer + */ + +char * +logger_buffer_get_filename (struct t_logger_buffer *logger_buffer) +{ + char *res, *mask_expanded, *file_path; + const char *mask; + const char *dir_separator, *weechat_dir; + int length; + + res = NULL; + mask_expanded = NULL; + file_path = NULL; + + dir_separator = weechat_info_get ("dir_separator", ""); + if (!dir_separator) + return NULL; + weechat_dir = weechat_info_get ("weechat_dir", ""); + if (!weechat_dir) + return NULL; + + /* get filename mask for buffer */ + mask = logger_buffer_get_mask_for_buffer (logger_buffer->buffer); + if (!mask) + { + weechat_printf_tags (NULL, + "no_log", + _("%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 (logger_buffer->buffer, "name")); + return NULL; + } + + mask_expanded = logger_buffer_get_mask_expanded (logger_buffer, mask); + if (!mask_expanded) + goto end; + + file_path = logger_get_file_path (); + if (!file_path) + goto end; + + /* build string with path + mask */ + length = strlen (file_path) + strlen (dir_separator) + + strlen (mask_expanded) + 1; + res = malloc (length); + if (res) + { + snprintf (res, length, "%s%s%s", + file_path, + (file_path[strlen (file_path) - 1] == dir_separator[0]) ? "" : dir_separator, + mask_expanded); + } + +end: + if (mask_expanded) + free (mask_expanded); + if (file_path) + free (file_path); + + return res; +} + +/* + * logger_buffer_set_log_filename: set log filename for a logger buffer + */ + +void +logger_buffer_set_log_filename (struct t_logger_buffer *logger_buffer) +{ + char *log_filename, *pos_last_sep; + const char *dir_separator; + struct t_logger_buffer *ptr_logger_buffer; + + /* get log filename for buffer */ + log_filename = logger_buffer_get_filename (logger_buffer); + if (!log_filename) + { + weechat_printf_tags (NULL, + "no_log", + _("%s%s: not enough memory"), + weechat_prefix ("error"), + LOGGER_PLUGIN_NAME); + return; + } + + /* log file is already used by another buffer? */ + ptr_logger_buffer = logger_buffer_search_log_filename (log_filename); + if (ptr_logger_buffer) + { + weechat_printf_tags (NULL, + "no_log", + _("%s%s: unable to start logging for buffer " + "\"%s\": filename \"%s\" is already used 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; + } + + /* create directory for path in "log_filename" */ + dir_separator = weechat_info_get ("dir_separator", ""); + if (dir_separator) + { + pos_last_sep = strrchr (log_filename, dir_separator[0]); + if (pos_last_sep) + { + pos_last_sep[0] = '\0'; + weechat_mkdir_parents (log_filename, 0700); + pos_last_sep[0] = dir_separator[0]; + } + } + + /* set log filename */ + logger_buffer->log_filename = log_filename; +} + +/* + * logger_buffer_add_line_in_array: add a line in array + */ + +void +logger_buffer_add_line_in_array (struct t_logger_buffer *logger_buffer, + const char *line) +{ + if (line && line[0]) + { + logger_buffer->lines_count++; + + if (logger_buffer->lines_array) + { + logger_buffer->lines_array = realloc (logger_buffer->lines_array, + logger_buffer->lines_count * + sizeof ((*logger_buffer->lines_array))); + } + else + { + logger_buffer->lines_array = malloc (logger_buffer->lines_count * + sizeof ((*logger_buffer->lines_array))); + } + + logger_buffer->lines_array[logger_buffer->lines_count - 1] = strdup (line); + } +} + +/* + * logger_buffer_add_line: log a line in a logger buffer + */ + +void +logger_buffer_add_line (struct t_logger_buffer *logger_buffer, + const char *format, ...) +{ + va_list argptr; + char *message, buf_time[256]; + const char *charset; + time_t seconds; + struct tm *date_tmp; + int log_level; + + /* create write buffer if needed */ + if (!logger_buf_write) + logger_buf_write = malloc (LOGGER_BUF_WRITE_SIZE); + if (!logger_buf_write) + return; + + /* check log level */ + log_level = logger_get_level_for_buffer (logger_buffer->buffer); + if (log_level == 0) + { + logger_buffer_free (logger_buffer); + return; + } + + /* get terminal charset */ + charset = weechat_info_get ("charset_terminal", ""); + + /* write info line */ + if (weechat_config_boolean (logger_config_file_info_lines) + && logger_buffer->write_start_info_line) + { + 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; + logger_buffer_add_line_in_array (logger_buffer, + (message) ? message : logger_buf_write); + if (message) + free (message); + } + logger_buffer->write_start_info_line = 0; + + /* format string */ + va_start (argptr, format); + vsnprintf (logger_buf_write, LOGGER_BUF_WRITE_SIZE, format, argptr); + va_end (argptr); + + /* add line */ + message = (charset) ? + weechat_iconv_from_internal (charset, logger_buf_write) : NULL; + logger_buffer_add_line_in_array (logger_buffer, + (message) ? message : logger_buf_write); + if (message) + free (message); +} + +/* + * logger_buffer_write_lines: write all lines in logger buffer to log file + */ + +void +logger_buffer_write_lines (struct t_logger_buffer *logger_buffer) +{ + int i; + + /* nothing to write? just return */ + if (!logger_buffer || (logger_buffer->lines_count == 0)) + return; + + /* create directory and file */ + if (!logger_buffer->log_file) + { + if (!logger_create_directory ()) + { + weechat_printf_tags (NULL, + "no_log", + _("%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_buffer_set_log_filename (logger_buffer); + if (!logger_buffer->log_filename) + { + logger_buffer_free (logger_buffer); + return; + } + + logger_buffer->log_file = + fopen (logger_buffer->log_filename, "a"); + if (!logger_buffer->log_file) + { + weechat_printf_tags (NULL, + "no_log", + _("%s%s: unable to write log file \"%s\""), + weechat_prefix ("error"), LOGGER_PLUGIN_NAME, + logger_buffer->log_filename); + logger_buffer_free (logger_buffer); + return; + } + } + + if (weechat_logger_plugin->debug >= 2) + { + weechat_printf_tags (NULL, + "no_log", + "%s: writing %d lines for buffer %s.%s", + LOGGER_PLUGIN_NAME, + logger_buffer->lines_count, + weechat_buffer_get_string (logger_buffer->buffer, "plugin"), + weechat_buffer_get_string (logger_buffer->buffer, "name")); + } + + /* write lines in file and clear array */ + for (i = 0; i < logger_buffer->lines_count; i++) + { + if (logger_buffer->lines_array[i]) + { + fprintf (logger_buffer->log_file, + "%s\n", logger_buffer->lines_array[i]); + free (logger_buffer->lines_array[i]); + } + } + logger_buffer->lines_count = 0; + free (logger_buffer->lines_array); + logger_buffer->lines_array = NULL; + + /* flush file */ + fflush (logger_buffer->log_file); +} + +/* * logger_buffer_free: remove a logger buffer from list */ @@ -189,10 +647,11 @@ logger_buffer_free (struct t_logger_buffer *logger_buffer) if (weechat_logger_plugin->debug) { - weechat_printf (NULL, - "%s: stop logging for buffer \"%s\"", - LOGGER_PLUGIN_NAME, - weechat_buffer_get_string (ptr_buffer, "name")); + weechat_printf_tags (NULL, + "no_log", + "%s: stop logging for buffer \"%s\"", + LOGGER_PLUGIN_NAME, + weechat_buffer_get_string (ptr_buffer, "name")); } } diff --git a/src/plugins/logger/logger-buffer.h b/src/plugins/logger/logger-buffer.h index 1255a3d..1a0780e 100644 --- a/src/plugins/logger/logger-buffer.h +++ b/src/plugins/logger/logger-buffer.h @@ -31,6 +31,8 @@ struct t_logger_buffer int log_level; /* log level (0..9) */ int write_start_info_line; /* 1 if start info line must be */ /* written in file */ + int lines_count; /* number of lines in array */ + char **lines_array; /* lines in memory before write */ struct t_logger_buffer *prev_buffer; /* link to previous buffer */ struct t_logger_buffer *next_buffer; /* link to next buffer */ }; @@ -43,6 +45,11 @@ extern struct t_logger_buffer *logger_buffer_add (struct t_gui_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 char *logger_buffer_get_filename (struct t_logger_buffer *logger_buffer); +extern void logger_buffer_set_log_filename (struct t_logger_buffer *logger_buffer); +extern void logger_buffer_add_line (struct t_logger_buffer *logger_buffer, + const char *format, ...); +extern void logger_buffer_write_lines (struct t_logger_buffer *logger_buffer); extern void logger_buffer_free (struct t_logger_buffer *logger_buffer); extern int logger_buffer_add_to_infolist (struct t_infolist *infolist, struct t_logger_buffer *logger_buffer); diff --git a/src/plugins/logger/logger-config.c b/src/plugins/logger/logger-config.c index c7d67bd..62467b5 100644 --- a/src/plugins/logger/logger-config.c +++ b/src/plugins/logger/logger-config.c @@ -48,6 +48,8 @@ struct t_config_option *logger_config_file_mask; struct t_config_option *logger_config_file_replacement_char; struct t_config_option *logger_config_file_info_lines; struct t_config_option *logger_config_file_time_format; +struct t_config_option *logger_config_file_timer_delay; +struct t_config_option *logger_config_file_timer_max_lines; /* @@ -69,6 +71,49 @@ logger_config_change_file_option_restart_log (void *data, } /* + * logger_config_timer_delay_change: called when timer delay is changed + */ + +void +logger_config_timer_delay_change (void *data, + struct t_config_option *option) +{ + /* make C compiler happy */ + (void) data; + (void) option; + + if (logger_config_loading) + return; + + if (logger_timer_write) + { + if (weechat_logger_plugin->debug) + { + weechat_printf_tags (NULL, + "no_log", + "%s: stopping timer", LOGGER_PLUGIN_NAME); + } + weechat_unhook (logger_timer_write); + logger_timer_write = NULL; + } + + if (weechat_config_integer (logger_config_file_timer_delay) > 0) + { + if (weechat_logger_plugin->debug) + { + weechat_printf_tags (NULL, + "no_log", + "%s: starting timer (interval: %d seconds)", + LOGGER_PLUGIN_NAME, + weechat_config_integer (logger_config_file_timer_delay)); + } + logger_timer_write = weechat_hook_timer (weechat_config_integer (logger_config_file_timer_delay) * 1000, + 0, 0, + &logger_timer_write_cb, NULL); + } +} + +/* * logger_config_level_change: called when a level option is changed */ @@ -395,6 +440,24 @@ logger_config_init () N_("timestamp used in log files (see man strftime for date/time " "specifiers)"), NULL, 0, 0, "%Y-%m-%d %H:%M:%S", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); + logger_config_file_timer_delay = weechat_config_new_option ( + logger_config_file, ptr_section, + "timer_delay", "integer", + N_("number of seconds between writes in log files; a long delay will " + "use more memory to store lines in memory before writing them in " + "log files (see option logger.file.timer_max_lines) (0 = do not " + "use timer and write immediately lines in log files)"), + NULL, 0, 3600, "120", NULL, 0, NULL, NULL, + &logger_config_timer_delay_change, NULL, NULL, NULL); + logger_config_file_timer_max_lines = weechat_config_new_option ( + logger_config_file, ptr_section, + "timer_max_lines", "integer", + N_("max number of lines per buffer to keep in memory before writing " + "them in log files; a high value will use more memory to " + "store lines in memory before writing them in log files (this " + "option is used only if timer is used, see option " + "logger.file.timer_delay)"), + NULL, 1, 1000000, "100", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL); /* level */ ptr_section = weechat_config_new_section (logger_config_file, "level", @@ -442,6 +505,8 @@ logger_config_read () rc = weechat_config_read (logger_config_file); logger_config_loading = 0; + logger_config_timer_delay_change (NULL, NULL); + return rc; } diff --git a/src/plugins/logger/logger-config.h b/src/plugins/logger/logger-config.h index 8cac0d2..d56a96e 100644 --- a/src/plugins/logger/logger-config.h +++ b/src/plugins/logger/logger-config.h @@ -32,6 +32,8 @@ extern struct t_config_option *logger_config_file_mask; extern struct t_config_option *logger_config_file_replacement_char; 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_file_timer_delay; +extern struct t_config_option *logger_config_file_timer_max_lines; extern struct t_config_option *logger_config_get_level (const char *name); extern int logger_config_set_level (const char *name, const char *value); diff --git a/src/plugins/logger/logger.c b/src/plugins/logger/logger.c index ca3b2ac..74ada99 100644 --- a/src/plugins/logger/logger.c +++ b/src/plugins/logger/logger.c @@ -27,14 +27,9 @@ #include #include -#include #include -#include #include #include -#include -#include -#include #include #include "../weechat-plugin.h" @@ -53,7 +48,8 @@ WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE); struct t_weechat_plugin *weechat_logger_plugin = NULL; -char *logger_buf_write = NULL; /* buffer for writing a line */ +struct t_hook *logger_timer_write = NULL; /* timer to write in log files */ +char *logger_buf_write = NULL; /* buffer for writing a line */ /* @@ -111,9 +107,10 @@ logger_get_file_path () if (weechat_logger_plugin->debug) { - weechat_printf (NULL, - "%s: file path = \"%s\"", - LOGGER_PLUGIN_NAME, file_path3); + weechat_printf_tags (NULL, + "no_log", + "%s: file path = \"%s\"", + LOGGER_PLUGIN_NAME, file_path3); } end: @@ -236,370 +233,6 @@ logger_get_level_for_buffer (struct t_gui_buffer *buffer) } /* - * 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) - */ - -const 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_mask_expanded: get expanded mask for a buffer, special vars are - * replaced: - * - local variables of buffer ($plugin, $name, ..) - * - date/time specifiers (see man strftime) - * note: returned value has to be free() after use - */ - -char * -logger_get_mask_expanded (struct t_gui_buffer *buffer, const char *mask) -{ - char *mask2, *mask_decoded, *mask_decoded2, *mask_decoded3, *mask_decoded4; - const char *dir_separator; - int length; - time_t seconds; - struct tm *date_tmp; - - mask2 = NULL; - mask_decoded = NULL; - mask_decoded2 = NULL; - mask_decoded3 = NULL; - mask_decoded4 = NULL; - - dir_separator = weechat_info_get ("dir_separator", ""); - if (!dir_separator) - return NULL; - - /* - * we first replace directory separator (commonly '/') by \01 because - * buffer mask can contain this char, and will be replaced by replacement - * char ('_' by default) - */ - mask2 = weechat_string_replace (mask, dir_separator, "\01"); - if (!mask2) - goto end; - - mask_decoded = weechat_buffer_string_replace_local_var (buffer, mask2); - if (!mask_decoded) - goto end; - - mask_decoded2 = weechat_string_replace (mask_decoded, - dir_separator, - weechat_config_string (logger_config_file_replacement_char)); - if (!mask_decoded2) - goto end; - - /* restore directory separator */ - mask_decoded3 = weechat_string_replace (mask_decoded2, - "\01", dir_separator); - if (!mask_decoded3) - goto end; - - /* replace date/time specifiers in mask */ - length = strlen (mask_decoded3) + 256 + 1; - mask_decoded4 = malloc (length); - if (!mask_decoded4) - goto end; - seconds = time (NULL); - date_tmp = localtime (&seconds); - mask_decoded4[0] = '\0'; - strftime (mask_decoded4, length - 1, mask_decoded3, date_tmp); - - /* convert to lower case? */ - if (weechat_config_boolean (logger_config_file_name_lower_case)) - weechat_string_tolower (mask_decoded4); - - if (weechat_logger_plugin->debug) - { - weechat_printf (NULL, - "%s: buffer = \"%s\", mask = \"%s\", " - "decoded mask = \"%s\"", - LOGGER_PLUGIN_NAME, - weechat_buffer_get_string (buffer, "name"), - mask, mask_decoded4); - } - -end: - if (mask2) - free (mask2); - if (mask_decoded) - free (mask_decoded); - if (mask_decoded2) - free (mask_decoded2); - if (mask_decoded3) - free (mask_decoded3); - - return mask_decoded4; -} - -/* - * logger_get_filename: build log filename for a buffer - */ - -char * -logger_get_filename (struct t_gui_buffer *buffer) -{ - char *res, *mask_expanded, *file_path; - const char *mask; - const char *dir_separator, *weechat_dir; - int length; - - res = NULL; - mask_expanded = NULL; - file_path = NULL; - - dir_separator = weechat_info_get ("dir_separator", ""); - if (!dir_separator) - return NULL; - weechat_dir = weechat_info_get ("weechat_dir", ""); - if (!weechat_dir) - return 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_expanded = logger_get_mask_expanded (buffer, mask); - if (!mask_expanded) - goto end; - - file_path = logger_get_file_path (); - if (!file_path) - goto end; - - /* build string with path + mask */ - length = strlen (file_path) + strlen (dir_separator) + - strlen (mask_expanded) + 1; - res = malloc (length); - if (res) - { - snprintf (res, length, "%s%s%s", - file_path, - (file_path[strlen (file_path) - 1] == dir_separator[0]) ? "" : dir_separator, - mask_expanded); - } - -end: - if (mask_expanded) - free (mask_expanded); - if (file_path) - free (file_path); - - return res; -} - -/* - * 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, *pos_last_sep; - const char *dir_separator; - struct t_logger_buffer *ptr_logger_buffer; - - /* get log filename for 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; - } - - /* log file is already used by another buffer? */ - 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 used 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; - } - - /* create directory for path in "log_filename" */ - dir_separator = weechat_info_get ("dir_separator", ""); - if (dir_separator) - { - pos_last_sep = strrchr (log_filename, dir_separator[0]); - if (pos_last_sep) - { - pos_last_sep[0] = '\0'; - weechat_mkdir_parents (log_filename, 0700); - pos_last_sep[0] = dir_separator[0]; - } - } - - /* set log filename */ - logger_buffer->log_filename = log_filename; -} - -/* - * logger_write_line: write a line to log file - */ - -void -logger_write_line (struct t_logger_buffer *logger_buffer, - const char *format, ...) -{ - va_list argptr; - char *message, buf_time[256]; - const char *charset; - time_t seconds; - struct tm *date_tmp; - int log_level; - - if (!logger_buf_write) - logger_buf_write = malloc (LOGGER_BUF_WRITE_SIZE); - if (!logger_buf_write) - return; - - charset = weechat_info_get ("charset_terminal", ""); - - if (!logger_buffer->log_file) - { - log_level = logger_get_level_for_buffer (logger_buffer->buffer); - if (log_level == 0) - { - logger_buffer_free (logger_buffer); - return; - } - 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_filename) - { - logger_buffer_free (logger_buffer); - 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); - logger_buffer_free (logger_buffer); - return; - } - - if (weechat_config_boolean (logger_config_file_info_lines) - && logger_buffer->write_start_info_line) - { - 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->write_start_info_line = 0; - } - - 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 */ @@ -613,7 +246,7 @@ logger_stop (struct t_logger_buffer *logger_buffer, int write_info_line) if (!logger_buffer) return; - if (logger_buffer->log_enabled && logger_buffer->log_file) + if (logger_buffer->log_enabled) { if (write_info_line && weechat_config_boolean (logger_config_file_info_lines)) { @@ -626,11 +259,13 @@ logger_stop (struct t_logger_buffer *logger_buffer, int write_info_line) weechat_config_string (logger_config_file_time_format), date_tmp); } - logger_write_line (logger_buffer, - _("%s\t**** End of log ****"), - buf_time); + logger_buffer_add_line (logger_buffer, + _("%s\t**** End of log ****"), + buf_time); } - fclose (logger_buffer->log_file); + logger_buffer_write_lines (logger_buffer); + if (logger_buffer->log_file) + fclose (logger_buffer->log_file); logger_buffer->log_file = NULL; } logger_buffer_free (logger_buffer); @@ -684,16 +319,11 @@ logger_start_buffer (struct t_gui_buffer *buffer, int write_info_line) { ptr_logger_buffer = logger_buffer_add (buffer, log_level); - if (ptr_logger_buffer) + if (ptr_logger_buffer && ptr_logger_buffer->log_filename + && ptr_logger_buffer->log_file) { - if (ptr_logger_buffer->log_filename) - { - if (ptr_logger_buffer->log_file) - { - fclose (ptr_logger_buffer->log_file); - ptr_logger_buffer->log_file = NULL; - } - } + fclose (ptr_logger_buffer->log_file); + ptr_logger_buffer->log_file = NULL; } } if (ptr_logger_buffer) @@ -772,7 +402,7 @@ logger_list () (ptr_logger_buffer) ? " (" : "", (ptr_logger_buffer) ? ((ptr_logger_buffer->log_filename) ? - ptr_logger_buffer->log_filename : _("log not started")) : "", + ptr_logger_buffer->log_filename : _("nothing written yet")) : "", (ptr_logger_buffer) ? ")" : ""); } } @@ -995,7 +625,7 @@ logger_backlog_signal_cb (void *data, const char *signal, if (ptr_logger_buffer && ptr_logger_buffer->log_enabled) { if (!ptr_logger_buffer->log_filename) - logger_set_log_filename (ptr_logger_buffer); + logger_buffer_set_log_filename (ptr_logger_buffer); if (ptr_logger_buffer->log_filename) { @@ -1076,7 +706,7 @@ logger_adjust_log_filenames () ptr_logger_buffer = logger_buffer_search_buffer (ptr_buffer); if (ptr_logger_buffer && ptr_logger_buffer->log_filename) { - log_filename = logger_get_filename (ptr_logger_buffer->buffer); + log_filename = logger_buffer_get_filename (ptr_logger_buffer); if (log_filename) { if (strcmp (log_filename, ptr_logger_buffer->log_filename) != 0) @@ -1182,11 +812,22 @@ logger_print_cb (void *data, struct t_gui_buffer *buffer, time_t date, date_tmp); } - logger_write_line (ptr_logger_buffer, - "%s\t%s\t%s", - buf_time, - (prefix) ? prefix : "", - message); + /* add line in logger buffer */ + logger_buffer_add_line (ptr_logger_buffer, + "%s\t%s\t%s", + buf_time, + (prefix) ? prefix : "", + message); + + /* + * write immediately lines in logger buffer if timer is not running + * or if max_lines is reached + */ + if (!logger_timer_write + || (ptr_logger_buffer->lines_count >= weechat_config_integer (logger_config_file_timer_max_lines))) + { + logger_buffer_write_lines (ptr_logger_buffer); + } } } @@ -1194,6 +835,28 @@ logger_print_cb (void *data, struct t_gui_buffer *buffer, time_t date, } /* + * logger_timer_write_cb: callback for logger timer + */ + +int +logger_timer_write_cb (void *data, int remaining_calls) +{ + struct t_logger_buffer *ptr_logger_buffer; + + /* make C compiler happy */ + (void) data; + (void) remaining_calls; + + for (ptr_logger_buffer = logger_buffers; ptr_logger_buffer; + ptr_logger_buffer = ptr_logger_buffer->next_buffer) + { + logger_buffer_write_lines (ptr_logger_buffer); + } + + return WEECHAT_RC_OK; +} + +/* * weechat_plugin_init: initialize logger plugin */ diff --git a/src/plugins/logger/logger.h b/src/plugins/logger/logger.h index ba7cc56..1ef7d27 100644 --- a/src/plugins/logger/logger.h +++ b/src/plugins/logger/logger.h @@ -26,10 +26,20 @@ #define LOGGER_BUF_WRITE_SIZE (16*1024) #define LOGGER_LEVEL_DEFAULT 9 +struct t_gui_buffer; + extern struct t_weechat_plugin *weechat_logger_plugin; +extern struct t_hook *logger_timer_write; +extern char *logger_buf_write; + +extern char *logger_get_file_path (); +extern int logger_create_directory (); +extern char *logger_build_option_name (struct t_gui_buffer *buffer); +extern int logger_get_level_for_buffer (struct t_gui_buffer *buffer); extern void logger_start_buffer_all (int write_info_line); extern void logger_stop_all (int write_info_line); extern void logger_adjust_log_filenames (); +extern int logger_timer_write_cb (void *data, int remaining_calls); #endif /* __WEECHAT_LOGGER_H */