aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-03-26 16:20:17 +0000
committerChristian Grothoff <christian@grothoff.org>2012-03-26 16:20:17 +0000
commite005be81997d31fdc7e18a079e97ebe3fffe370d (patch)
treee8f80d9942a0c078dd51984b782d608060065b01
parent34b4812d8902ae2bb8ca2340ad51955a50e40ec0 (diff)
downloadlibextractor-e005be81997d31fdc7e18a079e97ebe3fffe370d.tar.gz
libextractor-e005be81997d31fdc7e18a079e97ebe3fffe370d.zip
-LRN: Divide-extractor.c.patch was the first thing i did, once i
realized that extractor.c is just too long.
-rw-r--r--src/main/Makefile.am2
-rw-r--r--src/main/extractor.c908
2 files changed, 4 insertions, 906 deletions
diff --git a/src/main/Makefile.am b/src/main/Makefile.am
index 916f1f6..a99dd90 100644
--- a/src/main/Makefile.am
+++ b/src/main/Makefile.am
@@ -36,6 +36,8 @@ libextractor_la_CPPFLAGS = -DPLUGINDIR=\"@RPLUGINDIR@\" -DPLUGININSTDIR=\"${plug
36 36
37libextractor_la_SOURCES = \ 37libextractor_la_SOURCES = \
38 extractor.c \ 38 extractor.c \
39 extractor_plugpath.c \
40 extractor_plugins.c \
39 extractor_metatypes.c \ 41 extractor_metatypes.c \
40 extractor_print.c 42 extractor_print.c
41 43
diff --git a/src/main/extractor.c b/src/main/extractor.c
index df75e21..17ba1d2 100644
--- a/src/main/extractor.c
+++ b/src/main/extractor.c
@@ -38,6 +38,8 @@
38#include <zlib.h> 38#include <zlib.h>
39#endif 39#endif
40 40
41#include "extractor_plugpath.h"
42#include "extractor_plugins.h"
41 43
42 44
43/** 45/**
@@ -65,912 +67,6 @@
65 67
66 68
67/** 69/**
68 * Linked list of extractor plugins. An application builds this list
69 * by telling libextractor to load various keyword-extraction
70 * plugins. Libraries can also be unloaded (removed from this list,
71 * see EXTRACTOR_plugin_remove).
72 */
73struct EXTRACTOR_PluginList
74{
75 /**
76 * This is a linked list.
77 */
78 struct EXTRACTOR_PluginList *next;
79
80 /**
81 * Pointer to the plugin (as returned by lt_dlopen).
82 */
83 void * libraryHandle;
84
85 /**
86 * Name of the library (i.e., 'libextractor_foo.so')
87 */
88 char *libname;
89
90 /**
91 * Name of the library (i.e., 'libextractor_foo.so')
92 */
93 char *short_libname;
94
95 /**
96 * Pointer to the function used for meta data extraction.
97 */
98 EXTRACTOR_ExtractMethod extractMethod;
99
100 /**
101 * Options for the plugin.
102 */
103 char * plugin_options;
104
105 /**
106 * Special options for the plugin
107 * (as returned by the plugin's "options" method;
108 * typically NULL).
109 */
110 const char *specials;
111
112 /**
113 * Flags to control how the plugin is executed.
114 */
115 enum EXTRACTOR_Options flags;
116
117 /**
118 * Process ID of the child process for this plugin. 0 for
119 * none.
120 */
121#ifndef WINDOWS
122 int cpid;
123#else
124 HANDLE hProcess;
125#endif
126
127 /**
128 * Pipe used to send information about shared memory segments to
129 * the child process. NULL if not initialized.
130 */
131 FILE *cpipe_in;
132
133 /**
134 * Pipe used to read information about extracted meta data from
135 * the child process. -1 if not initialized.
136 */
137 int cpipe_out;
138};
139
140
141/**
142 * Remove a trailing '/bin' from in (if present).
143 */
144static char *
145cut_bin(char * in) {
146 size_t p;
147
148 if (in == NULL)
149 return NULL;
150 p = strlen(in);
151 if (p > 4) {
152 if ( (in[p-1] == '/') ||
153 (in[p-1] == '\\') )
154 in[--p] = '\0';
155 if (0 == strcmp(&in[p-3],
156 "bin")) {
157 in[p-3] = '\0';
158 p -= 3;
159 }
160 }
161 return in;
162}
163
164#if LINUX
165/**
166 * Try to determine path by reading /proc/PID/exe or
167 * /proc/PID/maps.
168 *
169 * Note that this may fail if LE is installed in one directory
170 * and the binary linking against it sits elsewhere.
171 */
172static char *
173get_path_from_proc_exe() {
174 char fn[64];
175 char line[1024];
176 char dir[1024];
177 char * lnk;
178 char * ret;
179 char * lestr;
180 ssize_t size;
181 FILE * f;
182
183 snprintf(fn,
184 sizeof (fn),
185 "/proc/%u/maps",
186 getpid());
187 f = FOPEN(fn, "r");
188 if (f != NULL) {
189 while (NULL != fgets(line, 1024, f)) {
190 if ( (1 == sscanf(line,
191 "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%s",
192 dir)) &&
193 (NULL != (lestr = strstr(dir,
194 "libextractor")) ) ) {
195 lestr[0] = '\0';
196 fclose(f);
197 return strdup(dir);
198 }
199 }
200 fclose(f);
201 }
202 snprintf(fn,
203 sizeof (fn),
204 "/proc/%u/exe",
205 getpid());
206 lnk = malloc(1029); /* 1024 + 5 for "lib/" catenation */
207 if (lnk == NULL)
208 return NULL;
209 size = readlink(fn, lnk, 1023);
210 if ( (size <= 0) || (size >= 1024) ) {
211 free(lnk);
212 return NULL;
213 }
214 lnk[size] = '\0';
215 while ( (lnk[size] != '/') &&
216 (size > 0) )
217 size--;
218 if ( (size < 4) ||
219 (lnk[size-4] != '/') ) {
220 /* not installed in "/bin/" -- binary path probably useless */
221 free(lnk);
222 return NULL;
223 }
224 lnk[size] = '\0';
225 lnk = cut_bin(lnk);
226 ret = realloc(lnk, strlen(lnk) + 5);
227 if (ret == NULL)
228 {
229 free (lnk);
230 return NULL;
231 }
232 strcat(ret, "lib/"); /* guess "lib/" as the library dir */
233 return ret;
234}
235#endif
236
237#if WINDOWS
238/**
239 * Try to determine path with win32-specific function
240 */
241static char *
242get_path_from_module_filename() {
243 char * path;
244 char * ret;
245 char * idx;
246
247 path = malloc(4103); /* 4096+nil+6 for "/lib/" catenation */
248 if (path == NULL)
249 return NULL;
250 GetModuleFileName(NULL, path, 4096);
251 idx = path + strlen(path);
252 while ( (idx > path) &&
253 (*idx != '\\') &&
254 (*idx != '/') )
255 idx--;
256 *idx = '\0';
257 path = cut_bin(path);
258 ret = realloc(path, strlen(path) + 6);
259 if (ret == NULL)
260 {
261 free (path);
262 return NULL;
263 }
264 strcat(ret, "/lib/"); /* guess "lib/" as the library dir */
265 return ret;
266}
267#endif
268
269#if DARWIN
270static char * get_path_from_dyld_image() {
271 const char * path;
272 char * p, * s;
273 int i;
274 int c;
275
276 p = NULL;
277 c = _dyld_image_count();
278 for (i = 0; i < c; i++) {
279 if (_dyld_get_image_header(i) == &_mh_dylib_header) {
280 path = _dyld_get_image_name(i);
281 if (path != NULL && strlen(path) > 0) {
282 p = strdup(path);
283 if (p == NULL)
284 return NULL;
285 s = p + strlen(p);
286 while ( (s > p) && (*s != '/') )
287 s--;
288 s++;
289 *s = '\0';
290 }
291 break;
292 }
293 }
294 return p;
295}
296#endif
297
298/**
299 * This may also fail -- for example, if extract
300 * is not also installed.
301 */
302static char *
303get_path_from_PATH() {
304 struct stat sbuf;
305 char * path;
306 char * pos;
307 char * end;
308 char * buf;
309 char * ret;
310 const char * p;
311
312 p = getenv("PATH");
313 if (p == NULL)
314 return NULL;
315 path = strdup(p); /* because we write on it */
316 if (path == NULL)
317 return NULL;
318 buf = malloc(strlen(path) + 20);
319 if (buf == NULL)
320 {
321 free (path);
322 return NULL;
323 }
324 pos = path;
325
326 while (NULL != (end = strchr(pos, ':'))) {
327 *end = '\0';
328 sprintf(buf, "%s/%s", pos, "extract");
329 if (0 == stat(buf, &sbuf)) {
330 pos = strdup(pos);
331 free(buf);
332 free(path);
333 if (pos == NULL)
334 return NULL;
335 pos = cut_bin(pos);
336 ret = realloc(pos, strlen(pos) + 5);
337 if (ret == NULL)
338 {
339 free (pos);
340 return NULL;
341 }
342 strcat(ret, "lib/");
343 return ret;
344 }
345 pos = end + 1;
346 }
347 sprintf(buf, "%s/%s", pos, "extract");
348 if (0 == stat(buf, &sbuf)) {
349 pos = strdup(pos);
350 free(buf);
351 free(path);
352 if (pos == NULL)
353 return NULL;
354 pos = cut_bin(pos);
355 ret = realloc(pos, strlen(pos) + 5);
356 if (ret == NULL)
357 {
358 free (pos);
359 return NULL;
360 }
361 strcat(ret, "lib/");
362 return ret;
363 }
364 free(buf);
365 free(path);
366 return NULL;
367}
368
369
370/**
371 * Function to call on paths.
372 *
373 * @param cls closure
374 * @param path a directory path
375 */
376typedef void (*PathProcessor)(void *cls,
377 const char *path);
378
379
380/**
381 * Create a filename by appending 'fname' to 'path'.
382 *
383 * @param path the base path
384 * @param fname the filename to append
385 * @return '$path/$fname'
386 */
387static char *
388append_to_dir (const char *path,
389 const char *fname)
390{
391 char *ret;
392 size_t slen;
393
394 slen = strlen (path);
395 if (slen == 0)
396 return NULL;
397 if (fname[0] == DIR_SEPARATOR)
398 fname++;
399 ret = malloc (slen + strlen(fname) + 2);
400 if (ret == NULL)
401 return NULL;
402#ifdef MINGW
403 if (path[slen-1] == '\\')
404 sprintf (ret,
405 "%s%s",
406 path,
407 fname);
408 else
409 sprintf (ret,
410 "%s\\%s",
411 path,
412 fname);
413#else
414 if (path[slen-1] == '/')
415 sprintf (ret,
416 "%s%s",
417 path,
418 fname);
419 else
420 sprintf (ret,
421 "%s/%s",
422 path,
423 fname);
424#endif
425 return ret;
426}
427
428
429/**
430 * Iterate over all paths where we expect to find GNU libextractor
431 * plugins.
432 *
433 * @param pp function to call for each path
434 * @param pp_cls cls argument for pp.
435 */
436static void
437get_installation_paths (PathProcessor pp,
438 void *pp_cls)
439{
440 const char *p;
441 char * path;
442 char * prefix;
443 char * d;
444
445 prefix = NULL;
446 p = getenv("LIBEXTRACTOR_PREFIX");
447 if (p != NULL)
448 {
449 d = strdup (p);
450 if (d == NULL)
451 return;
452 prefix = strtok (d, PATH_SEPARATOR_STR);
453 while (NULL != prefix)
454 {
455 pp (pp_cls, prefix);
456 prefix = strtok (NULL, PATH_SEPARATOR_STR);
457 }
458 free (d);
459 return;
460 }
461#if LINUX
462 if (prefix == NULL)
463 prefix = get_path_from_proc_exe();
464#endif
465#if WINDOWS
466 if (prefix == NULL)
467 prefix = get_path_from_module_filename();
468#endif
469#if DARWIN
470 if (prefix == NULL)
471 prefix = get_path_from_dyld_image();
472#endif
473 if (prefix == NULL)
474 prefix = get_path_from_PATH();
475 pp (pp_cls, PLUGININSTDIR);
476 if (prefix == NULL)
477 return;
478 path = append_to_dir (prefix, PLUGINDIR);
479 if (path != NULL)
480 {
481 if (0 != strcmp (path,
482 PLUGININSTDIR))
483 pp (pp_cls, path);
484 free (path);
485 }
486 free (prefix);
487}
488
489
490struct SearchContext
491{
492 const char *short_name;
493 char *path;
494};
495
496
497/**
498 * Load all plugins from the given directory.
499 *
500 * @param cls pointer to the "struct EXTRACTOR_PluginList*" to extend
501 * @param path path to a directory with plugins
502 */
503static void
504find_plugin_in_path (void *cls,
505 const char *path)
506{
507 struct SearchContext *sc = cls;
508 DIR *dir;
509 struct dirent *ent;
510 const char *la;
511 const char *sym_name;
512 char *sym;
513 char *dot;
514
515 if (sc->path != NULL)
516 return;
517 dir = OPENDIR (path);
518 if (NULL == dir)
519 return;
520 while (NULL != (ent = READDIR (dir)))
521 {
522 if (ent->d_name[0] == '.')
523 continue;
524 if ( (NULL != (la = strstr (ent->d_name, ".la"))) &&
525 (la[3] == '\0') )
526 continue; /* only load '.so' and '.dll' */
527 sym_name = strstr (ent->d_name, "_");
528 if (sym_name == NULL)
529 continue;
530 sym_name++;
531 sym = strdup (sym_name);
532 if (sym == NULL)
533 {
534 CLOSEDIR (dir);
535 return;
536 }
537 dot = strstr (sym, ".");
538 if (dot != NULL)
539 *dot = '\0';
540 if (0 == strcmp (sym, sc->short_name))
541 {
542 sc->path = append_to_dir (path, ent->d_name);
543 free (sym);
544 break;
545 }
546 free (sym);
547 }
548#if DEBUG
549 if (sc->path == NULL)
550 fprintf (stderr,
551 "Failed to find plugin `%s' in `%s'\n",
552 sc->short_name,
553 path);
554#endif
555 CLOSEDIR (dir);
556}
557
558
559
560/**
561 * Given a short name of a library (i.e. "mime"), find
562 * the full path of the respective plugin.
563 */
564static char *
565find_plugin (const char *short_name)
566{
567 struct SearchContext sc;
568
569 sc.path = NULL;
570 sc.short_name = short_name;
571 get_installation_paths (&find_plugin_in_path,
572 &sc);
573 return sc.path;
574}
575
576
577
578struct DefaultLoaderContext
579{
580 struct EXTRACTOR_PluginList *res;
581 enum EXTRACTOR_Options flags;
582};
583
584
585/**
586 * Load all plugins from the given directory.
587 *
588 * @param cls pointer to the "struct EXTRACTOR_PluginList*" to extend
589 * @param path path to a directory with plugins
590 */
591static void
592load_plugins_from_dir (void *cls,
593 const char *path)
594{
595 struct DefaultLoaderContext *dlc = cls;
596 DIR *dir;
597 struct dirent *ent;
598 const char *la;
599 const char *sym_name;
600 char *sym;
601 char *dot;
602
603 dir = opendir (path);
604 if (NULL == dir)
605 return;
606 while (NULL != (ent = readdir (dir)))
607 {
608 if (ent->d_name[0] == '.')
609 continue;
610 if ( ( (NULL != (la = strstr (ent->d_name, ".la"))) &&
611 (la[3] == '\0') ) ||
612 ( (NULL != (la = strstr (ent->d_name, ".a"))) &&
613 (la[2] == '\0')) )
614 continue; /* only load '.so' and '.dll' */
615
616 sym_name = strstr (ent->d_name, "_");
617 if (sym_name == NULL)
618 continue;
619 sym_name++;
620 sym = strdup (sym_name);
621 if (NULL == sym)
622 {
623 closedir (dir);
624 return;
625 }
626 dot = strstr (sym, ".");
627 if (dot != NULL)
628 *dot = '\0';
629#if DEBUG > 1
630 fprintf (stderr,
631 "Adding default plugin `%s'\n",
632 sym);
633#endif
634 dlc->res = EXTRACTOR_plugin_add (dlc->res,
635 sym,
636 NULL,
637 dlc->flags);
638 free (sym);
639 }
640 closedir (dir);
641}
642
643
644/**
645 * Load the default set of plugins. The default can be changed
646 * by setting the LIBEXTRACTOR_LIBRARIES environment variable.
647 * If it is set to "env", then this function will return
648 * EXTRACTOR_plugin_add_config (NULL, env, flags). Otherwise,
649 * it will load all of the installed plugins and return them.
650 *
651 * @param flags options for all of the plugins loaded
652 * @return the default set of plugins, NULL if no plugins were found
653 */
654struct EXTRACTOR_PluginList *
655EXTRACTOR_plugin_add_defaults(enum EXTRACTOR_Options flags)
656{
657 struct DefaultLoaderContext dlc;
658 char *env;
659
660 env = getenv ("LIBEXTRACTOR_LIBRARIES");
661 if (env != NULL)
662 return EXTRACTOR_plugin_add_config (NULL, env, flags);
663 dlc.res = NULL;
664 dlc.flags = flags;
665 get_installation_paths (&load_plugins_from_dir,
666 &dlc);
667 return dlc.res;
668}
669
670
671/**
672 * Try to resolve a plugin function.
673 *
674 * @param lib_handle library to search for the symbol
675 * @param prefix prefix to add
676 * @param sym_name base name for the symbol
677 * @param options set to special options requested by the plugin
678 * @return NULL on error, otherwise pointer to the symbol
679 */
680static void *
681get_symbol_with_prefix(void *lib_handle,
682 const char *template,
683 const char *prefix,
684 const char **options)
685{
686 char *name;
687 void *symbol;
688 const char *sym_name;
689 char *sym;
690 char *dot;
691 const char *(*opt_fun)(void);
692
693 if (NULL != options) *options = NULL;
694 sym_name = strstr (prefix, "_");
695 if (sym_name == NULL)
696 return NULL;
697 sym_name++;
698 sym = strdup (sym_name);
699 if (sym == NULL)
700 return NULL;
701 dot = strstr (sym, ".");
702 if (dot != NULL)
703 *dot = '\0';
704 name = malloc(strlen(sym) + strlen(template) + 1);
705 if (name == NULL)
706 {
707 free (sym);
708 return NULL;
709 }
710 sprintf(name,
711 template,
712 sym);
713 /* try without '_' first */
714 symbol = lt_dlsym(lib_handle, name + 1);
715 if (symbol==NULL)
716 {
717 /* now try with the '_' */
718#if DEBUG
719 char *first_error = strdup (lt_dlerror());
720#endif
721 symbol = lt_dlsym(lib_handle, name);
722#if DEBUG
723 if (NULL == symbol)
724 {
725 fprintf(stderr,
726 "Resolving symbol `%s' failed, "
727 "so I tried `%s', but that failed also. Errors are: "
728 "`%s' and `%s'.\n",
729 name+1,
730 name,
731 first_error == NULL ? "out of memory" : first_error,
732 lt_dlerror());
733 }
734 if (first_error != NULL)
735 free(first_error);
736#endif
737 }
738
739 if ( (symbol != NULL) &&
740 (NULL != options) )
741 {
742 /* get special options */
743 sprintf(name,
744 "_EXTRACTOR_%s_options",
745 sym);
746 /* try without '_' first */
747 opt_fun = lt_dlsym(lib_handle, name + 1);
748 if (opt_fun == NULL)
749 opt_fun = lt_dlsym(lib_handle, name);
750 if (opt_fun != NULL)
751 *options = opt_fun ();
752 }
753 free (sym);
754 free(name);
755
756 return symbol;
757}
758
759
760/**
761 * Load a plugin.
762 *
763 * @param plugin plugin to load
764 * @return 0 on success, -1 on error
765 */
766static int
767plugin_load (struct EXTRACTOR_PluginList *plugin)
768{
769#if WINDOWS
770 wchar_t wlibname[4097];
771 char llibname[4097];
772#endif
773 lt_dladvise advise;
774
775 if (plugin->libname == NULL)
776 plugin->libname = find_plugin (plugin->short_libname);
777 if (plugin->libname == NULL)
778 {
779#if DEBUG
780 fprintf (stderr,
781 "Failed to find plugin `%s'\n",
782 plugin->short_libname);
783#endif
784 plugin->flags = EXTRACTOR_OPTION_DISABLED;
785 return -1;
786 }
787 lt_dladvise_init (&advise);
788 lt_dladvise_ext (&advise);
789 lt_dladvise_local (&advise);
790#if WINDOWS
791 wlibname[0] = L'\0';
792 llibname[0] = '\0';
793 if (MultiByteToWideChar (CP_UTF8, 0, plugin->libname, -1, wlibname, 4097) <= 0
794 || WideCharToMultiByte (CP_ACP, 0, wlibname, -1, llibname, 4097, NULL, NULL) < 0)
795 {
796#if DEBUG
797 fprintf (stderr,
798 "Loading `%s' plugin failed: %s\n",
799 plugin->short_libname,
800 "can't convert plugin name to local encoding");
801 free (plugin->libname);
802 plugin->libname = NULL;
803 plugin->flags = EXTRACTOR_OPTION_DISABLED;
804 return -1;
805#endif
806 }
807 plugin->libraryHandle = lt_dlopenadvise (llibname,
808 advise);
809#else
810 plugin->libraryHandle = lt_dlopenadvise (plugin->libname,
811 advise);
812#endif
813 lt_dladvise_destroy(&advise);
814 if (plugin->libraryHandle == NULL)
815 {
816#if DEBUG
817 fprintf (stderr,
818 "Loading `%s' plugin failed: %s\n",
819 plugin->short_libname,
820 lt_dlerror ());
821#endif
822 free (plugin->libname);
823 plugin->libname = NULL;
824 plugin->flags = EXTRACTOR_OPTION_DISABLED;
825 return -1;
826 }
827 plugin->extractMethod = get_symbol_with_prefix (plugin->libraryHandle,
828 "_EXTRACTOR_%s_extract",
829 plugin->libname,
830 &plugin->specials);
831 if (plugin->extractMethod == NULL)
832 {
833#if DEBUG
834 fprintf (stderr,
835 "Resolving `extract' method of plugin `%s' failed: %s\n",
836 plugin->short_libname,
837 lt_dlerror ());
838#endif
839 lt_dlclose (plugin->libraryHandle);
840 free (plugin->libname);
841 plugin->libname = NULL;
842 plugin->flags = EXTRACTOR_OPTION_DISABLED;
843 return -1;
844 }
845 return 0;
846}
847
848
849
850
851/**
852 * Add a library for keyword extraction.
853 *
854 * @param prev the previous list of libraries, may be NULL
855 * @param library the name of the library
856 * @param flags options to use
857 * @return the new list of libraries, equal to prev iff an error occured
858 */
859struct EXTRACTOR_PluginList *
860EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList * prev,
861 const char *library,
862 const char *options,
863 enum EXTRACTOR_Options flags)
864{
865 struct EXTRACTOR_PluginList *result;
866 char *libname;
867
868 libname = find_plugin (library);
869 if (libname == NULL)
870 {
871 fprintf (stderr,
872 "Could not load `%s'\n",
873 library);
874 return prev;
875 }
876 result = calloc (1, sizeof (struct EXTRACTOR_PluginList));
877 if (result == NULL)
878 return prev;
879 result->next = prev;
880 result->short_libname = strdup (library);
881 if (result->short_libname == NULL)
882 {
883 free (result);
884 return NULL;
885 }
886 result->libname = libname;
887 result->flags = flags;
888 if (NULL != options)
889 result->plugin_options = strdup (options);
890 else
891 result->plugin_options = NULL;
892 return result;
893}
894
895
896/**
897 * Load multiple libraries as specified by the user.
898 *
899 * @param config a string given by the user that defines which
900 * libraries should be loaded. Has the format
901 * "[[-]LIBRARYNAME[(options)][:[-]LIBRARYNAME[(options)]]]*".
902 * For example, 'mp3:ogg.so' loads the
903 * mp3 and the ogg library. The '-' before the LIBRARYNAME
904 * indicates that the library should be removed from
905 * the library list.
906 * @param prev the previous list of libraries, may be NULL
907 * @param flags options to use
908 * @return the new list of libraries, equal to prev iff an error occured
909 * or if config was empty (or NULL).
910 */
911struct EXTRACTOR_PluginList *
912EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList * prev,
913 const char *config,
914 enum EXTRACTOR_Options flags)
915{
916 char *cpy;
917 size_t pos;
918 size_t last;
919 ssize_t lastconf;
920 size_t len;
921
922 if (config == NULL)
923 return prev;
924 len = strlen(config);
925 cpy = strdup(config);
926 if (cpy == NULL)
927 return prev;
928 pos = 0;
929 last = 0;
930 lastconf = 0;
931 while (pos < len)
932 {
933 while ((cpy[pos] != ':') && (cpy[pos] != '\0') &&
934 (cpy[pos] != '('))
935 pos++;
936 if( cpy[pos] == '(' ) {
937 cpy[pos++] = '\0'; /* replace '(' by termination */
938 lastconf = pos; /* start config from here, after (. */
939 while ((cpy[pos] != '\0') && (cpy[pos] != ')'))
940 pos++; /* config until ) or EOS. */
941 if( cpy[pos] == ')' ) {
942 cpy[pos++] = '\0'; /* write end of config here. */
943 while ((cpy[pos] != ':') && (cpy[pos] != '\0'))
944 pos++; /* forward until real end of string found. */
945 cpy[pos++] = '\0';
946 } else {
947 cpy[pos++] = '\0'; /* end of string. */
948 }
949 } else {
950 lastconf = -1; /* NULL config when no (). */
951 cpy[pos++] = '\0'; /* replace ':' by termination */
952 }
953 if (cpy[last] == '-')
954 {
955 last++;
956 prev = EXTRACTOR_plugin_remove (prev,
957 &cpy[last]);
958 }
959 else
960 {
961 prev = EXTRACTOR_plugin_add (prev,
962 &cpy[last],
963 (lastconf != -1) ? &cpy[lastconf] : NULL,
964 flags);
965 }
966 last = pos;
967 }
968 free (cpy);
969 return prev;
970}
971
972
973/**
974 * Stop the child process of this plugin. 70 * Stop the child process of this plugin.
975 */ 71 */
976static void 72static void