X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fplugin.c;h=65e0311aff4a8802fbb3af06834cd221cc98b229;hb=c329f0f22773df936ef31c539d8fd32c3a973659;hp=cfbd906ace35081dd3f4a16c864dc53336d6d12f;hpb=0889675fe72fdedfd0f8919084d80a550d6b3472;p=framework%2Fconnectivity%2Fconnman.git diff --git a/src/plugin.c b/src/plugin.c index cfbd906..65e0311 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -2,7 +2,7 @@ * * Connection Manager * - * Copyright (C) 2007-2008 Intel Corporation. All rights reserved. + * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -27,42 +27,121 @@ #include +#ifdef CONNMAN_PLUGIN_BUILTIN +#undef CONNMAN_PLUGIN_BUILTIN +#endif + #include "connman.h" +/* + * Plugins that are using libraries with threads and their own mainloop + * will crash on exit. This is a bug inside these libraries, but there is + * nothing much that can be done about it. + */ +#ifdef NEED_THREADS +#define PLUGINFLAG (RTLD_NOW | RTLD_NODELETE) +#else +#define PLUGINFLAG (RTLD_NOW) +#endif + static GSList *plugins = NULL; struct connman_plugin { void *handle; + gboolean active; struct connman_plugin_desc *desc; }; +static gint compare_priority(gconstpointer a, gconstpointer b) +{ + const struct connman_plugin *plugin1 = a; + const struct connman_plugin *plugin2 = b; + + return plugin2->desc->priority - plugin1->desc->priority; +} + static gboolean add_plugin(void *handle, struct connman_plugin_desc *desc) { struct connman_plugin *plugin; + if (desc->init == NULL) + return FALSE; + + if (g_str_equal(desc->version, CONNMAN_VERSION) == FALSE) { + connman_error("Invalid version %s for %s", desc->version, + desc->description); + return FALSE; + } + plugin = g_try_new0(struct connman_plugin, 1); if (plugin == NULL) return FALSE; plugin->handle = handle; + plugin->active = FALSE; plugin->desc = desc; - if (desc->init() < 0) - return FALSE; + __connman_log_enable(desc->debug_start, desc->debug_stop); + + plugins = g_slist_insert_sorted(plugins, plugin, compare_priority); + + return TRUE; +} + +static gboolean check_plugin(struct connman_plugin_desc *desc, + char **patterns, char **excludes) +{ + if (excludes) { + for (; *excludes; excludes++) + if (g_pattern_match_simple(*excludes, desc->name)) + break; + if (*excludes) { + connman_info("Excluding %s", desc->description); + return FALSE; + } + } - plugins = g_slist_append(plugins, plugin); + if (patterns) { + for (; *patterns; patterns++) + if (g_pattern_match_simple(*patterns, desc->name)) + break; + if (!*patterns) { + connman_info("Ignoring %s", desc->description); + return FALSE; + } + } return TRUE; } -int __connman_plugin_init(void) +#include "builtin.h" + +int __connman_plugin_init(const char *pattern, const char *exclude) { + gchar **patterns = NULL; + gchar **excludes = NULL; + GSList *list; GDir *dir; const gchar *file; gchar *filename; + unsigned int i; DBG(""); + if (pattern) + patterns = g_strsplit_set(pattern, ":, ", -1); + + if (exclude) + excludes = g_strsplit_set(exclude, ":, ", -1); + + for (i = 0; __connman_builtin[i]; i++) { + if (check_plugin(__connman_builtin[i], + patterns, excludes) == FALSE) + continue; + + add_plugin(NULL, __connman_builtin[i]); + } + dir = g_dir_open(PLUGINDIR, 0, NULL); if (dir != NULL) { while ((file = g_dir_read_name(dir)) != NULL) { @@ -75,10 +154,10 @@ int __connman_plugin_init(void) filename = g_build_filename(PLUGINDIR, file, NULL); - handle = dlopen(filename, RTLD_NOW); + handle = dlopen(filename, PLUGINFLAG); if (handle == NULL) { - g_warning("Can't load %s: %s", filename, - dlerror()); + connman_error("Can't load %s: %s", + filename, dlerror()); g_free(filename); continue; } @@ -87,12 +166,13 @@ int __connman_plugin_init(void) desc = dlsym(handle, "connman_plugin_desc"); if (desc == NULL) { - g_warning("Can't load symbol: %s", dlerror()); + connman_error("Can't load symbol: %s", + dlerror()); dlclose(handle); continue; } - if (desc->init == NULL) { + if (check_plugin(desc, patterns, excludes) == FALSE) { dlclose(handle); continue; } @@ -104,6 +184,18 @@ int __connman_plugin_init(void) g_dir_close(dir); } + for (list = plugins; list; list = list->next) { + struct connman_plugin *plugin = list->data; + + if (plugin->desc->init() < 0) + continue; + + plugin->active = TRUE; + } + + g_strfreev(patterns); + g_strfreev(excludes); + return 0; } @@ -116,10 +208,11 @@ void __connman_plugin_cleanup(void) for (list = plugins; list; list = list->next) { struct connman_plugin *plugin = list->data; - if (plugin->desc->exit) + if (plugin->active == TRUE && plugin->desc->exit) plugin->desc->exit(); - dlclose(plugin->handle); + if (plugin->handle != NULL) + dlclose(plugin->handle); g_free(plugin); }