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
28 #include <libltdl/ltdl.h>
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 * Libtool search path before we started.
58 static char *old_dlsearchpath;
62 * List of plugins we have loaded.
64 static struct PluginList *plugins;
68 * Setup libtool paths.
70 void __attribute__ ((constructor)) GNUNET_PLUGIN_init ()
85 _("Initialization of plugin mechanism failed: %s!\n"),
89 opath = lt_dlgetsearchpath ();
91 old_dlsearchpath = GNUNET_strdup (opath);
92 path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR);
97 cpath = GNUNET_malloc (strlen (path) + strlen (opath) + 4);
98 strcpy (cpath, opath);
100 strcat (cpath, path);
101 lt_dlsetsearchpath (cpath);
107 lt_dlsetsearchpath (path);
117 void __attribute__ ((destructor)) GNUNET_PLUGIN_fini ()
119 lt_dlsetsearchpath (old_dlsearchpath);
120 if (old_dlsearchpath != NULL)
122 GNUNET_free (old_dlsearchpath);
123 old_dlsearchpath = NULL;
135 * Lookup a function in the plugin.
137 static GNUNET_PLUGIN_Callback
138 resolve_function (struct PluginList *plug, const char *name)
143 GNUNET_asprintf (&initName, "_%s_%s", plug->name, name);
144 mptr = lt_dlsym (plug->handle, &initName[1]);
146 mptr = lt_dlsym (plug->handle, initName);
148 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
149 _("`%s' failed to resolve method '%s' with error: %s\n"),
150 "lt_dlsym", &initName[1], lt_dlerror ());
151 GNUNET_free (initName);
157 * Setup plugin (runs the "init" callback and returns whatever "init"
158 * returned). If "init" returns NULL, the plugin is unloaded.
160 * Note that the library must export symbols called
161 * "library_name_init" and "library_name_done". These will be called
162 * when the library is loaded and unloaded respectively.
164 * @param library_name name of the plugin to load
165 * @param arg argument to the plugin initialization function
166 * @return whatever the initialization function returned
169 GNUNET_PLUGIN_load (const char *library_name, void *arg)
172 struct PluginList *plug;
173 GNUNET_PLUGIN_Callback init;
176 libhandle = lt_dlopenext (library_name);
177 if (libhandle == NULL)
179 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
180 _("`%s' failed for library `%s' with error: %s\n"),
181 "lt_dlopenext", library_name, lt_dlerror ());
184 plug = GNUNET_malloc (sizeof (struct PluginList));
185 plug->handle = libhandle;
186 plug->name = GNUNET_strdup (library_name);
187 plug->next = plugins;
189 init = resolve_function (plug, "init");
190 if ((init == NULL) || (NULL == (ret = init (arg))))
192 GNUNET_free (plug->name);
193 plugins = plug->next;
202 * Unload plugin (runs the "done" callback and returns whatever "done"
203 * returned). The plugin is then unloaded.
205 * @param library_name name of the plugin to unload
206 * @param arg argument to the plugin shutdown function
207 * @return whatever the shutdown function returned
210 GNUNET_PLUGIN_unload (const char *library_name, void *arg)
212 struct PluginList *pos;
213 struct PluginList *prev;
214 GNUNET_PLUGIN_Callback done;
219 while ((pos != NULL) && (0 != strcmp (pos->name, library_name)))
227 done = resolve_function (pos, "done");
234 prev->next = pos->next;
235 lt_dlclose (pos->handle);
236 GNUNET_free (pos->name);
243 /* end of plugin.c */