aboutsummaryrefslogtreecommitdiff
path: root/src/util/plugin.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 13:37:38 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-10-18 13:37:38 +0200
commit9ef4abad615bea12d13be542b8ae5fbeb2dfee32 (patch)
tree8875a687e004d331c9ea6a1d511a328c72b88113 /src/util/plugin.c
parente95236b3ed78cd597c15f34b89385295702b627f (diff)
downloadgnunet-9ef4abad615bea12d13be542b8ae5fbeb2dfee32.tar.gz
gnunet-9ef4abad615bea12d13be542b8ae5fbeb2dfee32.zip
NEWS: Refactoring components under src/ into lib/, plugin/, cli/ and service/
This also includes a necessary API refactoring of crypto from IDENTITY to UTIL.
Diffstat (limited to 'src/util/plugin.c')
-rw-r--r--src/util/plugin.c403
1 files changed, 0 insertions, 403 deletions
diff --git a/src/util/plugin.c b/src/util/plugin.c
deleted file mode 100644
index 62c2a1df0..000000000
--- a/src/util/plugin.c
+++ /dev/null
@@ -1,403 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2002-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file util/plugin.c
23 * @brief Methods to access plugins
24 * @author Christian Grothoff
25 */
26
27
28#include "platform.h"
29#include <ltdl.h>
30#include "gnunet_util_lib.h"
31
32#define LOG(kind, ...) GNUNET_log_from (kind, "util-plugin", __VA_ARGS__)
33
34/**
35 * Linked list of active plugins.
36 */
37struct PluginList
38{
39 /**
40 * This is a linked list.
41 */
42 struct PluginList *next;
43
44 /**
45 * Name of the library.
46 */
47 char *name;
48
49 /**
50 * System handle.
51 */
52 void *handle;
53};
54
55
56/**
57 * Have we been initialized?
58 */
59static int initialized;
60
61/**
62 * Libtool search path before we started.
63 */
64static char *old_dlsearchpath;
65
66/**
67 * List of plugins we have loaded.
68 */
69static struct PluginList *plugins;
70
71
72/**
73 * Setup libtool paths.
74 */
75static void
76plugin_init (void)
77{
78 int err;
79 const char *opath;
80 char *path;
81 char *cpath;
82
83 err = lt_dlinit ();
84 if (err > 0)
85 {
86 fprintf (stderr,
87 _ ("Initialization of plugin mechanism failed: %s!\n"),
88 lt_dlerror ());
89 return;
90 }
91 opath = lt_dlgetsearchpath ();
92 if (NULL != opath)
93 old_dlsearchpath = GNUNET_strdup (opath);
94 path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR);
95 if (NULL != path)
96 {
97 if (NULL != opath)
98 {
99 GNUNET_asprintf (&cpath,
100 "%s:%s",
101 opath,
102 path);
103 lt_dlsetsearchpath (cpath);
104 GNUNET_free (path);
105 GNUNET_free (cpath);
106 }
107 else
108 {
109 lt_dlsetsearchpath (path);
110 GNUNET_free (path);
111 }
112 }
113}
114
115
116/**
117 * Shutdown libtool.
118 */
119static void
120plugin_fini (void)
121{
122 lt_dlsetsearchpath (old_dlsearchpath);
123 if (NULL != old_dlsearchpath)
124 {
125 GNUNET_free (old_dlsearchpath);
126 old_dlsearchpath = NULL;
127 }
128 if (NULL == getenv ("VALGRINDING_PLUGINS"))
129 lt_dlexit ();
130}
131
132
133/**
134 * Lookup a function in the plugin.
135 *
136 * @param plug the plugin to check
137 * @param name name of the symbol to look for
138 * @return NULL if the symbol was not found
139 */
140static GNUNET_PLUGIN_Callback
141resolve_function (struct PluginList *plug,
142 const char *name)
143{
144 char *initName;
145 void *mptr;
146
147 GNUNET_asprintf (&initName,
148 "_%s_%s",
149 plug->name,
150 name);
151 mptr = lt_dlsym (plug->handle,
152 &initName[1]);
153 if (NULL == mptr)
154 mptr = lt_dlsym (plug->handle,
155 initName);
156 if (NULL == mptr)
157 LOG (GNUNET_ERROR_TYPE_ERROR,
158 _ ("`%s' failed to resolve method '%s' with error: %s\n"),
159 "lt_dlsym",
160 &initName[1],
161 lt_dlerror ());
162 GNUNET_free (initName);
163 return mptr;
164}
165
166
167enum GNUNET_GenericReturnValue
168GNUNET_PLUGIN_test (const char *library_name)
169{
170 void *libhandle;
171 GNUNET_PLUGIN_Callback init;
172 struct PluginList plug;
173
174 if (! initialized)
175 {
176 initialized = GNUNET_YES;
177 plugin_init ();
178 }
179 libhandle = lt_dlopenext (library_name);
180 if (NULL == libhandle)
181 return GNUNET_NO;
182 plug.handle = libhandle;
183 plug.name = (char *) library_name;
184 init = resolve_function (&plug,
185 "init");
186 if (NULL == init)
187 {
188 GNUNET_break (0);
189 lt_dlclose (libhandle);
190 return GNUNET_NO;
191 }
192 lt_dlclose (libhandle);
193 return GNUNET_YES;
194}
195
196
197void *
198GNUNET_PLUGIN_load (const char *library_name,
199 void *arg)
200{
201 void *libhandle;
202 struct PluginList *plug;
203 GNUNET_PLUGIN_Callback init;
204 void *ret;
205
206 if (! initialized)
207 {
208 initialized = GNUNET_YES;
209 plugin_init ();
210 }
211 libhandle = lt_dlopenext (library_name);
212 if (NULL == libhandle)
213 {
214 LOG (GNUNET_ERROR_TYPE_ERROR,
215 _ ("`%s' failed for library `%s' with error: %s\n"),
216 "lt_dlopenext",
217 library_name,
218 lt_dlerror ());
219 return NULL;
220 }
221 plug = GNUNET_new (struct PluginList);
222 plug->handle = libhandle;
223 plug->name = GNUNET_strdup (library_name);
224 plug->next = plugins;
225 plugins = plug;
226 init = resolve_function (plug,
227 "init");
228 if ( (NULL == init) ||
229 (NULL == (ret = init (arg))) )
230 {
231 lt_dlclose (libhandle);
232 GNUNET_free (plug->name);
233 plugins = plug->next;
234 GNUNET_free (plug);
235 return NULL;
236 }
237 return ret;
238}
239
240
241void *
242GNUNET_PLUGIN_unload (const char *library_name,
243 void *arg)
244{
245 struct PluginList *pos;
246 struct PluginList *prev;
247 GNUNET_PLUGIN_Callback done;
248 void *ret;
249
250 prev = NULL;
251 pos = plugins;
252 while ( (NULL != pos) &&
253 (0 != strcmp (pos->name,
254 library_name)) )
255 {
256 prev = pos;
257 pos = pos->next;
258 }
259 if (NULL == pos)
260 return NULL;
261
262 done = resolve_function (pos,
263 "done");
264 ret = NULL;
265 if (NULL == prev)
266 plugins = pos->next;
267 else
268 prev->next = pos->next;
269 if (NULL != done)
270 ret = done (arg);
271 if (NULL == getenv ("VALGRINDING_PLUGINS"))
272 lt_dlclose (pos->handle);
273 GNUNET_free (pos->name);
274 GNUNET_free (pos);
275 if (NULL == plugins)
276 {
277 plugin_fini ();
278 initialized = GNUNET_NO;
279 }
280 return ret;
281}
282
283
284/**
285 * Closure for #find_libraries().
286 */
287struct LoadAllContext
288{
289 /**
290 * Prefix the plugin names we find have to match.
291 */
292 const char *basename;
293
294 /**
295 * Argument to give to 'init' when loading the plugin.
296 */
297 void *arg;
298
299 /**
300 * Function to call for each plugin.
301 */
302 GNUNET_PLUGIN_LoaderCallback cb;
303
304 /**
305 * Closure for @e cb
306 */
307 void *cb_cls;
308};
309
310
311/**
312 * Function called on each plugin in the directory. Loads
313 * the plugins that match the given basename.
314 *
315 * @param cls the `struct LoadAllContext` describing which
316 * plugins to load and what to do with them
317 * @param filename name of a plugin library to check
318 * @return #GNUNET_OK (continue loading)
319 */
320static int
321find_libraries (void *cls,
322 const char *filename)
323{
324 struct LoadAllContext *lac = cls;
325 const char *slashpos;
326 const char *libname;
327 char *basename;
328 char *dot;
329 void *lib_ret;
330 size_t n;
331
332 libname = filename;
333 while (NULL != (slashpos = strstr (libname,
334 DIR_SEPARATOR_STR)))
335 libname = slashpos + 1;
336 n = strlen (libname);
337 if (0 != strncmp (lac->basename,
338 libname,
339 strlen (lac->basename)))
340 return GNUNET_OK; /* wrong name */
341 if ( (n > 3) &&
342 (0 == strcmp (&libname[n - 3], ".la")) )
343 return GNUNET_OK; /* .la file */
344 basename = GNUNET_strdup (libname);
345 if (NULL != (dot = strstr (basename, ".")))
346 *dot = '\0';
347 lib_ret = GNUNET_PLUGIN_load (basename,
348 lac->arg);
349 if (NULL != lib_ret)
350 lac->cb (lac->cb_cls,
351 basename,
352 lib_ret);
353 GNUNET_free (basename);
354 return GNUNET_OK;
355}
356
357
358void
359GNUNET_PLUGIN_load_all (const char *basename,
360 void *arg,
361 GNUNET_PLUGIN_LoaderCallback cb,
362 void *cb_cls)
363{
364 struct LoadAllContext lac;
365 char *path;
366
367 path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR);
368 if (NULL == path)
369 {
370 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
371 _ ("Could not determine plugin installation path.\n"));
372 return;
373 }
374 lac.basename = basename;
375 lac.arg = arg;
376 lac.cb = cb;
377 lac.cb_cls = cb_cls;
378 GNUNET_DISK_directory_scan (path,
379 &find_libraries,
380 &lac);
381 GNUNET_free (path);
382}
383
384
385void
386GNUNET_PLUGIN_load_all_in_context (const struct GNUNET_OS_ProjectData *ctx,
387 const char *basename,
388 void *arg,
389 GNUNET_PLUGIN_LoaderCallback cb,
390 void *cb_cls)
391{
392 const struct GNUNET_OS_ProjectData *cpd = GNUNET_OS_project_data_get ();
393
394 GNUNET_OS_init (ctx);
395 GNUNET_PLUGIN_load_all (basename,
396 arg,
397 cb,
398 cb_cls);
399 GNUNET_OS_init (cpd);
400}
401
402
403/* end of plugin.c */