void connman_debug(const char *format, ...)
__attribute__((format(printf, 1, 2)));
+struct connman_debug_desc {
+ const char *name;
+ const char *file;
+#define CONNMAN_DEBUG_FLAG_DEFAULT (0)
+#define CONNMAN_DEBUG_FLAG_PRINT (1 << 0)
+#define CONNMAN_DEBUG_FLAG_ALIAS (1 << 1)
+ unsigned int flags;
+} __attribute__((aligned(8)));
+
+#define CONNMAN_DEBUG_DEFINE(name) \
+ static struct connman_debug_desc __debug_alias_ ## name \
+ __attribute__((used, section("__debug"), aligned(8))) = { \
+ #name, __FILE__, CONNMAN_DEBUG_FLAG_ALIAS \
+ };
+
/**
* DBG:
* @fmt: format string
* Simple macro around connman_debug() which also include the function
* name it is called in.
*/
-#define DBG(fmt, arg...) connman_debug("%s:%s() " fmt, __FILE__, __FUNCTION__ , ## arg)
+#define DBG(fmt, arg...) do { \
+ static struct connman_debug_desc desc \
+ __attribute__((used, section("__debug"), aligned(8))) = { \
+ .file = __FILE__, .flags = CONNMAN_DEBUG_FLAG_DEFAULT, \
+ }; \
+ if (desc.flags & CONNMAN_DEBUG_FLAG_PRINT) \
+ connman_debug("%s:%s() " fmt, \
+ __FILE__, __FUNCTION__ , ## arg); \
+} while (0)
#ifdef __cplusplus
}
#include <connman/log.h>
-int __connman_log_init(gboolean detach, gboolean debug);
+int __connman_log_init(const char *debug, connman_bool_t detach);
void __connman_log_cleanup(void);
-void __connman_toggle_debug(void);
-gboolean __connman_debug_enabled(void);
+void __connman_debug_list_available(DBusMessageIter *iter);
+void __connman_debug_list_enabled(DBusMessageIter *iter);
#include <connman/option.h>
#include "connman.h"
-static volatile gboolean debug_enabled = FALSE;
-
/**
* connman_info:
* @format: format string
* @varargs: list of arguments
*
* Output debug message
- *
- * The actual output of the debug message is controlled via a command line
- * switch. If not enabled, these messages will be ignored.
*/
void connman_debug(const char *format, ...)
{
va_list ap;
- if (debug_enabled == FALSE)
- return;
-
va_start(ap, format);
vsyslog(LOG_DEBUG, format, ap);
va_end(ap);
}
-void __connman_toggle_debug(void)
+extern struct connman_debug_desc __start___debug[];
+extern struct connman_debug_desc __stop___debug[];
+
+void __connman_debug_list_available(DBusMessageIter *iter)
+{
+ struct connman_debug_desc *desc;
+
+ for (desc = __start___debug; desc < __stop___debug; desc++) {
+ if ((desc->flags & CONNMAN_DEBUG_FLAG_ALIAS) &&
+ desc->name != NULL)
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_STRING, &desc->name);
+ }
+}
+
+static gchar **enabled = NULL;
+
+void __connman_debug_list_enabled(DBusMessageIter *iter)
+{
+ int i;
+
+ if (enabled == NULL)
+ return;
+
+ for (i = 0; enabled[i] != NULL; i++)
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_STRING, &enabled[i]);
+}
+
+static connman_bool_t is_enabled(struct connman_debug_desc *desc)
{
- if (debug_enabled == TRUE) {
- connman_info("Disabling debug output");
- debug_enabled = FALSE;
- } else {
- connman_info("Enabling debug output");
- debug_enabled = TRUE;
+ int i;
+
+ if (enabled == NULL)
+ return FALSE;
+
+ for (i = 0; enabled[i] != NULL; i++) {
+ if (desc->name != NULL && g_pattern_match_simple(enabled[i],
+ desc->name) == TRUE)
+ return TRUE;
+ if (desc->file != NULL && g_pattern_match_simple(enabled[i],
+ desc->file) == TRUE)
+ return TRUE;
}
+
+ return FALSE;
}
-int __connman_log_init(gboolean detach, gboolean debug)
+int __connman_log_init(const char *debug, connman_bool_t detach)
{
int option = LOG_NDELAY | LOG_PID;
+ struct connman_debug_desc *desc;
+ const char *name = NULL, *file = NULL;
+
+ if (debug != NULL)
+ enabled = g_strsplit_set(debug, ":, ", 0);
+
+ for (desc = __start___debug; desc < __stop___debug; desc++) {
+ if (desc->flags & CONNMAN_DEBUG_FLAG_ALIAS) {
+ file = desc->file;
+ name = desc->name;
+ continue;
+ }
+
+ if (file != NULL || name != NULL) {
+ if (g_strcmp0(desc->file, file) == 0) {
+ if (desc->name == NULL)
+ desc->name = name;
+ } else
+ file = NULL;
+ }
+
+ if (is_enabled(desc) == TRUE)
+ desc->flags |= CONNMAN_DEBUG_FLAG_PRINT;
+ }
if (detach == FALSE)
option |= LOG_PERROR;
syslog(LOG_INFO, "Connection Manager version %s", VERSION);
- if (debug == TRUE)
- __connman_toggle_debug();
-
return 0;
}
syslog(LOG_INFO, "Exit");
closelog();
-}
-gboolean __connman_debug_enabled(void)
-{
- return debug_enabled;
+ g_strfreev(enabled);
}
g_main_loop_quit(main_loop);
}
-static void sig_debug(int sig)
-{
- __connman_toggle_debug();
-}
-
static void disconnect_callback(DBusConnection *conn, void *user_data)
{
connman_error("D-Bus disconnect");
g_main_loop_quit(main_loop);
}
+static gchar *option_debug = NULL;
static gchar *option_device = NULL;
static gchar *option_plugin = NULL;
static gchar *option_nodevice = NULL;
static gchar *option_wifi = NULL;
static gboolean option_detach = TRUE;
static gboolean option_compat = FALSE;
-static gboolean option_debug = FALSE;
static gboolean option_selftest = FALSE;
static gboolean option_version = FALSE;
static GOptionEntry options[] = {
+ { "debug", 'd', 0, G_OPTION_ARG_STRING, &option_debug,
+ "Specify debug options to enable", "DEBUG" },
{ "device", 'i', 0, G_OPTION_ARG_STRING, &option_device,
"Specify networking device or interface", "DEV" },
{ "nodevice", 'I', 0, G_OPTION_ARG_STRING, &option_nodevice,
"Don't fork daemon to background" },
{ "compat", 'c', 0, G_OPTION_ARG_NONE, &option_compat,
"Enable Network Manager compatibility" },
- { "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug,
- "Enable debug information output" },
{ "selftest", 't', 0, G_OPTION_ARG_NONE, &option_selftest,
"Run self testing routines" },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
}
}
- __connman_log_init(option_detach, option_debug);
+ __connman_log_init(option_debug, option_detach);
if (option_selftest == TRUE) {
if (__connman_selftest() < 0) {
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
- sa.sa_handler = sig_debug;
- sigaction(SIGUSR2, &sa, NULL);
-
g_main_loop_run(main_loop);
__connman_element_stop();
dbus_message_iter_close_container(dict, &entry);
}
+static void append_available_debugs(DBusMessageIter *dict)
+{
+ DBusMessageIter entry, value, iter;
+ const char *key = "AvailableDebugs";
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+ &value);
+
+ dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &iter);
+ __connman_debug_list_available(&iter);
+ dbus_message_iter_close_container(&value, &iter);
+
+ dbus_message_iter_close_container(&entry, &value);
+
+ dbus_message_iter_close_container(dict, &entry);
+}
+
+static void append_enabled_debugs(DBusMessageIter *dict)
+{
+ DBusMessageIter entry, value, iter;
+ const char *key = "EnabledDebugs";
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+ &value);
+
+ dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &iter);
+ __connman_debug_list_enabled(&iter);
+ dbus_message_iter_close_container(&value, &iter);
+
+ dbus_message_iter_close_container(&entry, &value);
+
+ dbus_message_iter_close_container(dict, &entry);
+}
+
static DBusMessage *get_properties(DBusConnection *conn,
DBusMessage *msg, void *data)
{
connman_dbus_dict_append_variant(&dict, "DefaultTechnology",
DBUS_TYPE_STRING, &str);
+ append_available_debugs(&dict);
+ append_enabled_debugs(&dict);
+
dbus_message_iter_close_container(&array, &dict);
return reply;
if key in ["Profiles", "Devices", "Connections", "Services"]:
print_properties(key, properties[key])
elif key in ["AvailableTechnologies", "EnabledTechnologies",
- "ConnectedTechnologies"]:
+ "ConnectedTechnologies",
+ "AvailableDebugs", "EnabledDebugs"]:
print "%s" % (key)
list = ""
for val in properties[key]: