aboutsummaryrefslogtreecommitdiff
path: root/src/main/extractor_plugpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/extractor_plugpath.c')
-rw-r--r--src/main/extractor_plugpath.c512
1 files changed, 314 insertions, 198 deletions
diff --git a/src/main/extractor_plugpath.c b/src/main/extractor_plugpath.c
index a47cb6c..949e22a 100644
--- a/src/main/extractor_plugpath.c
+++ b/src/main/extractor_plugpath.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of libextractor. 2 This file is part of libextractor.
3 (C) 2002, 2003, 2004, 2005, 2006, 2009 Vidyut Samanta and Christian Grothoff 3 (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian Grothoff
4 4
5 libextractor is free software; you can redistribute it and/or modify 5 libextractor is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -33,25 +33,36 @@
33#include "extractor_plugpath.h" 33#include "extractor_plugpath.h"
34 34
35/** 35/**
36 * Remove a trailing '/bin' from in (if present). 36 * Remove a trailing '/bin/' from 'in' (if present).
37 *
38 * @param in input string, modified
39 * @return NULL if 'in' is NULL, otherwise 'in' with '/bin/' removed
37 */ 40 */
38static char * 41static char *
39cut_bin(char * in) { 42cut_bin (char * in)
43{
40 size_t p; 44 size_t p;
41 45
42 if (in == NULL) 46 if (NULL == in)
43 return NULL; 47 return NULL;
44 p = strlen(in); 48 p = strlen (in);
45 if (p > 4) { 49 if (p < 4)
46 if ( (in[p-1] == '/') || 50 return in;
47 (in[p-1] == '\\') ) 51 if ( ('/' == in[p-1]) ||
48 in[--p] = '\0'; 52 ('\\' == in[p-1]) )
49 if (0 == strcmp(&in[p-3], 53 in[--p] = '\0';
50 "bin")) { 54 if (0 == strcmp (&in[p-4],
51 in[p-3] = '\0'; 55 "/bin"))
52 p -= 3; 56 {
57 in[p-4] = '\0';
58 p -= 4;
59 }
60 else if (0 == strcmp (&in[p-4],
61 "\bin"))
62 {
63 in[p-4] = '\0';
64 p -= 4;
53 } 65 }
54 }
55 return in; 66 return in;
56} 67}
57 68
@@ -64,208 +75,269 @@ cut_bin(char * in) {
64 * and the binary linking against it sits elsewhere. 75 * and the binary linking against it sits elsewhere.
65 */ 76 */
66static char * 77static char *
67get_path_from_proc_exe() { 78get_path_from_proc_exe ()
79{
68 char fn[64]; 80 char fn[64];
69 char line[1024]; 81 char line[1024];
70 char dir[1024]; 82 char dir[1024];
71 char * lnk; 83 char *lnk;
72 char * ret; 84 char *ret;
73 char * lestr; 85 char *lestr;
74 ssize_t size; 86 ssize_t size;
75 FILE * f; 87 FILE *f;
76 88
77 snprintf(fn, 89 snprintf (fn,
78 sizeof (fn), 90 sizeof (fn),
79 "/proc/%u/maps", 91 "/proc/%u/maps",
80 getpid()); 92 getpid ());
81 f = FOPEN(fn, "r"); 93 if (NULL != (f = FOPEN (fn, "r")))
82 if (f != NULL) { 94 {
83 while (NULL != fgets(line, 1024, f)) { 95 while (NULL != fgets (line, 1024, f))
84 if ( (1 == sscanf(line, 96 {
85 "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%s", 97 if ( (1 == sscanf (line,
86 dir)) && 98 "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%s",
87 (NULL != (lestr = strstr(dir, 99 dir)) &&
88 "libextractor")) ) ) { 100 (NULL != (lestr = strstr (dir,
89 lestr[0] = '\0'; 101 "libextractor")) ) )
90 fclose(f); 102 {
91 return strdup(dir); 103 lestr[0] = '\0';
92 } 104 fclose (f);
105 return strdup (dir);
106 }
107 }
108 fclose (f);
93 } 109 }
94 fclose(f); 110 snprintf (fn,
95 } 111 sizeof (fn),
96 snprintf(fn, 112 "/proc/%u/exe",
97 sizeof (fn), 113 getpid ());
98 "/proc/%u/exe", 114 if (NULL == (lnk = malloc (1029))) /* 1024 + 6 for "/lib/" catenation */
99 getpid());
100 lnk = malloc(1029); /* 1024 + 5 for "lib/" catenation */
101 if (lnk == NULL)
102 return NULL;
103 size = readlink(fn, lnk, 1023);
104 if ( (size <= 0) || (size >= 1024) ) {
105 free(lnk);
106 return NULL; 115 return NULL;
107 } 116 size = readlink (fn, lnk, 1023);
117 if ( (size <= 0) || (size >= 1024) )
118 {
119 free (lnk);
120 return NULL;
121 }
108 lnk[size] = '\0'; 122 lnk[size] = '\0';
109 while ( (lnk[size] != '/') && 123 while ( ('/' != lnk[size]) &&
110 (size > 0) ) 124 (size > 0) )
111 size--; 125 size--;
112 if ( (size < 4) || 126 if ( (size < 4) ||
113 (lnk[size-4] != '/') ) { 127 ('/' != lnk[size-4]) )
114 /* not installed in "/bin/" -- binary path probably useless */ 128 {
115 free(lnk); 129 /* not installed in "/bin/" -- binary path probably useless */
116 return NULL; 130 free (lnk);
117 } 131 return NULL;
132 }
118 lnk[size] = '\0'; 133 lnk[size] = '\0';
119 lnk = cut_bin(lnk); 134 lnk = cut_bin (lnk);
120 ret = realloc(lnk, strlen(lnk) + 5); 135 if (NULL == (ret = realloc (lnk, strlen(lnk) + 6)))
121 if (ret == NULL)
122 { 136 {
123 free (lnk); 137 free (lnk);
124 return NULL; 138 return NULL;
125 } 139 }
126 strcat(ret, "lib/"); /* guess "lib/" as the library dir */ 140 strcat (ret, "/lib/"); /* guess "lib/" as the library dir */
127 return ret; 141 return ret;
128} 142}
129#endif 143#endif
130 144
145
131#if WINDOWS 146#if WINDOWS
132/** 147/**
133 * Try to determine path with win32-specific function 148 * Try to determine path with win32-specific function
134 */ 149 */
135static char * 150static char *
136get_path_from_module_filename() { 151get_path_from_module_filename ()
137 char * path; 152{
138 char * ret; 153 char *path;
139 char * idx; 154 char *ret;
155 char *idx;
140 156
141 path = malloc(4103); /* 4096+nil+6 for "/lib/" catenation */ 157 if (NULL == (path = malloc (4103))) /* 4096+nil+6 for "/lib/" catenation */
142 if (path == NULL)
143 return NULL; 158 return NULL;
144 GetModuleFileName(NULL, path, 4096); 159 GetModuleFileName (NULL, path, 4096);
145 idx = path + strlen(path); 160 idx = path + strlen (path);
146 while ( (idx > path) && 161 while ( (idx > path) &&
147 (*idx != '\\') && 162 ('\\' != *idx) &&
148 (*idx != '/') ) 163 ('/' != *idx) )
149 idx--; 164 idx--;
150 *idx = '\0'; 165 *idx = '\0';
151 path = cut_bin(path); 166 path = cut_bin (path);
152 ret = realloc(path, strlen(path) + 6); 167 if (NULL == (ret = realloc (path, strlen(path) + 6)))
153 if (ret == NULL)
154 { 168 {
155 free (path); 169 free (path);
156 return NULL; 170 return NULL;
157 } 171 }
158 strcat(ret, "/lib/"); /* guess "lib/" as the library dir */ 172 strcat (ret, "/lib/"); /* guess "lib/" as the library dir */
159 return ret; 173 return ret;
160} 174}
161#endif 175#endif
162 176
177
163#if DARWIN 178#if DARWIN
164static char * get_path_from_dyld_image() { 179/**
165 const char * path; 180 * Signature of the '_NSGetExecutablePath" function.
166 char * p, * s; 181 *
167 int i; 182 * @param buf where to write the path
183 * @param number of bytes available in 'buf'
184 * @return 0 on success, otherwise desired number of bytes is stored in 'bufsize'
185 */
186typedef int (*MyNSGetExecutablePathProto) (char *buf,
187 size_t *bufsize);
188
189
190/**
191 * Try to obtain the path of our executable using '_NSGetExecutablePath'.
192 *
193 * @return NULL on error
194 */
195static char *
196get_path_from_NSGetExecutablePath ()
197{
198 static char zero;
199 char *path;
200 size_t len;
201 MyNSGetExecutablePathProto func;
202
203 path = NULL;
204 if (NULL == (func =
205 (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT,
206 "_NSGetExecutablePath")))
207 return NULL;
208 path = &zero;
209 len = 0;
210 /* get the path len, including the trailing \0 */
211 (void) func (path, &len);
212 if (0 == len)
213 return NULL;
214 path = GNUNET_malloc (len);
215 if (0 != func (path, &len))
216 {
217 GNUNET_free (path);
218 return NULL;
219 }
220 len = strlen (path);
221 while ((path[len] != '/') && (len > 0))
222 len--;
223 path[len] = '\0';
224 return path;
225}
226
227
228/**
229 * Try to obtain the path of our executable using '_dyld_image' API.
230 *
231 * @return NULL on error
232 */
233static char *
234get_path_from_dyld_image ()
235{
236 const char *path;
237 char *s;
238 unsigned int i;
168 int c; 239 int c;
169 240
170 p = NULL; 241 c = _dyld_image_count ();
171 c = _dyld_image_count(); 242 for (i = 0; i < c; i++)
172 for (i = 0; i < c; i++) { 243 {
173 if (_dyld_get_image_header(i) == &_mh_dylib_header) { 244 if (_dyld_get_image_header (i) != &_mh_dylib_header)
174 path = _dyld_get_image_name(i); 245 continue;
175 if (path != NULL && strlen(path) > 0) { 246 path = _dyld_get_image_name (i);
176 p = strdup(path); 247 if ( (NULL == path) || (0 == strlen (path)) )
177 if (p == NULL) 248 continue;
178 return NULL; 249 if (NULL == (p = strdup (path)))
179 s = p + strlen(p); 250 return NULL;
180 while ( (s > p) && (*s != '/') ) 251 s = p + strlen (p);
181 s--; 252 while ( (s > p) && ('/' != *s) )
182 s++; 253 s--;
183 *s = '\0'; 254 s++;
184 } 255 *s = '\0';
185 break; 256 return p;
186 } 257 }
187 } 258 return NULL;
188 return p;
189} 259}
190#endif 260#endif
191 261
262
192/** 263/**
193 * This may also fail -- for example, if extract 264 * Return the actual path to a file found in the current
194 * is not also installed. 265 * PATH environment variable.
266 *
267 * @return path to binary, NULL if not found
195 */ 268 */
196static char * 269static char *
197get_path_from_PATH() { 270get_path_from_PATH() {
198 struct stat sbuf; 271 struct stat sbuf;
199 char * path; 272 char *path;
200 char * pos; 273 char *pos;
201 char * end; 274 char *end;
202 char * buf; 275 char *buf;
203 char * ret; 276 char *ret;
204 const char * p; 277 const char *p;
205 278
206 p = getenv("PATH"); 279 if (NULL == (p = getenv ("PATH")))
207 if (p == NULL)
208 return NULL; 280 return NULL;
209 path = strdup(p); /* because we write on it */ 281 if (NULL == (path = strdup (p))) /* because we write on it */
210 if (path == NULL)
211 return NULL; 282 return NULL;
212 buf = malloc(strlen(path) + 20); 283 if (NULL == (buf = malloc (strlen(path) + 20)))
213 if (buf == NULL)
214 { 284 {
215 free (path); 285 free (path);
216 return NULL; 286 return NULL;
217 } 287 }
218 pos = path; 288 pos = path;
219 289 while (NULL != (end = strchr(pos, ':')))
220 while (NULL != (end = strchr(pos, ':'))) { 290 {
221 *end = '\0'; 291 *end = '\0';
222 sprintf(buf, "%s/%s", pos, "extract"); 292 sprintf(buf, "%s/%s", pos, "extract");
223 if (0 == stat(buf, &sbuf)) { 293 if (0 == stat(buf, &sbuf))
224 pos = strdup(pos); 294 {
225 free(buf); 295 pos = strdup(pos);
226 free(path); 296 free (buf);
227 if (pos == NULL) 297 free (path);
298 if (NULL == pos)
299 return NULL;
300 pos = cut_bin (pos);
301 if (NULL == (ret = realloc (pos, strlen(pos) + 5)))
302 {
303 free (pos);
304 return NULL;
305 }
306 strcat (ret, "lib/");
307 return ret;
308 }
309 pos = end + 1;
310 }
311 sprintf(buf, "%s/%s", pos, "extract");
312 if (0 == stat (buf, &sbuf))
313 {
314 pos = strdup (pos);
315 free (buf);
316 free (path);
317 if (NULL == pos)
228 return NULL; 318 return NULL;
229 pos = cut_bin(pos); 319 pos = cut_bin (pos);
230 ret = realloc(pos, strlen(pos) + 5); 320 ret = realloc (pos, strlen(pos) + 5);
231 if (ret == NULL) 321 if (NULL == ret)
232 { 322 {
233 free (pos); 323 free (pos);
234 return NULL; 324 return NULL;
235 } 325 }
236 strcat(ret, "lib/"); 326 strcat (ret, "lib/");
237 return ret; 327 return ret;
238 } 328 }
239 pos = end + 1;
240 }
241 sprintf(buf, "%s/%s", pos, "extract");
242 if (0 == stat(buf, &sbuf)) {
243 pos = strdup(pos);
244 free(buf);
245 free(path);
246 if (pos == NULL)
247 return NULL;
248 pos = cut_bin(pos);
249 ret = realloc(pos, strlen(pos) + 5);
250 if (ret == NULL)
251 {
252 free (pos);
253 return NULL;
254 }
255 strcat(ret, "lib/");
256 return ret;
257 }
258 free(buf); 329 free(buf);
259 free(path); 330 free(path);
260 return NULL; 331 return NULL;
261} 332}
262 333
334
263/** 335/**
264 * Create a filename by appending 'fname' to 'path'. 336 * Create a filename by appending 'fname' to 'path'.
265 * 337 *
266 * @param path the base path 338 * @param path the base path
267 * @param fname the filename to append 339 * @param fname the filename to append
268 * @return '$path/$fname' 340 * @return '$path/$fname', NULL on error
269 */ 341 */
270static char * 342static char *
271append_to_dir (const char *path, 343append_to_dir (const char *path,
@@ -274,16 +346,15 @@ append_to_dir (const char *path,
274 char *ret; 346 char *ret;
275 size_t slen; 347 size_t slen;
276 348
277 slen = strlen (path); 349 if (0 == (slen = strlen (path)))
278 if (slen == 0)
279 return NULL; 350 return NULL;
280 if (fname[0] == DIR_SEPARATOR) 351 if (DIR_SEPARATOR == fname[0])
281 fname++; 352 fname++;
282 ret = malloc (slen + strlen(fname) + 2); 353 ret = malloc (slen + strlen(fname) + 2);
283 if (ret == NULL) 354 if (NULL == ret)
284 return NULL; 355 return NULL;
285#ifdef MINGW 356#ifdef MINGW
286 if (path[slen-1] == '\\') 357 if ('\\' == path[slen-1])
287 sprintf (ret, 358 sprintf (ret,
288 "%s%s", 359 "%s%s",
289 path, 360 path,
@@ -294,16 +365,16 @@ append_to_dir (const char *path,
294 path, 365 path,
295 fname); 366 fname);
296#else 367#else
297 if (path[slen-1] == '/') 368 if ('/' == path[slen-1])
298 sprintf (ret, 369 sprintf (ret,
299 "%s%s", 370 "%s%s",
300 path, 371 path,
301 fname); 372 fname);
302 else 373 else
303 sprintf (ret, 374 sprintf (ret,
304 "%s/%s", 375 "%s/%s",
305 path, 376 path,
306 fname); 377 fname);
307#endif 378#endif
308 return ret; 379 return ret;
309} 380}
@@ -317,49 +388,47 @@ append_to_dir (const char *path,
317 * @param pp_cls cls argument for pp. 388 * @param pp_cls cls argument for pp.
318 */ 389 */
319void 390void
320get_installation_paths (PathProcessor pp, 391EXTRACTOR_get_installation_paths_ (EXTRACTOR_PathProcessor pp,
321 void *pp_cls) 392 void *pp_cls)
322{ 393{
323 const char *p; 394 const char *p;
324 char * path; 395 char *path;
325 char * prefix; 396 char *prefix;
326 char * d; 397 char *d;
327 398
328 prefix = NULL; 399 prefix = NULL;
329 p = getenv("LIBEXTRACTOR_PREFIX"); 400 if (NULL != (p = getenv ("LIBEXTRACTOR_PREFIX")))
330 if (p != NULL)
331 { 401 {
332 d = strdup (p); 402 if (NULL == (d = strdup (p)))
333 if (d == NULL)
334 return; 403 return;
335 prefix = strtok (d, PATH_SEPARATOR_STR); 404 for (prefix = strtok (d, PATH_SEPARATOR_STR);
336 while (NULL != prefix) 405 NULL != prefix;
337 { 406 prefix = strtok (NULL, PATH_SEPARATOR_STR))
338 pp (pp_cls, prefix); 407 pp (pp_cls, prefix);
339 prefix = strtok (NULL, PATH_SEPARATOR_STR);
340 }
341 free (d); 408 free (d);
342 return; 409 return;
343 } 410 }
344#if LINUX 411#if LINUX
345 if (prefix == NULL) 412 if (NULL == prefix)
346 prefix = get_path_from_proc_exe(); 413 prefix = get_path_from_proc_exe ();
347#endif 414#endif
348#if WINDOWS 415#if WINDOWS
349 if (prefix == NULL) 416 if (NULL == prefix)
350 prefix = get_path_from_module_filename(); 417 prefix = get_path_from_module_filename ();
351#endif 418#endif
352#if DARWIN 419#if DARWIN
353 if (prefix == NULL) 420 if (NULL == prefix)
354 prefix = get_path_from_dyld_image(); 421 prefix = get_path_from_NSGetExecutablePath ();
422 if (NULL == prefix)
423 prefix = get_path_from_dyld_image ();
355#endif 424#endif
356 if (prefix == NULL) 425 if (NULL == prefix)
357 prefix = get_path_from_PATH(); 426 prefix = get_path_from_PATH ();
358 pp (pp_cls, PLUGININSTDIR); 427 pp (pp_cls, PLUGININSTDIR);
359 if (prefix == NULL) 428 if (NULL == prefix)
360 return; 429 return;
361 path = append_to_dir (prefix, PLUGINDIR); 430 path = append_to_dir (prefix, PLUGINDIR);
362 if (path != NULL) 431 if (NULL != path)
363 { 432 {
364 if (0 != strcmp (path, 433 if (0 != strcmp (path,
365 PLUGININSTDIR)) 434 PLUGININSTDIR))
@@ -370,9 +439,19 @@ get_installation_paths (PathProcessor pp,
370} 439}
371 440
372 441
442/**
443 * Closure for 'find_plugin_in_path'.
444 */
373struct SearchContext 445struct SearchContext
374{ 446{
447 /**
448 * Name of the plugin we are looking for.
449 */
375 const char *short_name; 450 const char *short_name;
451
452 /**
453 * Location for storing the path to the plugin upon success.
454 */
376 char *path; 455 char *path;
377}; 456};
378 457
@@ -395,30 +474,28 @@ find_plugin_in_path (void *cls,
395 char *sym; 474 char *sym;
396 char *dot; 475 char *dot;
397 476
398 if (sc->path != NULL) 477 if (NULL != sc->path)
399 return; 478 return;
400 dir = OPENDIR (path); 479 if (NULL == (dir = OPENDIR (path)))
401 if (NULL == dir)
402 return; 480 return;
403 while (NULL != (ent = READDIR (dir))) 481 while (NULL != (ent = READDIR (dir)))
404 { 482 {
405 if (ent->d_name[0] == '.') 483 if ('.' == ent->d_name[0])
406 continue; 484 continue;
407 if ( (NULL != (la = strstr (ent->d_name, ".la"))) && 485 if ( (NULL != (la = strstr (ent->d_name, ".la"))) &&
408 (la[3] == '\0') ) 486 ('\0' == la[3]) )
409 continue; /* only load '.so' and '.dll' */ 487 continue; /* only load '.so' and '.dll' */
410 sym_name = strrchr (ent->d_name, '_'); 488 if (NULL == (sym_name = strrchr (ent->d_name, '_')))
411 if (sym_name == NULL)
412 continue; 489 continue;
413 sym_name++; 490 sym_name++;
414 sym = strdup (sym_name); 491 sym = strdup (sym_name);
415 if (sym == NULL) 492 if (NULL == sym)
416 { 493 {
417 CLOSEDIR (dir); 494 CLOSEDIR (dir);
418 return; 495 return;
419 } 496 }
420 dot = strchr (sym, '.'); 497 dot = strchr (sym, '.');
421 if (dot != NULL) 498 if (NULL != dot)
422 *dot = '\0'; 499 *dot = '\0';
423 if (0 == strcmp (sym, sc->short_name)) 500 if (0 == strcmp (sym, sc->short_name))
424 { 501 {
@@ -428,13 +505,6 @@ find_plugin_in_path (void *cls,
428 } 505 }
429 free (sym); 506 free (sym);
430 } 507 }
431#if DEBUG
432 if (sc->path == NULL)
433 fprintf (stderr,
434 "Failed to find plugin `%s' in `%s'\n",
435 sc->short_name,
436 path);
437#endif
438 CLOSEDIR (dir); 508 CLOSEDIR (dir);
439} 509}
440 510
@@ -444,7 +514,7 @@ find_plugin_in_path (void *cls,
444 * the full path of the respective plugin. 514 * the full path of the respective plugin.
445 */ 515 */
446char * 516char *
447find_plugin (const char *short_name) 517EXTRACTOR_find_plugin_ (const char *short_name)
448{ 518{
449 struct SearchContext sc; 519 struct SearchContext sc;
450 520
@@ -456,13 +526,30 @@ find_plugin (const char *short_name)
456} 526}
457 527
458 528
529/**
530 * Closure for 'load_plugins_from_dir'.
531 */
532struct DefaultLoaderContext
533{
534 /**
535 * Accumulated result list.
536 */
537 struct EXTRACTOR_PluginList *res;
538
539 /**
540 * Flags to use for all plugins.
541 */
542 enum EXTRACTOR_Options flags;
543};
544
545
459/** 546/**
460 * Load all plugins from the given directory. 547 * Load all plugins from the given directory.
461 * 548 *
462 * @param cls pointer to the "struct EXTRACTOR_PluginList*" to extend 549 * @param cls pointer to the "struct EXTRACTOR_PluginList*" to extend
463 * @param path path to a directory with plugins 550 * @param path path to a directory with plugins
464 */ 551 */
465void 552static void
466load_plugins_from_dir (void *cls, 553load_plugins_from_dir (void *cls,
467 const char *path) 554 const char *path)
468{ 555{
@@ -514,3 +601,32 @@ load_plugins_from_dir (void *cls,
514 closedir (dir); 601 closedir (dir);
515} 602}
516 603
604
605/**
606 * Load the default set of plugins. The default can be changed
607 * by setting the LIBEXTRACTOR_LIBRARIES environment variable.
608 * If it is set to "env", then this function will return
609 * EXTRACTOR_plugin_add_config (NULL, env, flags). Otherwise,
610 * it will load all of the installed plugins and return them.
611 *
612 * @param flags options for all of the plugins loaded
613 * @return the default set of plugins, NULL if no plugins were found
614 */
615struct EXTRACTOR_PluginList *
616EXTRACTOR_plugin_add_defaults (enum EXTRACTOR_Options flags)
617{
618 struct DefaultLoaderContext dlc;
619 char *env;
620
621 env = getenv ("LIBEXTRACTOR_LIBRARIES");
622 if (NULL != env)
623 return EXTRACTOR_plugin_add_config (NULL, env, flags);
624 dlc.res = NULL;
625 dlc.flags = flags;
626 get_installation_paths (&load_plugins_from_dir,
627 &dlc);
628 return dlc.res;
629}
630
631
632/* end of extractor_plugpath.c */