diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-11-03 15:24:08 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-11-03 15:24:08 +0000 |
commit | 84a70da19fdf98b028b98e23a228e32f591535fe (patch) | |
tree | 3fde202b9a1d16c4594c25f5a64dea15e989a160 /src | |
parent | 7ae7229d2de6a6ef842634265847a46ac46f8c5c (diff) | |
download | gnunet-84a70da19fdf98b028b98e23a228e32f591535fe.tar.gz gnunet-84a70da19fdf98b028b98e23a228e32f591535fe.zip |
implementing plugin directory scanner for #1746
Diffstat (limited to 'src')
-rw-r--r-- | src/include/gnunet_plugin_lib.h | 35 | ||||
-rw-r--r-- | src/util/plugin.c | 82 | ||||
-rw-r--r-- | src/util/test_plugin.c | 13 |
3 files changed, 130 insertions, 0 deletions
diff --git a/src/include/gnunet_plugin_lib.h b/src/include/gnunet_plugin_lib.h index d143a6ccf..ff795d975 100644 --- a/src/include/gnunet_plugin_lib.h +++ b/src/include/gnunet_plugin_lib.h | |||
@@ -62,6 +62,7 @@ typedef void *(*GNUNET_PLUGIN_Callback) (void *arg); | |||
62 | int | 62 | int |
63 | GNUNET_PLUGIN_test (const char *library_name); | 63 | GNUNET_PLUGIN_test (const char *library_name); |
64 | 64 | ||
65 | |||
65 | /** | 66 | /** |
66 | * Setup plugin (runs the "init" callback and returns whatever "init" | 67 | * Setup plugin (runs the "init" callback and returns whatever "init" |
67 | * returned). If "init" returns NULL, the plugin is unloaded. | 68 | * returned). If "init" returns NULL, the plugin is unloaded. |
@@ -79,6 +80,40 @@ GNUNET_PLUGIN_load (const char *library_name, void *arg); | |||
79 | 80 | ||
80 | 81 | ||
81 | /** | 82 | /** |
83 | * Signature of a function called by 'GNUNET_PLUGIN_load_all'. | ||
84 | * | ||
85 | * @param cls closure | ||
86 | * @param library_name full name of the library (to be used with | ||
87 | * 'GNUNET_PLUGIN_unload') | ||
88 | * @param lib_ret return value from the initialization function | ||
89 | * of the library (same as what 'GNUNET_PLUGIN_load' would | ||
90 | * have returned for the given library name) | ||
91 | */ | ||
92 | typedef void (*GNUNET_PLUGIN_LoaderCallback)(void *cls, | ||
93 | const char *library_name, | ||
94 | void *lib_ret); | ||
95 | |||
96 | |||
97 | /** | ||
98 | * Load all compatible plugins with the given base name. | ||
99 | * | ||
100 | * Note that the library must export symbols called | ||
101 | * "basename_ANYTHING_init" and "basename_ANYTHING__done". These will | ||
102 | * be called when the library is loaded and unloaded respectively. | ||
103 | * | ||
104 | * @param basename basename of the plugins to load | ||
105 | * @param arg argument to the plugin initialization function | ||
106 | * @param cb function to call for each plugin found | ||
107 | * @param cb_cls closure for 'cb' | ||
108 | */ | ||
109 | void | ||
110 | GNUNET_PLUGIN_load_all (const char *basename, | ||
111 | void *arg, | ||
112 | GNUNET_PLUGIN_LoaderCallback cb, | ||
113 | void *cb_cls); | ||
114 | |||
115 | |||
116 | /** | ||
82 | * Unload plugin (runs the "done" callback and returns whatever "done" | 117 | * Unload plugin (runs the "done" callback and returns whatever "done" |
83 | * returned). The plugin is then unloaded. | 118 | * returned). The plugin is then unloaded. |
84 | * | 119 | * |
diff --git a/src/util/plugin.c b/src/util/plugin.c index 77631410c..dffc8ecd6 100644 --- a/src/util/plugin.c +++ b/src/util/plugin.c | |||
@@ -284,5 +284,87 @@ GNUNET_PLUGIN_unload (const char *library_name, void *arg) | |||
284 | } | 284 | } |
285 | 285 | ||
286 | 286 | ||
287 | struct LoadAllContext | ||
288 | { | ||
289 | const char *basename; | ||
290 | void *arg; | ||
291 | GNUNET_PLUGIN_LoaderCallback cb; | ||
292 | void *cb_cls; | ||
293 | }; | ||
294 | |||
295 | |||
296 | static int | ||
297 | find_libraries (void *cls, | ||
298 | const char *filename) | ||
299 | { | ||
300 | struct LoadAllContext *lac = cls; | ||
301 | const char *slashpos; | ||
302 | const char *libname; | ||
303 | char *basename; | ||
304 | char *dot; | ||
305 | void *lib_ret; | ||
306 | size_t n; | ||
307 | |||
308 | libname = filename; | ||
309 | while (NULL != (slashpos = strstr (libname, DIR_SEPARATOR_STR))) | ||
310 | libname = slashpos + 1; | ||
311 | n = strlen (libname); | ||
312 | if (0 != strncmp (lac->basename, | ||
313 | libname, | ||
314 | strlen (lac->basename))) | ||
315 | return GNUNET_OK; /* wrong name */ | ||
316 | if ( (n > 3) && | ||
317 | (0 == strcmp (&libname[n-3], | ||
318 | ".la")) ) | ||
319 | return GNUNET_OK; /* .la file */ | ||
320 | basename = GNUNET_strdup (libname); | ||
321 | if (NULL != (dot = strstr (basename, "."))) | ||
322 | *dot = '\0'; | ||
323 | lib_ret = GNUNET_PLUGIN_load (basename, lac->arg); | ||
324 | if (NULL != lib_ret) | ||
325 | lac->cb (lac->cb_cls, basename, lib_ret); | ||
326 | GNUNET_free (basename); | ||
327 | return GNUNET_OK; | ||
328 | } | ||
329 | |||
330 | |||
331 | /** | ||
332 | * Load all compatible plugins with the given base name. | ||
333 | * | ||
334 | * Note that the library must export symbols called | ||
335 | * "basename_ANYTHING_init" and "basename_ANYTHING__done". These will | ||
336 | * be called when the library is loaded and unloaded respectively. | ||
337 | * | ||
338 | * @param basename basename of the plugins to load | ||
339 | * @param arg argument to the plugin initialization function | ||
340 | * @param cb function to call for each plugin found | ||
341 | * @param cb_cls closure for 'cb' | ||
342 | */ | ||
343 | void | ||
344 | GNUNET_PLUGIN_load_all (const char *basename, | ||
345 | void *arg, | ||
346 | GNUNET_PLUGIN_LoaderCallback cb, | ||
347 | void *cb_cls) | ||
348 | { | ||
349 | struct LoadAllContext lac; | ||
350 | char *path; | ||
351 | |||
352 | path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR); | ||
353 | if (path == NULL) | ||
354 | { | ||
355 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
356 | _("Could not determine plugin installation path.\n")); | ||
357 | return; | ||
358 | } | ||
359 | lac.basename = basename; | ||
360 | lac.arg = arg; | ||
361 | lac.cb = cb; | ||
362 | lac.cb_cls = cb_cls; | ||
363 | GNUNET_DISK_directory_scan (path, | ||
364 | &find_libraries, | ||
365 | &lac); | ||
366 | GNUNET_free (path); | ||
367 | } | ||
368 | |||
287 | 369 | ||
288 | /* end of plugin.c */ | 370 | /* end of plugin.c */ |
diff --git a/src/util/test_plugin.c b/src/util/test_plugin.c index 479edb3cb..dc34841f5 100644 --- a/src/util/test_plugin.c +++ b/src/util/test_plugin.c | |||
@@ -26,6 +26,17 @@ | |||
26 | 26 | ||
27 | #define VERBOSE GNUNET_EXTRA_LOGGING | 27 | #define VERBOSE GNUNET_EXTRA_LOGGING |
28 | 28 | ||
29 | static void | ||
30 | test_cb (void *cls, | ||
31 | const char *libname, | ||
32 | void *lib_ret) | ||
33 | { | ||
34 | GNUNET_assert (0 == strcmp (cls, "test")); | ||
35 | GNUNET_assert (0 == strcmp (lib_ret, "Hello")); | ||
36 | GNUNET_assert (0 == strcmp (GNUNET_PLUGIN_unload (libname, "out"), "World")); | ||
37 | } | ||
38 | |||
39 | |||
29 | static int | 40 | static int |
30 | check () | 41 | check () |
31 | { | 42 | { |
@@ -47,6 +58,8 @@ check () | |||
47 | if (0 != strcmp (ret, "World")) | 58 | if (0 != strcmp (ret, "World")) |
48 | return 4; | 59 | return 4; |
49 | free (ret); | 60 | free (ret); |
61 | |||
62 | GNUNET_PLUGIN_load_all ("libgnunet_plugin_tes", "in", &test_cb, "test"); | ||
50 | return 0; | 63 | return 0; |
51 | } | 64 | } |
52 | 65 | ||