2 This file is part of GNUnet
3 (C) 2002, 2003, 2004, 2005, 2006, 2009 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
23 * @brief Methods to access plugins
24 * @author Christian Grothoff
29 #include "gnunet_common.h"
30 #include "gnunet_os_lib.h"
31 #include "gnunet_plugin_lib.h"
34 * Linked list of active plugins.
39 * This is a linked list.
41 struct PluginList *next;
44 * Name of the library.
56 * Have we been initialized?
58 static int initialized;
62 * Libtool search path before we started.
64 static char *old_dlsearchpath;
68 * List of plugins we have loaded.
70 static struct PluginList *plugins;
74 * Setup libtool paths.
88 _("Initialization of plugin mechanism failed: %s!\n"),
92 opath = lt_dlgetsearchpath ();
94 old_dlsearchpath = GNUNET_strdup (opath);
95 path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR);
100 GNUNET_asprintf (&cpath,
104 lt_dlsetsearchpath (cpath);
110 lt_dlsetsearchpath (path);
123 lt_dlsetsearchpath (old_dlsearchpath);
124 if (old_dlsearchpath != NULL)
126 GNUNET_free (old_dlsearchpath);
127 old_dlsearchpath = NULL;
134 * Lookup a function in the plugin.
136 static GNUNET_PLUGIN_Callback
137 resolve_function (struct PluginList *plug, const char *name)
142 GNUNET_asprintf (&initName, "_%s_%s", plug->name, name);
143 mptr = lt_dlsym (plug->handle, &initName[1]);
145 mptr = lt_dlsym (plug->handle, initName);
147 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
148 _("`%s' failed to resolve method '%s' with error: %s\n"),
149 "lt_dlsym", &initName[1], lt_dlerror ());
150 GNUNET_free (initName);
155 * Test if a plugin exists.
157 * Note that the library must export a symbol called
158 * "library_name_init" for the test to succeed.
160 * @param library_name name of the plugin to test if it is installed
161 * @return GNUNET_YES if the plugin exists, GNUNET_NO if not
164 GNUNET_PLUGIN_test (const char *library_name)
167 GNUNET_PLUGIN_Callback init;
168 struct PluginList plug;
172 initialized = GNUNET_YES;
175 libhandle = lt_dlopenext (library_name);
176 if (libhandle == NULL)
178 plug.handle = libhandle;
179 plug.name = (char*) library_name;
180 init = resolve_function (&plug, "init");
184 lt_dlclose (libhandle);
187 lt_dlclose (libhandle);
193 * Setup plugin (runs the "init" callback and returns whatever "init"
194 * returned). If "init" returns NULL, the plugin is unloaded.
196 * Note that the library must export symbols called
197 * "library_name_init" and "library_name_done". These will be called
198 * when the library is loaded and unloaded respectively.
200 * @param library_name name of the plugin to load
201 * @param arg argument to the plugin initialization function
202 * @return whatever the initialization function returned
205 GNUNET_PLUGIN_load (const char *library_name, void *arg)
208 struct PluginList *plug;
209 GNUNET_PLUGIN_Callback init;
214 initialized = GNUNET_YES;
217 libhandle = lt_dlopenext (library_name);
218 if (libhandle == NULL)
220 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
221 _("`%s' failed for library `%s' with error: %s\n"),
222 "lt_dlopenext", library_name, lt_dlerror ());
225 plug = GNUNET_malloc (sizeof (struct PluginList));
226 plug->handle = libhandle;
227 plug->name = GNUNET_strdup (library_name);
228 plug->next = plugins;
230 init = resolve_function (plug, "init");
231 if ((init == NULL) || (NULL == (ret = init (arg))))
233 lt_dlclose (libhandle);
234 GNUNET_free (plug->name);
235 plugins = plug->next;
244 * Unload plugin (runs the "done" callback and returns whatever "done"
245 * returned). The plugin is then unloaded.
247 * @param library_name name of the plugin to unload
248 * @param arg argument to the plugin shutdown function
249 * @return whatever the shutdown function returned
252 GNUNET_PLUGIN_unload (const char *library_name, void *arg)
254 struct PluginList *pos;
255 struct PluginList *prev;
256 GNUNET_PLUGIN_Callback done;
261 while ((pos != NULL) && (0 != strcmp (pos->name, library_name)))
269 done = resolve_function (pos, "done");
276 prev->next = pos->next;
277 lt_dlclose (pos->handle);
278 GNUNET_free (pos->name);
283 initialized = GNUNET_NO;
290 /* end of plugin.c */