GNUnet 0.22.2
plugin.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2002-2013, 2024 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
26#include "platform.h"
27#include <ltdl.h>
28#include "gnunet_util_lib.h"
29
30#define LOG(kind, ...) GNUNET_log_from (kind, "util-plugin", __VA_ARGS__)
31
36{
41
45 char *name;
46
50 void *handle;
51};
52
53
57static int initialized;
58
62static struct PluginList *plugins;
63
64
68static void
70{
71 int err;
72
73 err = lt_dlinit ();
74 if (err > 0)
75 {
76 fprintf (stderr,
77 _ ("Initialization of plugin mechanism failed: %s!\n"),
78 lt_dlerror ());
79 return;
80 }
81}
82
83
87static void
89{
90 if (NULL == getenv ("VALGRINDING_PLUGINS"))
91 lt_dlexit ();
92}
93
94
104 const char *name)
105{
106 char *initName;
107 void *mptr;
108
109 GNUNET_asprintf (&initName,
110 "_%s_%s",
111 plug->name,
112 name);
113 mptr = lt_dlsym (plug->handle,
114 &initName[1]);
115 if (NULL == mptr)
116 mptr = lt_dlsym (plug->handle,
117 initName);
118 if (NULL == mptr)
120 _ ("`%s' failed to resolve method '%s' with error: %s\n"),
121 "lt_dlsym",
122 &initName[1],
123 lt_dlerror ());
124 GNUNET_free (initName);
125 return mptr;
126}
127
128
136static void *
138 const char *library_name)
139{
140 void *libhandle;
141 const char *opath;
142 char *path;
143 char *cpath;
144
145 opath = lt_dlgetsearchpath ();
148 if (NULL != path)
149 {
150 if (NULL != opath)
151 {
152 GNUNET_asprintf (&cpath,
153 "%s:%s",
154 opath,
155 path);
156 lt_dlsetsearchpath (cpath);
157 GNUNET_free (cpath);
158 }
159 else
160 {
161 lt_dlsetsearchpath (path);
162 }
163 }
164 GNUNET_free (path);
165 libhandle = lt_dlopenext (library_name);
166 lt_dlsetsearchpath (opath);
167 return libhandle;
168}
169
170
173 const char *library_name)
174{
175 void *libhandle;
177 struct PluginList plug;
178
179 if (! initialized)
180 {
182 plugin_init ();
183 }
184 libhandle = open_library (pd,
185 library_name);
186 if (NULL == libhandle)
187 {
188 if (NULL == plugins)
189 {
190 plugin_fini ();
192 }
193 return GNUNET_NO;
194 }
195 plug.handle = libhandle;
196 plug.name = (char *) library_name;
197 init = resolve_function (&plug,
198 "init");
199 if (NULL == init)
200 {
201 GNUNET_break (0);
202 lt_dlclose (libhandle);
203 if (NULL == plugins)
204 {
205 plugin_fini ();
207 }
208 return GNUNET_NO;
209 }
210 lt_dlclose (libhandle);
211 if (NULL == plugins)
212 {
213 plugin_fini ();
215 }
216 return GNUNET_YES;
217}
218
219
220void *
222 const char *library_name,
223 void *arg)
224{
225 void *libhandle;
226 struct PluginList *plug;
228 void *ret;
229
230 if (! initialized)
231 {
233 plugin_init ();
234 }
235 libhandle = open_library (pd,
236 library_name);
237 if (NULL == libhandle)
238 {
240 _ ("`%s' failed for library `%s' with error: %s\n"),
241 "lt_dlopenext",
242 library_name,
243 lt_dlerror ());
244 if (NULL == plugins)
245 {
246 plugin_fini ();
248 }
249 return NULL;
250 }
251 plug = GNUNET_new (struct PluginList);
252 plug->handle = libhandle;
253 plug->name = GNUNET_strdup (library_name);
254 plug->next = plugins;
255 plugins = plug;
256 init = resolve_function (plug,
257 "init");
258 if ( (NULL == init) ||
259 (NULL == (ret = init (arg))) )
260 {
261 lt_dlclose (libhandle);
262 GNUNET_free (plug->name);
263 plugins = plug->next;
264 GNUNET_free (plug);
265 if (NULL == plugins)
266 {
267 plugin_fini ();
269 }
270 return NULL;
271 }
272 return ret;
273}
274
275
276void *
277GNUNET_PLUGIN_unload (const char *library_name,
278 void *arg)
279{
280 struct PluginList *pos;
281 struct PluginList *prev;
283 void *ret;
284
285 prev = NULL;
286 pos = plugins;
287 while ( (NULL != pos) &&
288 (0 != strcmp (pos->name,
289 library_name)) )
290 {
291 prev = pos;
292 pos = pos->next;
293 }
294 if (NULL == pos)
295 return NULL;
296
297 done = resolve_function (pos,
298 "done");
299 ret = NULL;
300 if (NULL == prev)
301 plugins = pos->next;
302 else
303 prev->next = pos->next;
304 if (NULL != done)
305 ret = done (arg);
306 if (NULL == getenv ("VALGRINDING_PLUGINS"))
307 lt_dlclose (pos->handle);
308 GNUNET_free (pos->name);
309 GNUNET_free (pos);
310 if (NULL == plugins)
311 {
312 plugin_fini ();
314 }
315 return ret;
316}
317
318
323{
324
329
333 const char *basename;
334
338 void *arg;
339
344
348 void *cb_cls;
349};
350
351
362find_libraries (void *cls,
363 const char *filename)
364{
365 struct LoadAllContext *lac = cls;
366 const char *slashpos;
367 const char *libname;
368 char *basename;
369 char *dot;
370 void *lib_ret;
371 size_t n;
372
373 libname = filename;
374 while (NULL != (slashpos = strstr (libname,
376 libname = slashpos + 1;
377 n = strlen (libname);
378 if (0 != strncmp (lac->basename,
379 libname,
380 strlen (lac->basename)))
381 return GNUNET_OK; /* wrong name */
382 if ( (n > 3) &&
383 (0 == strcmp (&libname[n - 3], ".la")) )
384 return GNUNET_OK; /* .la file */
385 basename = GNUNET_strdup (libname);
386 if (NULL != (dot = strstr (basename, ".")))
387 *dot = '\0';
388 lib_ret = GNUNET_PLUGIN_load (lac->pd,
389 basename,
390 lac->arg);
391 if (NULL != lib_ret)
392 lac->cb (lac->cb_cls,
393 basename,
394 lib_ret);
396 return GNUNET_OK;
397}
398
399
400void
402 const char *basename,
403 void *arg,
405 void *cb_cls)
406{
407 struct LoadAllContext lac = {
408 .pd = pd,
409 .basename = basename,
410 .arg = arg,
411 .cb = cb,
412 .cb_cls = cb_cls
413 };
414 char *path;
415
418 if (NULL == path)
419 {
421 _ ("Could not determine plugin installation path.\n"));
422 return;
423 }
426 &lac);
427 GNUNET_free (path);
428}
429
430
431/* end of plugin.c */
char * getenv()
static int ret
Final status code.
Definition: gnunet-arm.c:93
static char * init
Set to the name of a service to start.
Definition: gnunet-arm.c:73
static char * filename
static char * name
Name (label) of the records to list.
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:826
#define GNUNET_log(kind,...)
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_ERROR
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_OS_installation_get_path(const struct GNUNET_OS_ProjectData *pd, enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
@ GNUNET_OS_IPK_LIBDIR
Return the directory where libraries are installed.
void * GNUNET_PLUGIN_load(const struct GNUNET_OS_ProjectData *pd, const char *library_name, void *arg)
Setup plugin (runs the "init" callback and returns whatever "init" returned).
Definition: plugin.c:221
void *(* GNUNET_PLUGIN_Callback)(void *arg)
Signature of any function exported by a plugin.
enum GNUNET_GenericReturnValue GNUNET_PLUGIN_test(const struct GNUNET_OS_ProjectData *pd, const char *library_name)
Test if a plugin exists.
Definition: plugin.c:172
void GNUNET_PLUGIN_load_all(const struct GNUNET_OS_ProjectData *pd, const char *basename, void *arg, GNUNET_PLUGIN_LoaderCallback cb, void *cb_cls)
Load all compatible plugins with the given base name.
Definition: plugin.c:401
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
Definition: plugin.c:277
void(* GNUNET_PLUGIN_LoaderCallback)(void *cls, const char *library_name, void *lib_ret)
Signature of a function called by GNUNET_PLUGIN_load_all().
#define DIR_SEPARATOR_STR
Definition: platform.h:167
#define _(String)
GNU gettext support macro.
Definition: platform.h:179
static void plugin_fini(void)
Shutdown libtool.
Definition: plugin.c:88
static GNUNET_PLUGIN_Callback resolve_function(struct PluginList *plug, const char *name)
Lookup a function in the plugin.
Definition: plugin.c:103
static void plugin_init(void)
Setup libtool paths.
Definition: plugin.c:69
static enum GNUNET_GenericReturnValue find_libraries(void *cls, const char *filename)
Function called on each plugin in the directory.
Definition: plugin.c:362
static void * open_library(const struct GNUNET_OS_ProjectData *pd, const char *library_name)
Open library library_name using search path from pd.
Definition: plugin.c:137
static struct PluginList * plugins
List of plugins we have loaded.
Definition: plugin.c:62
#define LOG(kind,...)
Definition: plugin.c:30
static int initialized
Have we been initialized?
Definition: plugin.c:57
Project-specific data used to help the OS subsystem find installation paths.
Closure for find_libraries().
Definition: plugin.c:323
const char * basename
Prefix the plugin names we find have to match.
Definition: plugin.c:333
void * cb_cls
Closure for cb.
Definition: plugin.c:348
const struct GNUNET_OS_ProjectData * pd
Project data to determine load paths.
Definition: plugin.c:328
void * arg
Argument to give to 'init' when loading the plugin.
Definition: plugin.c:338
GNUNET_PLUGIN_LoaderCallback cb
Function to call for each plugin.
Definition: plugin.c:343
Linked list of active plugins.
Definition: plugin.c:36
char * name
Name of the library.
Definition: plugin.c:45
struct PluginList * next
This is a linked list.
Definition: plugin.c:40
void * handle
System handle.
Definition: plugin.c:50