aboutsummaryrefslogtreecommitdiff
path: root/src/util/plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/plugin.c')
-rw-r--r--src/util/plugin.c243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/util/plugin.c b/src/util/plugin.c
new file mode 100644
index 000000000..d26a343c7
--- /dev/null
+++ b/src/util/plugin.c
@@ -0,0 +1,243 @@
1/*
2 This file is part of GNUnet
3 (C) 2002, 2003, 2004, 2005, 2006, 2009 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19*/
20
21/**
22 * @file util/plugin.c
23 * @brief Methods to access plugins
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include <libltdl/ltdl.h>
29#include "gnunet_common.h"
30#include "gnunet_os_lib.h"
31#include "gnunet_plugin_lib.h"
32
33/**
34 * Linked list of active plugins.
35 */
36struct PluginList
37{
38 /**
39 * This is a linked list.
40 */
41 struct PluginList *next;
42
43 /**
44 * Name of the library.
45 */
46 char *name;
47
48 /**
49 * System handle.
50 */
51 void *handle;
52};
53
54
55/**
56 * Libtool search path before we started.
57 */
58static char *old_dlsearchpath;
59
60
61/**
62 * List of plugins we have loaded.
63 */
64static struct PluginList *plugins;
65
66
67/**
68 * Setup libtool paths.
69 */
70void __attribute__ ((constructor)) GNUNET_PLUGIN_init ()
71{
72 int err;
73 const char *opath;
74 char *path;
75 char *cpath;
76
77#ifdef MINGW
78 InitWinEnv (NULL);
79#endif
80
81 err = lt_dlinit ();
82 if (err > 0)
83 {
84 fprintf (stderr,
85 _("Initialization of plugin mechanism failed: %s!\n"),
86 lt_dlerror ());
87 return;
88 }
89 opath = lt_dlgetsearchpath ();
90 if (opath != NULL)
91 old_dlsearchpath = GNUNET_strdup (opath);
92 path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR);
93 if (path != NULL)
94 {
95 if (opath != NULL)
96 {
97 cpath = GNUNET_malloc (strlen (path) + strlen (opath) + 4);
98 strcpy (cpath, opath);
99 strcat (cpath, ":");
100 strcat (cpath, path);
101 lt_dlsetsearchpath (cpath);
102 GNUNET_free (path);
103 GNUNET_free (cpath);
104 }
105 else
106 {
107 lt_dlsetsearchpath (path);
108 GNUNET_free (path);
109 }
110 }
111}
112
113
114/**
115 * Shutdown libtool.
116 */
117void __attribute__ ((destructor)) GNUNET_PLUGIN_fini ()
118{
119 lt_dlsetsearchpath (old_dlsearchpath);
120 if (old_dlsearchpath != NULL)
121 {
122 GNUNET_free (old_dlsearchpath);
123 old_dlsearchpath = NULL;
124 }
125
126#ifdef MINGW
127 ShutdownWinEnv ();
128#endif
129
130 lt_dlexit ();
131}
132
133
134/**
135 * Lookup a function in the plugin.
136 */
137static GNUNET_PLUGIN_Callback
138resolve_function (struct PluginList *plug, const char *name)
139{
140 char *initName;
141 void *mptr;
142
143 GNUNET_asprintf (&initName, "_%s_%s", plug->name, name);
144 mptr = lt_dlsym (plug->handle, &initName[1]);
145 if (mptr == NULL)
146 mptr = lt_dlsym (plug->handle, initName);
147 if (mptr == NULL)
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);
152 return mptr;
153}
154
155
156/**
157 * Setup plugin (runs the "init" callback and returns whatever "init"
158 * returned). If "init" returns NULL, the plugin is unloaded.
159 *
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.
163 *
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
167 */
168void *
169GNUNET_PLUGIN_load (const char *library_name, void *arg)
170{
171 void *libhandle;
172 struct PluginList *plug;
173 GNUNET_PLUGIN_Callback init;
174 void *ret;
175
176 libhandle = lt_dlopenext (library_name);
177 if (libhandle == NULL)
178 {
179 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
180 _("`%s' failed for library `%s' with error: %s\n"),
181 "lt_dlopenext", library_name, lt_dlerror ());
182 return NULL;
183 }
184 plug = GNUNET_malloc (sizeof (struct PluginList));
185 plug->handle = libhandle;
186 plug->name = GNUNET_strdup (library_name);
187 plug->next = plugins;
188 plugins = plug;
189 init = resolve_function (plug, "init");
190 if ((init == NULL) || (NULL == (ret = init (arg))))
191 {
192 GNUNET_free (plug->name);
193 plugins = plug->next;
194 GNUNET_free (plug);
195 return NULL;
196 }
197 return ret;
198}
199
200
201/**
202 * Unload plugin (runs the "done" callback and returns whatever "done"
203 * returned). The plugin is then unloaded.
204 *
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
208 */
209void *
210GNUNET_PLUGIN_unload (const char *library_name, void *arg)
211{
212 struct PluginList *pos;
213 struct PluginList *prev;
214 GNUNET_PLUGIN_Callback done;
215 void *ret;
216
217 prev = NULL;
218 pos = plugins;
219 while ((pos != NULL) && (0 != strcmp (pos->name, library_name)))
220 {
221 prev = pos;
222 pos = pos->next;
223 }
224 if (pos == NULL)
225 return NULL;
226
227 done = resolve_function (pos, "done");
228 ret = NULL;
229 if (done != NULL)
230 ret = done (arg);
231 if (prev == NULL)
232 plugins = pos->next;
233 else
234 prev->next = pos->next;
235 // lt_dlclose (pos->handle);
236 GNUNET_free (pos->name);
237 GNUNET_free (pos);
238 return ret;
239}
240
241
242
243/* end of plugin.c */