GNUnet  0.19.2
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 
37 struct PluginList
38 {
42  struct PluginList *next;
43 
47  char *name;
48 
52  void *handle;
53 };
54 
55 
59 static int initialized;
60 
64 static char *old_dlsearchpath;
65 
69 static struct PluginList *plugins;
70 
71 
75 static 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 
119 static 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 
168 GNUNET_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 
197 void *
198 GNUNET_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 
241 void *
242 GNUNET_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 
320 static int
321 find_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 
358 void
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 
385 void
387  const char *basename,
388  void *arg,
390  void *cb_cls)
391 {
392  const struct GNUNET_OS_ProjectData *cpd = GNUNET_OS_project_data_get ();
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
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:813
#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.
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:359
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_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_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_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: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
const char * name
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