diff options
-rw-r--r-- | po/.gitignore | 1 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | po/POTFILES.skip | 2 | ||||
-rw-r--r-- | src/dkp-main.c | 10 | ||||
-rw-r--r-- | src/dkp-self-test.c | 2 | ||||
-rw-r--r-- | src/egg-debug.c | 332 | ||||
-rw-r--r-- | src/egg-debug.h | 26 | ||||
-rw-r--r-- | tools/dkp-tool.c | 4 |
8 files changed, 273 insertions, 105 deletions
diff --git a/po/.gitignore b/po/.gitignore index 005ab20..73b9707 100644 --- a/po/.gitignore +++ b/po/.gitignore @@ -2,4 +2,5 @@ Makefile.in.in POTFILES stamp-it .intltool-merge-cache +*.pot diff --git a/po/POTFILES.in b/po/POTFILES.in index 6add251..72595a1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -5,4 +5,5 @@ policy/org.freedesktop.devicekit.power.policy.in policy/org.freedesktop.devicekit.power.qos.policy.in src/dkp-main.c tools/dkp-tool.c +src/egg-debug.c diff --git a/po/POTFILES.skip b/po/POTFILES.skip new file mode 100644 index 0000000..c369e8d --- /dev/null +++ b/po/POTFILES.skip @@ -0,0 +1,2 @@ +tools/egg-debug.c + diff --git a/src/dkp-main.c b/src/dkp-main.c index ed9f81c..57165c0 100644 --- a/src/dkp-main.c +++ b/src/dkp-main.c @@ -117,23 +117,15 @@ main (gint argc, gchar **argv) GOptionContext *context; DBusGProxy *bus_proxy; DBusGConnection *bus; - gboolean verbose = FALSE; gboolean ret; gint retval = 1; - const GOptionEntry entries[] = { - { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, - _("Show extra debugging information"), NULL }, - { NULL } - }; - g_type_init (); context = g_option_context_new ("DeviceKit Power Daemon"); - g_option_context_add_main_entries (context, entries, NULL); + g_option_context_add_group (context, egg_debug_get_option_group ()); g_option_context_parse (context, &argc, &argv, NULL); g_option_context_free (context); - egg_debug_init (verbose); /* get bus connection */ bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); diff --git a/src/dkp-self-test.c b/src/dkp-self-test.c index e274be9..bcbb7b2 100644 --- a/src/dkp-self-test.c +++ b/src/dkp-self-test.c @@ -42,7 +42,7 @@ main (int argc, char **argv) g_type_init (); test = egg_test_init (); - egg_debug_init (TRUE); + egg_debug_init (&argc, &argv); /* tests go here */ dkp_backend_test (test); diff --git a/src/egg-debug.c b/src/egg-debug.c index f18a5d1..77bfa20 100644 --- a/src/egg-debug.c +++ b/src/egg-debug.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2007-2008 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2007-2009 Richard Hughes <richard@hughsie.com> * * Licensed under the GNU General Public License Version 2 * @@ -26,6 +26,8 @@ * This file contains functions that can be used for debugging. */ +#include "config.h" + #include <glib.h> #include <glib/gi18n.h> #include <glib/gprintf.h> @@ -39,7 +41,10 @@ #include <sys/stat.h> #include <fcntl.h> #include <time.h> + +#ifdef HAVE_EXECINFO_H #include <execinfo.h> +#endif #include "egg-debug.h" @@ -53,18 +58,79 @@ #define CONSOLE_CYAN 36 #define CONSOLE_WHITE 37 -static gint fd = -1; +static gint _fd = -1; +static gboolean _verbose = FALSE; +static gboolean _console = FALSE; +static gchar *_log_filename = NULL; +static gboolean _initialized = FALSE; +static GPtrArray *_modules_array = NULL; +static GPtrArray *_functions_array = NULL; +static gchar **_modules = NULL; +static gchar **_functions = NULL; + +/** + * egg_debug_filter_module: + **/ +static gboolean +egg_debug_filter_module (const gchar *filename) +{ + gchar *module; + const gchar *module_tmp; + guint i; + gboolean ret = FALSE; + + /* nothing filtering */ + if (_modules_array == NULL) + return FALSE; + + /* are we in the filter list */ + module = g_strdup (filename); + g_strdelimit (module, ".", '\0'); + for (i=0; i<_modules_array->len; i++) { + module_tmp = g_ptr_array_index (_modules_array, i); + if (g_strcmp0 (module_tmp, module) == 0) { + ret = TRUE; + break; + } + } + return ret; +} /** - * pk_set_console_mode: + * egg_debug_filter_function: + **/ +static gboolean +egg_debug_filter_function (const gchar *function) +{ + guint i; + const gchar *function_tmp; + gboolean ret = FALSE; + + /* nothing filtering */ + if (_functions_array == NULL) + return FALSE; + + /* are we in the filter list */ + for (i=0; i<_functions_array->len; i++) { + function_tmp = g_ptr_array_index (_functions_array, i); + if (g_str_has_prefix (function, function_tmp)) { + ret = TRUE; + break; + } + } + return ret; +} + +/** + * egg_debug_set_console_mode: **/ static void -pk_set_console_mode (guint console_code) +egg_debug_set_console_mode (guint console_code) { gchar command[13]; /* don't put extra commands into logs */ - if (!egg_debug_is_console ()) + if (!_console) return; /* Command is the control command to the terminal */ @@ -78,6 +144,7 @@ pk_set_console_mode (guint console_code) void egg_debug_backtrace (void) { +#ifdef HAVE_EXECINFO_H void *call_stack[512]; int call_stack_size; char **symbols; @@ -86,75 +153,76 @@ egg_debug_backtrace (void) call_stack_size = backtrace (call_stack, G_N_ELEMENTS (call_stack)); symbols = backtrace_symbols (call_stack, call_stack_size); if (symbols != NULL) { - pk_set_console_mode (CONSOLE_RED); + egg_debug_set_console_mode (CONSOLE_RED); g_print ("Traceback:\n"); while (i < call_stack_size) { g_print ("\t%s\n", symbols[i]); i++; } - pk_set_console_mode (CONSOLE_RESET); + egg_debug_set_console_mode (CONSOLE_RESET); free (symbols); } +#endif } /** - * pk_log_line: + * egg_debug_log_line: **/ static void -pk_log_line (const gchar *buffer) +egg_debug_log_line (const gchar *buffer) { ssize_t count; + /* open a file */ - if (fd == -1) { + if (_fd == -1) { /* ITS4: ignore, /var/log/foo is owned by root, and this is just debug text */ - fd = open (EGG_LOG_FILE, O_WRONLY|O_APPEND|O_CREAT, 0777); - if (fd == -1) - g_error ("could not open log: '%s'", EGG_LOG_FILE); + _fd = open (_log_filename, O_WRONLY|O_APPEND|O_CREAT, 0777); + if (_fd == -1) + g_error ("could not open log: '%s'", _log_filename); } /* ITS4: ignore, debug text always NULL terminated */ - count = write (fd, buffer, strlen (buffer)); + count = write (_fd, buffer, strlen (buffer)); if (count == -1) g_warning ("could not write %s", buffer); + /* newline */ - count = write (fd, "\n", 1); + count = write (_fd, "\n", 1); if (count == -1) g_warning ("could not write newline"); } /** - * pk_print_line: + * egg_debug_print_line: **/ static void -pk_print_line (const gchar *func, const gchar *file, const int line, const gchar *buffer, guint color) +egg_debug_print_line (const gchar *func, const gchar *file, const int line, const gchar *buffer, guint color) { gchar *str_time; gchar *header; time_t the_time; - GThread *thread; time (&the_time); str_time = g_new0 (gchar, 255); strftime (str_time, 254, "%H:%M:%S", localtime (&the_time)); - thread = g_thread_self (); /* generate header text */ - header = g_strdup_printf ("TI:%s\tTH:%p\tFI:%s\tFN:%s,%d", str_time, thread, file, func, line); + header = g_strdup_printf ("TI:%s\tFI:%s\tFN:%s,%d", str_time, file, func, line); g_free (str_time); /* always in light green */ - pk_set_console_mode (CONSOLE_GREEN); + egg_debug_set_console_mode (CONSOLE_GREEN); printf ("%s\n", header); /* different colors according to the severity */ - pk_set_console_mode (color); + egg_debug_set_console_mode (color); printf (" - %s\n", buffer); - pk_set_console_mode (CONSOLE_RESET); + egg_debug_set_console_mode (CONSOLE_RESET); /* log to a file */ - if (egg_debug_is_logging ()) { - pk_log_line (header); - pk_log_line (buffer); + if (_log_filename != NULL) { + egg_debug_log_line (header); + egg_debug_log_line (buffer); } /* flush this output, as we need to debug */ @@ -172,16 +240,16 @@ egg_debug_real (const gchar *func, const gchar *file, const int line, const gcha va_list args; gchar *buffer = NULL; - if (!egg_debug_enabled ()) + if (!_verbose && !egg_debug_filter_module (file) && !egg_debug_filter_function (func)) return; va_start (args, format); g_vasprintf (&buffer, format, args); va_end (args); - pk_print_line (func, file, line, buffer, CONSOLE_BLUE); + egg_debug_print_line (func, file, line, buffer, CONSOLE_BLUE); - g_free(buffer); + g_free (buffer); } /** @@ -193,7 +261,7 @@ egg_warning_real (const gchar *func, const gchar *file, const int line, const gc va_list args; gchar *buffer = NULL; - if (!egg_debug_enabled ()) + if (!_verbose && !egg_debug_filter_module (file) && !egg_debug_filter_function (func)) return; va_start (args, format); @@ -201,11 +269,11 @@ egg_warning_real (const gchar *func, const gchar *file, const int line, const gc va_end (args); /* do extra stuff for a warning */ - if (!egg_debug_is_console ()) + if (!_console) printf ("*** WARNING ***\n"); - pk_print_line (func, file, line, buffer, CONSOLE_RED); + egg_debug_print_line (func, file, line, buffer, CONSOLE_RED); - g_free(buffer); + g_free (buffer); } /** @@ -222,10 +290,10 @@ egg_error_real (const gchar *func, const gchar *file, const int line, const gcha va_end (args); /* do extra stuff for a warning */ - if (!egg_debug_is_console ()) + if (!_console) printf ("*** ERROR ***\n"); - pk_print_line (func, file, line, buffer, CONSOLE_RED); - g_free(buffer); + egg_debug_print_line (func, file, line, buffer, CONSOLE_RED); + g_free (buffer); /* we want to fix this! */ egg_debug_backtrace (); @@ -234,75 +302,181 @@ egg_error_real (const gchar *func, const gchar *file, const int line, const gcha } /** - * egg_debug_enabled: + * egg_debug_is_verbose: * * Returns: TRUE if we have debugging enabled **/ gboolean -egg_debug_enabled (void) +egg_debug_is_verbose (void) { - const gchar *env; - env = g_getenv (EGG_VERBOSE); - return (g_strcmp0 (env, "1") == 0); + return _verbose; } /** - * egg_debug_is_logging: - * - * Returns: TRUE if we have logging enabled + * egg_debug_set_log_filename: **/ -gboolean -egg_debug_is_logging (void) +void +egg_debug_set_log_filename (const gchar *filename) { - const gchar *env; - env = g_getenv (EGG_LOGGING); - return (g_strcmp0 (env, "1") == 0); + g_free (_log_filename); + _log_filename = g_strdup (filename); } /** - * egg_debug_is_console: - * - * Returns: TRUE if we have debugging enabled + * egg_debug_strv_split_to_ptr_array: **/ -gboolean -egg_debug_is_console (void) +static GPtrArray * +egg_debug_strv_split_to_ptr_array (gchar **modules) +{ + GPtrArray *array = NULL; + guint i, j; + gchar **split; + + /* nothing */ + if (modules == NULL) + goto out; + + /* create array of strings */ + array = g_ptr_array_new_with_free_func (g_free); + + /* parse each --debug-foo option */ + for (i=0; modules[i] != NULL; i++) { + /* use a comma to delimit multiple entries */ + split = g_strsplit (modules[i], ",", -1); + for (j=0; split[j] != NULL; j++) + g_ptr_array_add (array, g_strdup (split[j])); + g_strfreev (split); + } +out: + return array; +} + +/** + * egg_debug_pre_parse_hook: + */ +static gboolean +egg_debug_pre_parse_hook (GOptionContext *context, GOptionGroup *group, gpointer data, GError **error) { - const gchar *env; - env = g_getenv (EGG_CONSOLE); - return (g_strcmp0 (env, "1") == 0); + const gchar *env_string; + const GOptionEntry main_entries[] = { + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &_verbose, + /* TRANSLATORS: turn on all debugging */ + N_("Show debugging information for all files"), NULL }, + { NULL} + }; + + /* global variable */ + env_string = g_getenv ("VERBOSE"); + if (env_string != NULL) + _verbose = TRUE; + + /* add main entry */ + g_option_context_add_main_entries (context, main_entries, NULL); + + return TRUE; } /** - * egg_debug_set_logging: + * egg_debug_free: **/ -void -egg_debug_set_logging (gboolean enabled) +static void +egg_debug_free (void) +{ + if (!_initialized) + return; + + /* close file */ + if (_fd != -1) + close (_fd); + + /* free memory */ + g_free (_log_filename); + if (_modules_array != NULL) + g_ptr_array_unref (_modules_array); + if (_functions_array != NULL) + g_ptr_array_unref (_functions_array); + g_strfreev (_modules); + g_strfreev (_functions); + + /* can not re-init */ + _initialized = FALSE; +} + +/** + * egg_debug_post_parse_hook: + */ +static gboolean +egg_debug_post_parse_hook (GOptionContext *context, GOptionGroup *group, gpointer data, GError **error) { - if (enabled) - g_setenv (EGG_LOGGING, "1", TRUE); - else - g_setenv (EGG_LOGGING, "0", TRUE); + _initialized = TRUE; + _modules_array = egg_debug_strv_split_to_ptr_array (_modules); + _functions_array = egg_debug_strv_split_to_ptr_array (_functions); + _console = (isatty (fileno (stdout)) == 1); + egg_debug ("Verbose debugging %i (on console %i)", _verbose, _console); + + /* run this function on cleanup */ + atexit (egg_debug_free); - if (egg_debug_is_logging ()) - egg_debug ("logging to %s", EGG_LOG_FILE); + return TRUE; +} + +/** + * egg_debug_get_option_group: + * + * Returns a #GOptionGroup for the commandline arguments recognized + * by debugging. You should add this group to your #GOptionContext + * with g_option_context_add_group(), if you are using + * g_option_context_parse() to parse your commandline arguments. + * + * Returns: a #GOptionGroup for the commandline arguments + */ +GOptionGroup * +egg_debug_get_option_group (void) +{ + GOptionGroup *group; + const GOptionEntry debug_entries[] = { + { "debug-modules", '\0', 0, G_OPTION_ARG_STRING_ARRAY, &_modules, + /* TRANSLATORS: a list of modules to debug */ + N_("Debug these specific modules"), NULL }, + { "debug-functions", '\0', 0, G_OPTION_ARG_STRING_ARRAY, &_functions, + /* TRANSLATORS: a list of functions to debug */ + N_("Debug these specific functions"), NULL }, + { "debug-log-filename", '\0', 0, G_OPTION_ARG_STRING, &_log_filename, + /* TRANSLATORS: save to a log */ + N_("Log debugging data to a file"), NULL }, + { NULL} + }; + + group = g_option_group_new ("debug", _("Debugging Options"), _("Show debugging options"), NULL, NULL); + g_option_group_set_parse_hooks (group, egg_debug_pre_parse_hook, egg_debug_post_parse_hook); + g_option_group_add_entries (group, debug_entries); + return group; } /** * egg_debug_init: - * @debug: If we should print out verbose logging + * @argc: a pointer to the number of command line arguments. + * @argv: a pointer to the array of command line arguments. + * + * Parses command line arguments. + * + * Return value: %TRUE if initialization succeeded, otherwise %FALSE. **/ -void -egg_debug_init (gboolean debug) +gboolean +egg_debug_init (gint *argc, gchar ***argv) { - /* check if we are on console */ - if (isatty (fileno (stdout)) == 1) - g_setenv (EGG_CONSOLE, "1", FALSE); - else - g_setenv (EGG_CONSOLE, "0", FALSE); - if (debug) - g_setenv (EGG_VERBOSE, "1", FALSE); - else - g_setenv (EGG_VERBOSE, "0", FALSE); - egg_debug ("Verbose debugging %i (on console %i)%s", egg_debug_enabled (), egg_debug_is_console (), EGG_VERBOSE); + GOptionContext *context; + + /* already initialized */ + if (_initialized) + return TRUE; + + context = g_option_context_new (NULL); + g_option_context_set_ignore_unknown_options (context, TRUE); + g_option_context_add_group (context, egg_debug_get_option_group ()); + g_option_context_parse (context, argc, argv, NULL); + g_option_context_free (context); + + return TRUE; } diff --git a/src/egg-debug.h b/src/egg-debug.h index c935dcb..ac6728b 100644 --- a/src/egg-debug.h +++ b/src/egg-debug.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * - * Copyright (C) 2007-2008 Richard Hughes <richard@hughsie.com> + * Copyright (C) 2007-2009 Richard Hughes <richard@hughsie.com> * * Licensed under the GNU General Public License Version 2 * @@ -59,23 +59,23 @@ G_BEGIN_DECLS #define egg_error(...) #endif -void egg_debug_init (gboolean debug); -void egg_debug_set_logging (gboolean enabled); -gboolean egg_debug_enabled (void); -gboolean egg_debug_is_logging (void); -gboolean egg_debug_is_console (void); -void egg_debug_backtrace (void); -void egg_debug_real (const gchar *func, +gboolean egg_debug_init (gint *argc, + gchar ***argv); +GOptionGroup *egg_debug_get_option_group (void); +gboolean egg_debug_is_verbose (void); +void egg_debug_backtrace (void); +void egg_debug_set_log_filename (const gchar *filename); +void egg_debug_real (const gchar *func, const gchar *file, - int line, + gint line, const gchar *format, ...) __attribute__((format (printf,4,5))); -void egg_warning_real (const gchar *func, +void egg_warning_real (const gchar *func, const gchar *file, - int line, + gint line, const gchar *format, ...) __attribute__((format (printf,4,5))); -void egg_error_real (const gchar *func, +void egg_error_real (const gchar *func, const gchar *file, - int line, + gint line, const gchar *format, ...) G_GNUC_NORETURN __attribute__((format (printf,4,5))); G_END_DECLS diff --git a/tools/dkp-tool.c b/tools/dkp-tool.c index f853706..a2d700c 100644 --- a/tools/dkp-tool.c +++ b/tools/dkp-tool.c @@ -230,7 +230,6 @@ main (int argc, char **argv) gint retval = EXIT_FAILURE; guint i; GOptionContext *context; - gboolean verbose = FALSE; gboolean opt_dump = FALSE; gboolean opt_wakeups = FALSE; gboolean opt_enumerate = FALSE; @@ -244,7 +243,6 @@ main (int argc, char **argv) DkpDevice *device; const GOptionEntry entries[] = { - { "verbose", '\0', 0, G_OPTION_ARG_NONE, &verbose, _("Show extra debugging information"), NULL }, { "enumerate", 'e', 0, G_OPTION_ARG_NONE, &opt_enumerate, _("Enumerate objects paths for devices"), NULL }, { "dump", 'd', 0, G_OPTION_ARG_NONE, &opt_dump, _("Dump all parameters for all objects"), NULL }, { "wakeups", 'w', 0, G_OPTION_ARG_NONE, &opt_wakeups, _("Get the wakeup data"), NULL }, @@ -259,9 +257,9 @@ main (int argc, char **argv) context = g_option_context_new ("DeviceKit-power tool"); g_option_context_add_main_entries (context, entries, NULL); + g_option_context_add_group (context, egg_debug_get_option_group ()); g_option_context_parse (context, &argc, &argv, NULL); g_option_context_free (context); - egg_debug_init (verbose); loop = g_main_loop_new (NULL, FALSE); client = dkp_client_new (); |