GNUnet  0.17.6
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  if (NULL == getenv ("VALGRINDING_PLUGINS"))
128  lt_dlexit ();
129 }
130 
131 
141  const char *name)
142 {
143  char *initName;
144  void *mptr;
145 
146  GNUNET_asprintf (&initName,
147  "_%s_%s",
148  plug->name,
149  name);
150  mptr = lt_dlsym (plug->handle,
151  &initName[1]);
152  if (NULL == mptr)
153  mptr = lt_dlsym (plug->handle,
154  initName);
155  if (NULL == mptr)
157  _ ("`%s' failed to resolve method '%s' with error: %s\n"),
158  "lt_dlsym",
159  &initName[1],
160  lt_dlerror ());
161  GNUNET_free (initName);
162  return mptr;
163 }
164 
165 
167 GNUNET_PLUGIN_test (const char *library_name)
168 {
169  void *libhandle;
171  struct PluginList plug;
172 
173  if (! initialized)
174  {
176  plugin_init ();
177  }
178  libhandle = lt_dlopenext (library_name);
179  if (NULL == libhandle)
180  return GNUNET_NO;
181  plug.handle = libhandle;
182  plug.name = (char *) library_name;
183  init = resolve_function (&plug,
184  "init");
185  if (NULL == init)
186  {
187  GNUNET_break (0);
188  lt_dlclose (libhandle);
189  return GNUNET_NO;
190  }
191  lt_dlclose (libhandle);
192  return GNUNET_YES;
193 }
194 
195 
196 void *
197 GNUNET_PLUGIN_load (const char *library_name,
198  void *arg)
199 {
200  void *libhandle;
201  struct PluginList *plug;
203  void *ret;
204 
205  if (! initialized)
206  {
208  plugin_init ();
209  }
210  libhandle = lt_dlopenext (library_name);
211  if (NULL == libhandle)
212  {
214  _ ("`%s' failed for library `%s' with error: %s\n"),
215  "lt_dlopenext",
216  library_name,
217  lt_dlerror ());
218  return NULL;
219  }
220  plug = GNUNET_new (struct PluginList);
221  plug->handle = libhandle;
222  plug->name = GNUNET_strdup (library_name);
223  plug->next = plugins;
224  plugins = plug;
225  init = resolve_function (plug,
226  "init");
227  if ( (NULL == init) ||
228  (NULL == (ret = init (arg))) )
229  {
230  lt_dlclose (libhandle);
231  GNUNET_free (plug->name);
232  plugins = plug->next;
233  GNUNET_free (plug);
234  return NULL;
235  }
236  return ret;
237 }
238 
239 
240 void *
241 GNUNET_PLUGIN_unload (const char *library_name,
242  void *arg)
243 {
244  struct PluginList *pos;
245  struct PluginList *prev;
247  void *ret;
248 
249  prev = NULL;
250  pos = plugins;
251  while ( (NULL != pos) &&
252  (0 != strcmp (pos->name,
253  library_name)) )
254  {
255  prev = pos;
256  pos = pos->next;
257  }
258  if (NULL == pos)
259  return NULL;
260 
261  done = resolve_function (pos,
262  "done");
263  ret = NULL;
264  if (NULL == prev)
265  plugins = pos->next;
266  else
267  prev->next = pos->next;
268  if (NULL != done)
269  ret = done (arg);
270  if (NULL == getenv ("VALGRINDING_PLUGINS"))
271  lt_dlclose (pos->handle);
272  GNUNET_free (pos->name);
273  GNUNET_free (pos);
274  if (NULL == plugins)
275  {
276  plugin_fini ();
278  }
279  return ret;
280 }
281 
282 
287 {
291  const char *basename;
292 
296  void *arg;
297 
302 
306  void *cb_cls;
307 };
308 
309 
319 static int
320 find_libraries (void *cls,
321  const char *filename)
322 {
323  struct LoadAllContext *lac = cls;
324  const char *slashpos;
325  const char *libname;
326  char *basename;
327  char *dot;
328  void *lib_ret;
329  size_t n;
330 
331  libname = filename;
332  while (NULL != (slashpos = strstr (libname,
334  libname = slashpos + 1;
335  n = strlen (libname);
336  if (0 != strncmp (lac->basename,
337  libname,
338  strlen (lac->basename)))
339  return GNUNET_OK; /* wrong name */
340  if ( (n > 3) &&
341  (0 == strcmp (&libname[n - 3], ".la")) )
342  return GNUNET_OK; /* .la file */
343  basename = GNUNET_strdup (libname);
344  if (NULL != (dot = strstr (basename, ".")))
345  *dot = '\0';
346  lib_ret = GNUNET_PLUGIN_load (basename,
347  lac->arg);
348  if (NULL != lib_ret)
349  lac->cb (lac->cb_cls,
350  basename,
351  lib_ret);
353  return GNUNET_OK;
354 }
355 
356 
357 void
359  void *arg,
361  void *cb_cls)
362 {
363  struct LoadAllContext lac;
364  char *path;
365 
367  if (NULL == path)
368  {
370  _ ("Could not determine plugin installation path.\n"));
371  return;
372  }
373  lac.basename = basename;
374  lac.arg = arg;
375  lac.cb = cb;
376  lac.cb_cls = cb_cls;
379  &lac);
380  GNUNET_free (path);
381 }
382 
383 
384 void
386  const char *basename,
387  void *arg,
389  void *cb_cls)
390 {
391  const struct GNUNET_OS_ProjectData *cpd = GNUNET_OS_project_data_get ();
392 
394  GNUNET_PLUGIN_load_all (basename,
395  arg,
396  cb,
397  cb_cls);
398  GNUNET_OS_init (cpd);
399 }
400 
401 
402 /* end of plugin.c */
char * getenv()
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.
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.
Definition: gnunet_common.h:96
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
#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:358
void * GNUNET_PLUGIN_unload(const char *library_name, void *arg)
Unload plugin (runs the "done" callback and returns whatever "done" returned).
Definition: plugin.c:241
enum GNUNET_GenericReturnValue GNUNET_PLUGIN_test(const char *library_name)
Test if a plugin exists.
Definition: plugin.c:167
void * GNUNET_PLUGIN_load(const char *library_name, void *arg)
Setup plugin (runs the "init" callback and returns whatever "init" returned).
Definition: plugin.c:197
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:385
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:140
static int find_libraries(void *cls, const char *filename)
Function called on each plugin in the directory.
Definition: plugin.c:320
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:287
const char * basename
Prefix the plugin names we find have to match.
Definition: plugin.c:291
void * cb_cls
Closure for cb.
Definition: plugin.c:306
void * arg
Argument to give to 'init' when loading the plugin.
Definition: plugin.c:296
GNUNET_PLUGIN_LoaderCallback cb
Function to call for each plugin.
Definition: plugin.c:301
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