GNUnet  0.11.x
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 
27 #include "platform.h"
28 #include <ltdl.h>
29 #include "gnunet_util_lib.h"
30 
31 #define LOG(kind, ...) GNUNET_log_from (kind, "util-plugin", __VA_ARGS__)
32 
36 struct PluginList
37 {
41  struct PluginList *next;
42 
46  char *name;
47 
51  void *handle;
52 };
53 
54 
58 static int initialized;
59 
63 static char *old_dlsearchpath;
64 
68 static struct PluginList *plugins;
69 
70 
74 static void
76 {
77  int err;
78  const char *opath;
79  char *path;
80  char *cpath;
81 
82  err = lt_dlinit ();
83  if (err > 0)
84  {
85  fprintf (stderr,
86  _ ("Initialization of plugin mechanism failed: %s!\n"),
87  lt_dlerror ());
88  return;
89  }
90  opath = lt_dlgetsearchpath ();
91  if (NULL != opath)
94  if (NULL != path)
95  {
96  if (NULL != opath)
97  {
98  GNUNET_asprintf (&cpath,
99  "%s:%s",
100  opath,
101  path);
102  lt_dlsetsearchpath (cpath);
103  GNUNET_free (path);
104  GNUNET_free (cpath);
105  }
106  else
107  {
108  lt_dlsetsearchpath (path);
109  GNUNET_free (path);
110  }
111  }
112 }
113 
114 
118 static void
120 {
121  lt_dlsetsearchpath (old_dlsearchpath);
122  if (NULL != old_dlsearchpath)
123  {
125  old_dlsearchpath = NULL;
126  }
127  lt_dlexit ();
128 }
129 
130 
140  const char *name)
141 {
142  char *initName;
143  void *mptr;
144 
145  GNUNET_asprintf (&initName,
146  "_%s_%s",
147  plug->name,
148  name);
149  mptr = lt_dlsym (plug->handle,
150  &initName[1]);
151  if (NULL == mptr)
152  mptr = lt_dlsym (plug->handle,
153  initName);
154  if (NULL == mptr)
156  _ ("`%s' failed to resolve method '%s' with error: %s\n"),
157  "lt_dlsym",
158  &initName[1],
159  lt_dlerror ());
160  GNUNET_free (initName);
161  return mptr;
162 }
163 
164 
174 int
175 GNUNET_PLUGIN_test (const char *library_name)
176 {
177  void *libhandle;
179  struct PluginList plug;
180 
181  if (! initialized)
182  {
184  plugin_init ();
185  }
186  libhandle = lt_dlopenext (library_name);
187  if (NULL == libhandle)
188  return GNUNET_NO;
189  plug.handle = libhandle;
190  plug.name = (char *) library_name;
191  init = resolve_function (&plug,
192  "init");
193  if (NULL == init)
194  {
195  GNUNET_break (0);
196  lt_dlclose (libhandle);
197  return GNUNET_NO;
198  }
199  lt_dlclose (libhandle);
200  return GNUNET_YES;
201 }
202 
203 
216 void *
217 GNUNET_PLUGIN_load (const char *library_name,
218  void *arg)
219 {
220  void *libhandle;
221  struct PluginList *plug;
223  void *ret;
224 
225  if (! initialized)
226  {
228  plugin_init ();
229  }
230  libhandle = lt_dlopenext (library_name);
231  if (NULL == libhandle)
232  {
234  _ ("`%s' failed for library `%s' with error: %s\n"),
235  "lt_dlopenext",
236  library_name,
237  lt_dlerror ());
238  return NULL;
239  }
240  plug = GNUNET_new (struct PluginList);
241  plug->handle = libhandle;
242  plug->name = GNUNET_strdup (library_name);
243  plug->next = plugins;
244  plugins = plug;
245  init = resolve_function (plug,
246  "init");
247  if ( (NULL == init) ||
248  (NULL == (ret = init (arg))) )
249  {
250  lt_dlclose (libhandle);
251  GNUNET_free (plug->name);
252  plugins = plug->next;
253  GNUNET_free (plug);
254  return NULL;
255  }
256  return ret;
257 }
258 
259 
268 void *
269 GNUNET_PLUGIN_unload (const char *library_name,
270  void *arg)
271 {
272  struct PluginList *pos;
273  struct PluginList *prev;
275  void *ret;
276 
277  prev = NULL;
278  pos = plugins;
279  while ( (NULL != pos) &&
280  (0 != strcmp (pos->name,
281  library_name)) )
282  {
283  prev = pos;
284  pos = pos->next;
285  }
286  if (NULL == pos)
287  return NULL;
288 
289  done = resolve_function (pos,
290  "done");
291  ret = NULL;
292  if (NULL != done)
293  ret = done (arg);
294  if (NULL == prev)
295  plugins = pos->next;
296  else
297  prev->next = pos->next;
298  lt_dlclose (pos->handle);
299  GNUNET_free (pos->name);
300  GNUNET_free (pos);
301  if (NULL == plugins)
302  {
303  plugin_fini ();
305  }
306  return ret;
307 }
308 
309 
314 {
318  const char *basename;
319 
323  void *arg;
324 
329 
333  void *cb_cls;
334 };
335 
336 
346 static int
347 find_libraries (void *cls,
348  const char *filename)
349 {
350  struct LoadAllContext *lac = cls;
351  const char *slashpos;
352  const char *libname;
353  char *basename;
354  char *dot;
355  void *lib_ret;
356  size_t n;
357 
358  libname = filename;
359  while (NULL != (slashpos = strstr (libname,
361  libname = slashpos + 1;
362  n = strlen (libname);
363  if (0 != strncmp (lac->basename,
364  libname,
365  strlen (lac->basename)))
366  return GNUNET_OK; /* wrong name */
367  if ( (n > 3) &&
368  (0 == strcmp (&libname[n - 3], ".la")) )
369  return GNUNET_OK; /* .la file */
370  basename = GNUNET_strdup (libname);
371  if (NULL != (dot = strstr (basename, ".")))
372  *dot = '\0';
373  lib_ret = GNUNET_PLUGIN_load (basename,
374  lac->arg);
375  if (NULL != lib_ret)
376  lac->cb (lac->cb_cls,
377  basename,
378  lib_ret);
380  return GNUNET_OK;
381 }
382 
383 
401 void
403  void *arg,
405  void *cb_cls)
406 {
407  struct LoadAllContext lac;
408  char *path;
409 
411  if (NULL == path)
412  {
414  _ ("Could not determine plugin installation path.\n"));
415  return;
416  }
417  lac.basename = basename;
418  lac.arg = arg;
419  lac.cb = cb;
420  lac.cb_cls = cb_cls;
423  &lac);
424  GNUNET_free (path);
425 }
426 
427 
442 void
444  const char *basename,
445  void *arg,
447  void *cb_cls)
448 {
449  const struct GNUNET_OS_ProjectData *cpd = GNUNET_OS_project_data_get ();
450 
452  GNUNET_PLUGIN_load_all (basename,
453  arg,
454  cb,
455  cb_cls);
456  GNUNET_OS_init (cpd);
457 }
458 
459 
460 /* end of plugin.c */
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static char * init
Set to the name of a service to start.
Definition: gnunet-arm.c:74
static void done()
static char * filename
static struct GNUNET_DNSSTUB_Context * ctx
Context for DNS resolution.
#define GNUNET_log(kind,...)
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
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_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.
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_get(void)
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.
@ 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:402
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the done callback and returns whatever done returned).
Definition: plugin.c:269
int GNUNET_PLUGIN_test(const char *library_name)
Test if a plugin exists.
Definition: plugin.c:175
void * GNUNET_PLUGIN_load(const char *library_name, void *arg)
Setup plugin (runs the init callback and returns whatever init returned).
Definition: plugin.c:217
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:443
void *(* GNUNET_PLUGIN_Callback)(void *arg)
Signature of any function exported by a plugin.
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:165
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
static void plugin_fini(void)
Shutdown libtool.
Definition: plugin.c:119
static GNUNET_PLUGIN_Callback resolve_function(struct PluginList *plug, const char *name)
Lookup a function in the plugin.
Definition: plugin.c:139
static int find_libraries(void *cls, const char *filename)
Function called on each plugin in the directory.
Definition: plugin.c:347
static void plugin_init(void)
Setup libtool paths.
Definition: plugin.c:75
static char * old_dlsearchpath
Libtool search path before we started.
Definition: plugin.c:63
static struct PluginList * plugins
List of plugins we have loaded.
Definition: plugin.c:68
#define LOG(kind,...)
Definition: plugin.c:31
static int initialized
Have we been initialized?
Definition: plugin.c:58
const char * name
Project-specific data used to help the OS subsystem find installation paths.
Closure for find_libraries().
Definition: plugin.c:314
const char * basename
Prefix the plugin names we find have to match.
Definition: plugin.c:318
void * cb_cls
Closure for cb.
Definition: plugin.c:333
void * arg
Argument to give to 'init' when loading the plugin.
Definition: plugin.c:323
GNUNET_PLUGIN_LoaderCallback cb
Function to call for each plugin.
Definition: plugin.c:328
Linked list of active plugins.
Definition: plugin.c:37
char * name
Name of the library.
Definition: plugin.c:46
struct PluginList * next
This is a linked list.
Definition: plugin.c:41
void * handle
System handle.
Definition: plugin.c:51