#include "gnunet_os_lib.h"
#include "gnunet_plugin_lib.h"
+#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+
/**
* Linked list of active plugins.
*/
/**
* Setup libtool paths.
*/
-static void
+static void
plugin_init ()
{
int err;
err = lt_dlinit ();
if (err > 0)
{
- fprintf (stderr,
- _("Initialization of plugin mechanism failed: %s!\n"),
- lt_dlerror ());
+ fprintf (stderr, _("Initialization of plugin mechanism failed: %s!\n"),
+ lt_dlerror ());
return;
}
opath = lt_dlgetsearchpath ();
if (path != NULL)
{
if (opath != NULL)
- {
- cpath = GNUNET_malloc (strlen (path) + strlen (opath) + 4);
- strcpy (cpath, opath);
- strcat (cpath, ":");
- strcat (cpath, path);
- lt_dlsetsearchpath (cpath);
- GNUNET_free (path);
- GNUNET_free (cpath);
- }
+ {
+ GNUNET_asprintf (&cpath, "%s:%s", opath, path);
+ lt_dlsetsearchpath (cpath);
+ GNUNET_free (path);
+ GNUNET_free (cpath);
+ }
else
- {
- lt_dlsetsearchpath (path);
- GNUNET_free (path);
- }
+ {
+ lt_dlsetsearchpath (path);
+ GNUNET_free (path);
+ }
}
}
if (mptr == NULL)
mptr = lt_dlsym (plug->handle, initName);
if (mptr == NULL)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("`%s' failed to resolve method '%s' with error: %s\n"),
- "lt_dlsym", &initName[1], lt_dlerror ());
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("`%s' failed to resolve method '%s' with error: %s\n"),
+ "lt_dlsym", &initName[1], lt_dlerror ());
GNUNET_free (initName);
return mptr;
}
+/**
+ * Test if a plugin exists.
+ *
+ * Note that the library must export a symbol called
+ * "library_name_init" for the test to succeed.
+ *
+ * @param library_name name of the plugin to test if it is installed
+ * @return GNUNET_YES if the plugin exists, GNUNET_NO if not
+ */
+int
+GNUNET_PLUGIN_test (const char *library_name)
+{
+ void *libhandle;
+ GNUNET_PLUGIN_Callback init;
+ struct PluginList plug;
+
+ if (!initialized)
+ {
+ initialized = GNUNET_YES;
+ plugin_init ();
+ }
+ libhandle = lt_dlopenext (library_name);
+ if (libhandle == NULL)
+ return GNUNET_NO;
+ plug.handle = libhandle;
+ plug.name = (char *) library_name;
+ init = resolve_function (&plug, "init");
+ if (init == NULL)
+ {
+ GNUNET_break (0);
+ lt_dlclose (libhandle);
+ return GNUNET_NO;
+ }
+ lt_dlclose (libhandle);
+ return GNUNET_YES;
+}
+
/**
* Setup plugin (runs the "init" callback and returns whatever "init"
GNUNET_PLUGIN_Callback init;
void *ret;
- if (! initialized)
+ if (!initialized)
{
initialized = GNUNET_YES;
plugin_init ();
libhandle = lt_dlopenext (library_name);
if (libhandle == NULL)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- _("`%s' failed for library `%s' with error: %s\n"),
- "lt_dlopenext", library_name, lt_dlerror ());
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("`%s' failed for library `%s' with error: %s\n"),
+ "lt_dlopenext", library_name, lt_dlerror ());
return NULL;
}
plug = GNUNET_malloc (sizeof (struct PluginList));
init = resolve_function (plug, "init");
if ((init == NULL) || (NULL == (ret = init (arg))))
{
+ lt_dlclose (libhandle);
GNUNET_free (plug->name);
plugins = plug->next;
GNUNET_free (plug);
GNUNET_free (pos);
if (plugins == NULL)
{
- plugin_fini();
+ plugin_fini ();
initialized = GNUNET_NO;
}
return ret;
}
+struct LoadAllContext
+{
+ const char *basename;
+ void *arg;
+ GNUNET_PLUGIN_LoaderCallback cb;
+ void *cb_cls;
+};
+
+
+static int
+find_libraries (void *cls,
+ const char *filename)
+{
+ struct LoadAllContext *lac = cls;
+ const char *slashpos;
+ const char *libname;
+ char *basename;
+ char *dot;
+ void *lib_ret;
+ size_t n;
+
+ libname = filename;
+ while (NULL != (slashpos = strstr (libname, DIR_SEPARATOR_STR)))
+ libname = slashpos + 1;
+ n = strlen (libname);
+ if (0 != strncmp (lac->basename,
+ libname,
+ strlen (lac->basename)))
+ return GNUNET_OK; /* wrong name */
+ if ( (n > 3) &&
+ (0 == strcmp (&libname[n-3],
+ ".la")) )
+ return GNUNET_OK; /* .la file */
+ basename = GNUNET_strdup (libname);
+ if (NULL != (dot = strstr (basename, ".")))
+ *dot = '\0';
+ lib_ret = GNUNET_PLUGIN_load (basename, lac->arg);
+ if (NULL != lib_ret)
+ lac->cb (lac->cb_cls, basename, lib_ret);
+ GNUNET_free (basename);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Load all compatible plugins with the given base name.
+ *
+ * Note that the library must export symbols called
+ * "basename_ANYTHING_init" and "basename_ANYTHING__done". These will
+ * be called when the library is loaded and unloaded respectively.
+ *
+ * @param basename basename of the plugins to load
+ * @param arg argument to the plugin initialization function
+ * @param cb function to call for each plugin found
+ * @param cb_cls closure for 'cb'
+ */
+void
+GNUNET_PLUGIN_load_all (const char *basename,
+ void *arg,
+ GNUNET_PLUGIN_LoaderCallback cb,
+ void *cb_cls)
+{
+ struct LoadAllContext lac;
+ char *path;
+
+ path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR);
+ if (path == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Could not determine plugin installation path.\n"));
+ return;
+ }
+ lac.basename = basename;
+ lac.arg = arg;
+ lac.cb = cb;
+ lac.cb_cls = cb_cls;
+ GNUNET_DISK_directory_scan (path,
+ &find_libraries,
+ &lac);
+ GNUNET_free (path);
+}
+
/* end of plugin.c */