diff --git a/src/command/command.c b/src/command/command.c index 7738e0d0..97442e45 100644 --- a/src/command/command.c +++ b/src/command/command.c @@ -68,6 +68,7 @@ static char * _connect_autocomplete(char *input, int *size); static char * _statuses_autocomplete(char *input, int *size); static char * _alias_autocomplete(char *input, int *size); static char * _join_autocomplete(char *input, int *size); +static char * _log_autocomplete(char *input, int *size); GHashTable *commands = NULL; @@ -637,12 +638,15 @@ static struct cmd_t command_defs[] = NULL } } }, { "/log", - cmd_log, parse_args, 2, 2, &cons_log_setting, - { "/log maxsize value", "Manage system logging settings.", - { "/log maxsize value", - "------------------", - "maxsize : When log file size exceeds this value it will be automatically", - " rotated (file will be renamed). Default value is 1048580 (1MB)", + cmd_log, parse_args, 1, 2, &cons_log_setting, + { "/log [property] [value]", "Manage system logging settings.", + { "/log [property] [value]", + "-----------------------", + "where : Show the current log file location.", + "Property may be one of:", + "rotate : Rotate log, accepts 'on' or 'off', defaults to 'on'.", + "maxsize : With rotate enabled, specifies the max log size, defaults to 1048580 (1MB).", + "shared : Share logs between all instances, accepts 'on' or 'off', defaults to 'on'.", NULL } } }, { "/reconnect", @@ -957,6 +961,9 @@ cmd_init(void) log_ac = autocomplete_new(); autocomplete_add(log_ac, "maxsize"); + autocomplete_add(log_ac, "rotate"); + autocomplete_add(log_ac, "shared"); + autocomplete_add(log_ac, "where"); autoaway_ac = autocomplete_new(); autocomplete_add(autoaway_ac, "mode"); @@ -1500,8 +1507,8 @@ _cmd_complete_parameters(char *input, int *size) } } - gchar *cmds[] = { "/help", "/prefs", "/log", "/disco", "/close", "/wins" }; - Autocomplete completers[] = { help_ac, prefs_ac, log_ac, disco_ac, close_ac, wins_ac }; + gchar *cmds[] = { "/help", "/prefs", "/disco", "/close", "/wins" }; + Autocomplete completers[] = { help_ac, prefs_ac, disco_ac, close_ac, wins_ac }; for (i = 0; i < ARRAY_SIZE(cmds); i++) { result = autocomplete_param_with_ac(input, size, cmds[i], completers[i]); @@ -1513,7 +1520,7 @@ _cmd_complete_parameters(char *input, int *size) } autocompleter acs[] = { _who_autocomplete, _sub_autocomplete, _notify_autocomplete, - _autoaway_autocomplete, _theme_autocomplete, + _autoaway_autocomplete, _theme_autocomplete, _log_autocomplete, _account_autocomplete, _roster_autocomplete, _group_autocomplete, _bookmark_autocomplete, _autoconnect_autocomplete, _otr_autocomplete, _connect_autocomplete, _statuses_autocomplete, _alias_autocomplete, @@ -1662,6 +1669,29 @@ _autoaway_autocomplete(char *input, int *size) return NULL; } +static char * +_log_autocomplete(char *input, int *size) +{ + char *result = NULL; + + result = autocomplete_param_with_func(input, size, "/log rotate", + prefs_autocomplete_boolean_choice); + if (result != NULL) { + return result; + } + result = autocomplete_param_with_func(input, size, "/log shared", + prefs_autocomplete_boolean_choice); + if (result != NULL) { + return result; + } + result = autocomplete_param_with_ac(input, size, "/log", log_ac); + if (result != NULL) { + return result; + } + + return NULL; +} + static char * _autoconnect_autocomplete(char *input, int *size) { diff --git a/src/command/commands.c b/src/command/commands.c index 3019680c..c7edc57a 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -2290,14 +2290,43 @@ cmd_log(gchar **args, struct cmd_help_t help) int intval; if (strcmp(subcmd, "maxsize") == 0) { + if (value == NULL) { + cons_show("Usage: %s", help.usage); + return TRUE; + } if (_strtoi(value, &intval, PREFS_MIN_LOG_SIZE, INT_MAX) == 0) { prefs_set_max_log_size(intval); cons_show("Log maxinum size set to %d bytes", intval); } - } else { - cons_show("Usage: %s", help.usage); + return TRUE; } + if (strcmp(subcmd, "rotate") == 0) { + if (value == NULL) { + cons_show("Usage: %s", help.usage); + return TRUE; + } + return _cmd_set_boolean_preference(value, help, "Log rotate", PREF_LOG_ROTATE); + } + + if (strcmp(subcmd, "shared") == 0) { + if (value == NULL) { + cons_show("Usage: %s", help.usage); + return TRUE; + } + gboolean result = _cmd_set_boolean_preference(value, help, "Shared log", PREF_LOG_SHARED); + log_reinit(); + return result; + } + + if (strcmp(subcmd, "where") == 0) { + char *logfile = get_log_file_location(); + cons_show("Log file: %s", logfile); + return TRUE; + } + + cons_show("Usage: %s", help.usage); + /* TODO: make 'level' subcommand for debug level */ return TRUE; diff --git a/src/config/preferences.c b/src/config/preferences.c index 37aeba2b..21f603cf 100644 --- a/src/config/preferences.c +++ b/src/config/preferences.c @@ -406,6 +406,8 @@ _get_group(preference_t pref) case PREF_CHLOG: case PREF_GRLOG: case PREF_OTR_LOG: + case PREF_LOG_ROTATE: + case PREF_LOG_SHARED: return PREF_GROUP_LOGGING; case PREF_AUTOAWAY_CHECK: case PREF_AUTOAWAY_MODE: @@ -477,6 +479,10 @@ _get_key(preference_t pref) return "otr"; case PREF_OTR_WARN: return "otr.warn"; + case PREF_LOG_ROTATE: + return "rotate"; + case PREF_LOG_SHARED: + return "shared"; default: return NULL; } @@ -490,6 +496,8 @@ _get_default_boolean(preference_t pref) case PREF_TITLEBAR: case PREF_OTR_WARN: case PREF_AUTOAWAY_CHECK: + case PREF_LOG_ROTATE: + case PREF_LOG_SHARED: return TRUE; default: return FALSE; diff --git a/src/config/preferences.h b/src/config/preferences.h index 25b2c7db..df1cf7ac 100644 --- a/src/config/preferences.h +++ b/src/config/preferences.h @@ -62,7 +62,9 @@ typedef enum { PREF_AUTOAWAY_MESSAGE, PREF_CONNECT_ACCOUNT, PREF_OTR_LOG, - PREF_OTR_WARN + PREF_OTR_WARN, + PREF_LOG_ROTATE, + PREF_LOG_SHARED } preference_t; typedef struct prof_alias_t { diff --git a/src/log.c b/src/log.c index 68ba476c..b30c68cb 100644 --- a/src/log.c +++ b/src/log.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "glib.h" @@ -36,6 +37,7 @@ #define PROF "prof" static FILE *logp; +GString *mainlogfile; static GTimeZone *tz; static GDateTime *dt; @@ -60,7 +62,7 @@ static char * _get_log_filename(const char * const other, const char * const log static char * _get_groupchat_log_filename(const char * const room, const char * const login, GDateTime *dt, gboolean create); static gchar * _get_chatlog_dir(void); -static gchar * _get_log_file(void); +static gchar * _get_main_log_file(void); static void _rotate_log_file(void); static char* _log_string_from_level(log_level_t level); @@ -117,11 +119,25 @@ log_init(log_level_t filter) { level_filter = filter; tz = g_time_zone_new_local(); - gchar *log_file = _get_log_file(); + gchar *log_file = _get_main_log_file(); logp = fopen(log_file, "a"); + mainlogfile = g_string_new(log_file); free(log_file); } +void +log_reinit(void) +{ + log_close(); + log_init(level_filter); +} + +char * +get_log_file_location(void) +{ + return mainlogfile->str; +} + log_level_t log_get_filter(void) { @@ -131,6 +147,7 @@ log_get_filter(void) void log_close(void) { + g_string_free(mainlogfile, TRUE); g_time_zone_unref(tz); if (logp != NULL) { fclose(logp); @@ -154,9 +171,11 @@ log_msg(log_level_t level, const char * const area, const char * const msg) fflush(logp); g_free(date_fmt); - result = ftell(logp); - if (result != -1 && result >= prefs_get_max_log_size()) { - _rotate_log_file(); + if (prefs_get_boolean(PREF_LOG_ROTATE)) { + result = ftell(logp); + if (result != -1 && result >= prefs_get_max_log_size()) { + _rotate_log_file(); + } } } } @@ -181,7 +200,7 @@ log_level_from_string(char *log_level) static void _rotate_log_file(void) { - gchar *log_file = _get_log_file(); + gchar *log_file = _get_main_log_file(); size_t len = strlen(log_file); char *log_file_new = malloc(len + 3); @@ -516,11 +535,15 @@ _get_chatlog_dir(void) } static gchar * -_get_log_file(void) +_get_main_log_file(void) { gchar *xdg_data = xdg_get_data_home(); GString *logfile = g_string_new(xdg_data); - g_string_append(logfile, "/profanity/logs/profanity.log"); + g_string_append(logfile, "/profanity/logs/profanity"); + if (!prefs_get_boolean(PREF_LOG_SHARED)) { + g_string_append_printf(logfile, "%d", getpid()); + } + g_string_append(logfile, ".log"); gchar *result = strdup(logfile->str); free(xdg_data); g_string_free(logfile, TRUE); diff --git a/src/log.h b/src/log.h index fcb1a9f2..d9cd92e1 100644 --- a/src/log.h +++ b/src/log.h @@ -41,6 +41,8 @@ typedef enum { void log_init(log_level_t filter); log_level_t log_get_filter(void); void log_close(void); +void log_reinit(void); +char * get_log_file_location(void); void log_debug(const char * const msg, ...); void log_info(const char * const msg, ...); void log_warning(const char * const msg, ...); diff --git a/src/profanity.c b/src/profanity.c index 78f4c241..59241403 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -260,6 +260,7 @@ _init(const int disable_tls, char *log_level) signal(SIGPIPE, SIG_IGN); _create_directories(); log_level_t prof_log_level = log_level_from_string(log_level); + prefs_load(); log_init(prof_log_level); if (strcmp(PROF_PACKAGE_STATUS, "development") == 0) { #ifdef PROF_HAVE_GIT_VERSION @@ -272,7 +273,6 @@ _init(const int disable_tls, char *log_level) } chat_log_init(); groupchat_log_init(); - prefs_load(); accounts_load(); gchar *theme = prefs_get_string(PREF_THEME); theme_init(theme); diff --git a/src/ui/console.c b/src/ui/console.c index bc413d21..39dbf1da 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -31,6 +31,7 @@ #include "command/command.h" #include "common.h" +#include "log.h" #include "roster_list.h" #include "config/preferences.h" #include "config/theme.h" @@ -1222,7 +1223,18 @@ _cons_show_chat_prefs(void) static void _cons_log_setting(void) { + cons_show("Log file location : %s", get_log_file_location()); cons_show("Max log size (/log maxsize) : %d bytes", prefs_get_max_log_size()); + + if (prefs_get_boolean(PREF_LOG_ROTATE)) + cons_show("Log rotation (/log rotate) : ON"); + else + cons_show("Log rotation (/log rotate) : OFF"); + + if (prefs_get_boolean(PREF_LOG_SHARED)) + cons_show("Shared log (/log shared) : ON"); + else + cons_show("Shared log (/log shared) : OFF"); } static void diff --git a/tests/log/mock_log.c b/tests/log/mock_log.c index a5e6a950..1d02c9d1 100644 --- a/tests/log/mock_log.c +++ b/tests/log/mock_log.c @@ -31,6 +31,7 @@ log_level_t log_get_filter(void) { return (log_level_t)mock(); } +void log_reinit(void) {} void log_close(void) {} void log_debug(const char * const msg, ...) {} void log_info(const char * const msg, ...) {}