Returns now GNUNET_SYSERR
[oweals/gnunet.git] / src / util / plugin.c
index d26a343c707261dc5f61474bf65a0a0c100fa07b..4e960b4fe83c778c1f5233f04fb591659bc2fd0d 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 #include "platform.h"
-#include <libltdl/ltdl.h>
+#include <ltdl.h>
 #include "gnunet_common.h"
 #include "gnunet_os_lib.h"
 #include "gnunet_plugin_lib.h"
@@ -52,6 +52,12 @@ struct PluginList
 };
 
 
+/**
+ * Have we been initialized?
+ */
+static int initialized;
+
+
 /**
  * Libtool search path before we started.
  */
@@ -67,17 +73,14 @@ static struct PluginList *plugins;
 /**
  * Setup libtool paths.
  */
-void __attribute__ ((constructor)) GNUNET_PLUGIN_init ()
+static void 
+plugin_init ()
 {
   int err;
   const char *opath;
   char *path;
   char *cpath;
 
-#ifdef MINGW
-  InitWinEnv (NULL);
-#endif
-
   err = lt_dlinit ();
   if (err > 0)
     {
@@ -94,10 +97,10 @@ void __attribute__ ((constructor)) GNUNET_PLUGIN_init ()
     {
       if (opath != NULL)
         {
-          cpath = GNUNET_malloc (strlen (path) + strlen (opath) + 4);
-          strcpy (cpath, opath);
-          strcat (cpath, ":");
-          strcat (cpath, path);
+         GNUNET_asprintf (&cpath,
+                          "%s:%s",
+                          opath,
+                          path);
           lt_dlsetsearchpath (cpath);
           GNUNET_free (path);
           GNUNET_free (cpath);
@@ -114,7 +117,8 @@ void __attribute__ ((constructor)) GNUNET_PLUGIN_init ()
 /**
  * Shutdown libtool.
  */
-void __attribute__ ((destructor)) GNUNET_PLUGIN_fini ()
+static void
+plugin_fini ()
 {
   lt_dlsetsearchpath (old_dlsearchpath);
   if (old_dlsearchpath != NULL)
@@ -122,11 +126,6 @@ void __attribute__ ((destructor)) GNUNET_PLUGIN_fini ()
       GNUNET_free (old_dlsearchpath);
       old_dlsearchpath = NULL;
     }
-
-#ifdef MINGW
-  ShutdownWinEnv ();
-#endif
-
   lt_dlexit ();
 }
 
@@ -152,6 +151,43 @@ resolve_function (struct PluginList *plug, const char *name)
   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"
@@ -173,6 +209,11 @@ GNUNET_PLUGIN_load (const char *library_name, void *arg)
   GNUNET_PLUGIN_Callback init;
   void *ret;
 
+  if (! initialized)
+    {
+      initialized = GNUNET_YES;
+      plugin_init ();
+    }
   libhandle = lt_dlopenext (library_name);
   if (libhandle == NULL)
     {
@@ -189,6 +230,7 @@ GNUNET_PLUGIN_load (const char *library_name, void *arg)
   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);
@@ -232,9 +274,14 @@ GNUNET_PLUGIN_unload (const char *library_name, void *arg)
     plugins = pos->next;
   else
     prev->next = pos->next;
-  // lt_dlclose (pos->handle);
+  lt_dlclose (pos->handle);
   GNUNET_free (pos->name);
   GNUNET_free (pos);
+  if (plugins == NULL)
+    {
+      plugin_fini();
+      initialized = GNUNET_NO;
+    }
   return ret;
 }