diff options
Diffstat (limited to 'src/util/plugin.c')
-rw-r--r-- | src/util/plugin.c | 243 |
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 | */ | ||
36 | struct 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 | */ | ||
58 | static char *old_dlsearchpath; | ||
59 | |||
60 | |||
61 | /** | ||
62 | * List of plugins we have loaded. | ||
63 | */ | ||
64 | static struct PluginList *plugins; | ||
65 | |||
66 | |||
67 | /** | ||
68 | * Setup libtool paths. | ||
69 | */ | ||
70 | void __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 | */ | ||
117 | void __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 | */ | ||
137 | static GNUNET_PLUGIN_Callback | ||
138 | resolve_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 | */ | ||
168 | void * | ||
169 | GNUNET_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 | */ | ||
209 | void * | ||
210 | GNUNET_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 */ | ||