GNUnet 0.21.0
plugin.c
Go to the documentation of this file.
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
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
38{
43
47 char *name;
48
52 void *handle;
53};
54
55
59static int initialized;
60
64static char *old_dlsearchpath;
65
69static struct PluginList *plugins;
70
71
75static 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)
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
119static void
121{
122 lt_dlsetsearchpath (old_dlsearchpath);
123 if (NULL != old_dlsearchpath)
124 {
126 old_dlsearchpath = NULL;
127 }
128 if (NULL == getenv ("VALGRINDING_PLUGINS"))
129 lt_dlexit ();
130}
131
132
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)
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
168GNUNET_PLUGIN_test (const char *library_name)
169{
170 void *libhandle;
172 struct PluginList plug;
173
174 if (! initialized)
175 {
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;
204 void *ret;
205
206 if (! initialized)
207 {
209 plugin_init ();
210 }
211 libhandle = lt_dlopenext (library_name);
212 if (NULL == libhandle)
213 {
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;
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 ();
279 }
280 return ret;
281}
282
283
288{
292 const char *basename;
293
297 void *arg;
298
303
307 void *cb_cls;
308};
309
310
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,
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);
354 return GNUNET_OK;
355}
356
357
358void
360 void *arg,
362 void *cb_cls)
363{
364 struct LoadAllContext lac;
365 char *path;
366
368 if (NULL == path)
369 {
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;
380 &lac);
381 GNUNET_free (path);
382}
383
384
385void
387 const char *basename,
388 void *arg,
390 void *cb_cls)
391{
393
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 */
char * getenv()
static int ret
Final status code.
Definition: gnunet-arm.c:94
static char * init
Set to the name of a service to start.
Definition: gnunet-arm.c:74
static struct GNUNET_FS_Handle * ctx
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:814
#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(enum GNUNET_OS_InstallationPathKind dirkind)
Get the path to a specific GNUnet installation directory or, with GNUNET_OS_IPK_SELF_PREFIX,...
void GNUNET_OS_init(const struct GNUNET_OS_ProjectData *pd)
Setup OS subsystem with project data.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
@ GNUNET_OS_IPK_LIBDIR
Return the directory where libraries are installed.
void GNUNET_PLUGIN_load_all(const char *basename, void *arg, GNUNET_PLUGIN_LoaderCallback cb, void *cb_cls)
Load all compatible plugins with the given base name.
Definition: plugin.c:359
void * GNUNET_PLUGIN_load(const char *library_name, void *arg)
Setup plugin (runs the "init" callback and returns whatever "init" returned).
Definition: plugin.c:198
void *(* GNUNET_PLUGIN_Callback)(void *arg)
Signature of any function exported by a plugin.
void GNUNET_PLUGIN_load_all_in_context(const struct GNUNET_OS_ProjectData *ctx, const char *basename, void *arg, GNUNET_PLUGIN_LoaderCallback cb, void *cb_cls)
Load all compatible plugins with the given base name while inside the given context (i....
Definition: plugin.c:386
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
Definition: plugin.c:242
enum GNUNET_GenericReturnValue GNUNET_PLUGIN_test(const char *library_name)
Test if a plugin exists.
Definition: plugin.c:168
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:166
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
static void plugin_fini(void)
Shutdown libtool.
Definition: plugin.c:120
static GNUNET_PLUGIN_Callback resolve_function(struct PluginList *plug, const char *name)
Lookup a function in the plugin.
Definition: plugin.c:141
static int find_libraries(void *cls, const char *filename)
Function called on each plugin in the directory.
Definition: plugin.c:321
static void plugin_init(void)
Setup libtool paths.
Definition: plugin.c:76
static char * old_dlsearchpath
Libtool search path before we started.
Definition: plugin.c:64
static struct PluginList * plugins
List of plugins we have loaded.
Definition: plugin.c:69
#define LOG(kind,...)
Definition: plugin.c:32
static int initialized
Have we been initialized?
Definition: plugin.c:59
Project-specific data used to help the OS subsystem find installation paths.
Closure for find_libraries().
Definition: plugin.c:288
const char * basename
Prefix the plugin names we find have to match.
Definition: plugin.c:292
void * cb_cls
Closure for cb.
Definition: plugin.c:307
void * arg
Argument to give to 'init' when loading the plugin.
Definition: plugin.c:297
GNUNET_PLUGIN_LoaderCallback cb
Function to call for each plugin.
Definition: plugin.c:302
Linked list of active plugins.
Definition: plugin.c:38
char * name
Name of the library.
Definition: plugin.c:47
struct PluginList * next
This is a linked list.
Definition: plugin.c:42
void * handle
System handle.
Definition: plugin.c:52