diff --git a/lib/mu-log.c b/lib/mu-log.c index e2cc9c79..62de2b6e 100644 --- a/lib/mu-log.c +++ b/lib/mu-log.c @@ -1,7 +1,7 @@ /* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ /* -** Copyright (C) 2008-2011 Dirk-Jan C. Binnema +** Copyright (C) 2008-2012 Dirk-Jan C. Binnema ** ** 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 @@ -43,9 +43,10 @@ struct _MuLog { int _fd; /* log file descriptor */ - gboolean _own; /* close _fd with log_destroy? */ - gboolean _debug; /* add debug-level stuff? */ - gboolean _quiet; /* don't write non-error to stdout/stderr */ + MuLogOptions _opts; + + gboolean _color_stdout; /* whether to use color */ + gboolean _color_stderr; GLogFunc _old_log_func; }; @@ -80,9 +81,10 @@ mu_log_init_silence (void) { g_return_val_if_fail (!MU_LOG, FALSE); - MU_LOG = g_new(MuLog, 1); - MU_LOG->_fd = -1; - MU_LOG->_own = FALSE; /* nobody owns silence */ + MU_LOG = g_new0 (MuLog, 1); + MU_LOG->_fd = -1; + + mu_log_options_set (MU_LOG_OPTIONS_NONE); MU_LOG->_old_log_func = g_log_set_default_handler ((GLogFunc)silence, NULL); @@ -94,32 +96,39 @@ static void log_handler (const gchar* log_domain, GLogLevelFlags log_level, const gchar* msg) { - if ((log_level & G_LOG_LEVEL_DEBUG) && !(MU_LOG->_debug)) + if ((log_level & G_LOG_LEVEL_DEBUG) && + !(MU_LOG->_opts & MU_LOG_OPTIONS_DEBUG)) return; log_write (log_domain ? log_domain : "mu", log_level, msg); } -gboolean -mu_log_init_with_fd (int fd, gboolean doclose, - gboolean quiet, gboolean debug) +void +mu_log_options_set (MuLogOptions opts) { - g_return_val_if_fail (!MU_LOG, FALSE); + g_return_if_fail (MU_LOG); - MU_LOG = g_new(MuLog, 1); + MU_LOG->_opts = opts; - MU_LOG->_fd = fd; - MU_LOG->_quiet = quiet; - MU_LOG->_debug = debug; - MU_LOG->_own = doclose; /* if we now own the fd, close it - * in _destroy */ - MU_LOG->_old_log_func = - g_log_set_default_handler ((GLogFunc)log_handler, NULL); + /* when color is, only enable it when output is to a tty */ + if (MU_LOG->_opts & MU_LOG_OPTIONS_COLOR) { + MU_LOG->_color_stdout = isatty(fileno(stdout)); + MU_LOG->_color_stderr = isatty(fileno(stderr)); - return TRUE; + } } + +MuLogOptions +mu_log_options_get (void) +{ + g_return_val_if_fail (MU_LOG, MU_LOG_OPTIONS_NONE); + + return MU_LOG->_opts; +} + + static gboolean move_log_file (const char *logfile) { @@ -165,8 +174,7 @@ log_file_backup_maybe (const char *logfile) gboolean -mu_log_init (const char* logfile, gboolean backup, - gboolean quiet, gboolean debug) +mu_log_init (const char* logfile, MuLogOptions opts) { int fd; @@ -174,21 +182,27 @@ mu_log_init (const char* logfile, gboolean backup, g_return_val_if_fail (!MU_LOG, FALSE); g_return_val_if_fail (logfile, FALSE); - if (backup && !log_file_backup_maybe(logfile)) { - g_warning ("failed to backup log file"); - return FALSE; - } + if (opts & MU_LOG_OPTIONS_BACKUP) + if (!log_file_backup_maybe(logfile)) { + g_warning ("failed to backup log file"); + return FALSE; + } fd = open (logfile, O_WRONLY|O_CREAT|O_APPEND, 00600); - if (fd < 0) + if (fd < 0) { g_warning ("%s: open() of '%s' failed: %s", __FUNCTION__, logfile, strerror(errno)); - - if (fd < 0 || !mu_log_init_with_fd (fd, FALSE, quiet, debug)) { - try_close (fd); return FALSE; } + MU_LOG = g_new0 (MuLog, 1); + MU_LOG->_fd = fd; + + mu_log_options_set (opts); + + MU_LOG->_old_log_func = + g_log_set_default_handler ((GLogFunc)log_handler, NULL); + MU_WRITE_LOG ("logging started"); return TRUE; @@ -202,9 +216,7 @@ mu_log_uninit (void) MU_WRITE_LOG ("logging stopped"); - if (MU_LOG->_own) - try_close (MU_LOG->_fd); - + try_close (MU_LOG->_fd); g_free (MU_LOG); MU_LOG = NULL; @@ -225,14 +237,23 @@ pfx (GLogLevelFlags level) } } + + +#define color_stdout_maybe(C) \ + do{if (MU_LOG->_color_stdout) fputs ((C),stdout);} while (0) +#define color_stderr_maybe(C) \ + do{if (MU_LOG->_color_stderr) fputs ((C),stderr);} while (0) + + static void log_write (const char* domain, GLogLevelFlags level, const gchar *msg) { time_t now; ssize_t len; + const char *mu; - /* log lines will be truncated at 768 chars */ + /* log lines will be truncated at 768-1 chars */ char buf [768], timebuf [22]; g_return_if_fail (MU_LOG); @@ -250,18 +271,26 @@ log_write (const char* domain, GLogLevelFlags level, fprintf (stderr, "%s: failed to write to log: %s\n", __FUNCTION__, strerror(errno)); - if (!(MU_LOG->_quiet) && (level & G_LOG_LEVEL_MESSAGE)) { - fputs ("mu: ", stdout); + mu = MU_LOG->_opts & MU_LOG_OPTIONS_NEWLINE ? + "\nmu: " : "mu: "; + + if (!(MU_LOG->_opts & MU_LOG_OPTIONS_QUIET) && + (level & G_LOG_LEVEL_MESSAGE)) { + color_stdout_maybe (MU_COLOR_GREEN); + fputs (mu, stdout); fputs (msg, stdout); fputs ("\n", stdout); + color_stdout_maybe (MU_COLOR_DEFAULT); } /* for errors, log them to stderr as well */ if (level & G_LOG_LEVEL_ERROR || level & G_LOG_LEVEL_CRITICAL || level & G_LOG_LEVEL_WARNING) { - fputs ("mu: ", stderr); + color_stderr_maybe (MU_COLOR_RED); + fputs (mu, stderr); fputs (msg, stderr); fputs ("\n", stderr); + color_stderr_maybe (MU_COLOR_DEFAULT); } } diff --git a/lib/mu-log.h b/lib/mu-log.h index 323a41f4..3dcd30e3 100644 --- a/lib/mu-log.h +++ b/lib/mu-log.h @@ -1,22 +1,22 @@ -/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ - -/* -** Copyright (C) 2008-2011 Dirk-Jan C. Binnema +/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: + 8 -*-*/ +/* +** Copyright (C) 2008-2012 Dirk-Jan C. Binnema ** ** 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 3 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** */ #ifndef __MU_LOG_H__ @@ -28,40 +28,49 @@ G_BEGIN_DECLS -/** - * write logging information to a log file - * - * @param full path to the log file (does not have to exist yet, but - * it's directory must) - * @param backup if TRUE and size of log file > MU_MAX_LOG_FILE_SIZE, move - * the log file to .old and start a new one. The .old file will overwrite - * existing files of that name - * @param quiet don't log non-errors to stdout/stderr - * @param debug include debug-level information. - * - * @return TRUE if initialization succeeds, FALSE otherwise - */ -gboolean mu_log_init (const char *logfile, gboolean backup, - gboolean quiet, gboolean debug) - G_GNUC_WARN_UNUSED_RESULT; +enum _MuLogOptions { + MU_LOG_OPTIONS_NONE = 0, + + /* when size of log file > MU_MAX_LOG_FILE_SIZE, move the log + * file to .old and start a new one. The .old file will + * overwrite existing files of that name */ + MU_LOG_OPTIONS_BACKUP = 1 << 1, + + /* quiet: don't log non-errors to stdout/stderr */ + MU_LOG_OPTIONS_QUIET = 1 << 2, + + /* should lines be preceded by \n? useful when errors come + * during indexing */ + MU_LOG_OPTIONS_NEWLINE = 1 << 3, + + /* color in output (iff output is to a tty) */ + MU_LOG_OPTIONS_COLOR = 1 << 4, + + /* log everything to stderr */ + MU_LOG_OPTIONS_STDERR = 1 << 5, + + /* debug: debug include debug-level information */ + MU_LOG_OPTIONS_DEBUG = 1 << 6 +}; +typedef enum _MuLogOptions MuLogOptions; + /** - * write logging information to a file descriptor - * - * @param fd an open file descriptor - * @param doclose if true, mu-log will close it upon mu_log_uninit - * @param quiet don't log non-errors to stdout/stderr - * @param debug include debug-level info - * + * write logging information to a log file + * + * @param full path to the log file (does not have to exist yet, but + * it's directory must) + * @param opts logging options + * * @return TRUE if initialization succeeds, FALSE otherwise */ -gboolean mu_log_init_with_fd (int fd, gboolean doclose, gboolean quiet, - gboolean debug) G_GNUC_WARN_UNUSED_RESULT; +gboolean mu_log_init (const char *logfile, MuLogOptions opts) + G_GNUC_WARN_UNUSED_RESULT; /** * be silent except for runtime errors, which will be written to * stderr. - * + * * @return TRUE if initialization succeeds, FALSE otherwise */ gboolean mu_log_init_silence (void) G_GNUC_WARN_UNUSED_RESULT; @@ -71,6 +80,19 @@ gboolean mu_log_init_silence (void) G_GNUC_WARN_UNUSED_RESULT; */ void mu_log_uninit (void); +/** + * set logging options, a logical-OR'd value of MuLogOptions + * + * @param opts the options (logically OR'd) + */ +void mu_log_options_set (MuLogOptions opts); + +/** + * get logging options, a logical-OR'd value of MuLogOptions + * + * @param opts the options (logically OR'd) + */ +MuLogOptions mu_log_options_get (void); G_END_DECLS