"Fossies" - the Fresh Open Source Software Archive 
Member "libextractor-1.11/src/main/extractor_plugins.c" (30 Jan 2021, 11165 Bytes) of package /linux/privat/libextractor-1.11.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "extractor_plugins.c" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
1.10_vs_1.11.
1 /*
2 This file is part of libextractor.
3 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009, 2012 Vidyut Samanta and Christian Grothoff
4
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
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 libextractor 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with libextractor; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20 /**
21 * @file main/extractor_plugins.c
22 * @brief code to load plugins
23 * @author Christian Grothoff
24 */
25 #include "extractor_plugins.h"
26 #include "extractor_plugpath.h"
27 #include "extractor_ipc.h"
28 #include "extractor_logging.h"
29
30
31 /**
32 * Try to resolve a plugin function.
33 *
34 * @param lib_handle library to search for the symbol
35 * @param prefix prefix to add
36 * @param sym_name base name for the symbol
37 * @param options set to special options requested by the plugin
38 * @return NULL on error, otherwise pointer to the symbol
39 */
40 static void *
41 get_symbol_with_prefix (void *lib_handle,
42 const char *template,
43 const char *prefix,
44 const char **options)
45 {
46 char *name;
47 void *symbol;
48 const char *sym_name;
49 char *sym;
50 char *dot;
51 const char *(*opt_fun)(void);
52
53 if (NULL != options)
54 *options = NULL;
55 if (NULL == (sym_name = strrchr (prefix, '_')))
56 return NULL;
57 sym_name++;
58 if (NULL == (sym = strdup (sym_name)))
59 {
60 LOG_STRERROR ("strdup");
61 return NULL;
62 }
63 if (NULL != (dot = strchr (sym, '.')))
64 *dot = '\0';
65 if (NULL == (name = malloc (strlen (sym) + strlen (template) + 1)))
66 {
67 free (sym);
68 return NULL;
69 }
70 sprintf (name,
71 template,
72 sym);
73 /* try without '_' first */
74 symbol = lt_dlsym (lib_handle, name + 1);
75 if (NULL == symbol)
76 {
77 /* now try with the '_' */
78 char *first_error = strdup (lt_dlerror ());
79 symbol = lt_dlsym (lib_handle, name);
80 if (NULL == symbol)
81 {
82 LOG ("Resolving symbol `%s' failed, "
83 "so I tried `%s', but that failed also. Errors are: "
84 "`%s' and `%s'.\n",
85 name + 1,
86 name,
87 first_error == NULL ? "out of memory" : first_error,
88 lt_dlerror ());
89 }
90 if (NULL != first_error)
91 free (first_error);
92 }
93
94 if ( (NULL != symbol) &&
95 (NULL != options) )
96 {
97 /* get special options */
98 sprintf (name,
99 "_EXTRACTOR_%s_options",
100 sym);
101 /* try without '_' first */
102 opt_fun = lt_dlsym (lib_handle, name + 1);
103 if (NULL == opt_fun)
104 opt_fun = lt_dlsym (lib_handle, name);
105 if (NULL != opt_fun)
106 *options = opt_fun ();
107 }
108 free (sym);
109 free (name);
110 return symbol;
111 }
112
113
114 /**
115 * Load a plugin.
116 *
117 * @param plugin plugin to load
118 * @return 0 on success, -1 on error
119 */
120 int
121 EXTRACTOR_plugin_load_ (struct EXTRACTOR_PluginList *plugin)
122 {
123 #if WINDOWS
124 wchar_t wlibname[4097];
125 char llibname[4097];
126 #endif
127 lt_dladvise advise;
128
129 if (EXTRACTOR_OPTION_DISABLED == plugin->flags)
130 return -1;
131 if (NULL == plugin->libname)
132 plugin->libname = EXTRACTOR_find_plugin_ (plugin->short_libname);
133 if (NULL == plugin->libname)
134 {
135 LOG ("Failed to find plugin `%s'\n",
136 plugin->short_libname);
137 plugin->flags = EXTRACTOR_OPTION_DISABLED;
138 return -1;
139 }
140 lt_dladvise_init (&advise);
141 lt_dladvise_ext (&advise);
142 lt_dladvise_local (&advise);
143 #if WINDOWS
144 wlibname[0] = L'\0';
145 llibname[0] = '\0';
146 if ( (MultiByteToWideChar (CP_UTF8, 0, plugin->libname, -1,
147 wlibname, sizeof (wlibname)) <= 0) ||
148 (WideCharToMultiByte (CP_ACP, 0, wlibname, -1,
149 llibname, sizeof (llibname), NULL, NULL) < 0) )
150 {
151 LOG ("Loading `%s' plugin failed: %s\n",
152 plugin->short_libname,
153 "can't convert plugin name to local encoding");
154 free (plugin->libname);
155 plugin->libname = NULL;
156 plugin->flags = EXTRACTOR_OPTION_DISABLED;
157 return -1;
158 }
159 plugin->libraryHandle = lt_dlopenadvise (llibname,
160 advise);
161 #else
162 plugin->libraryHandle = lt_dlopenadvise (plugin->libname,
163 advise);
164 #endif
165 lt_dladvise_destroy (&advise);
166 if (NULL == plugin->libraryHandle)
167 {
168 LOG ("Loading `%s' plugin failed (using name `%s'): %s\n",
169 plugin->short_libname,
170 plugin->libname,
171 lt_dlerror ());
172 free (plugin->libname);
173 plugin->libname = NULL;
174 plugin->flags = EXTRACTOR_OPTION_DISABLED;
175 return -1;
176 }
177 plugin->extract_method = get_symbol_with_prefix (plugin->libraryHandle,
178 "_EXTRACTOR_%s_extract_method",
179 plugin->libname,
180 &plugin->specials);
181 if (NULL == plugin->extract_method)
182 {
183 LOG ("Resolving `extract' method of plugin `%s' failed: %s\n",
184 plugin->short_libname,
185 lt_dlerror ());
186 lt_dlclose (plugin->libraryHandle);
187 free (plugin->libname);
188 plugin->libname = NULL;
189 plugin->flags = EXTRACTOR_OPTION_DISABLED;
190 return -1;
191 }
192 return 0;
193 }
194
195
196 /**
197 * Add a library for keyword extraction.
198 *
199 * @param prev the previous list of libraries, may be NULL
200 * @param library the name of the library
201 * @param options options to pass to the plugin
202 * @param flags options to use
203 * @return the new list of libraries, equal to prev iff an error occurred
204 */
205 struct EXTRACTOR_PluginList *
206 EXTRACTOR_plugin_add (struct EXTRACTOR_PluginList *prev,
207 const char *library,
208 const char *options,
209 enum EXTRACTOR_Options flags)
210 {
211 struct EXTRACTOR_PluginList *plugin;
212 struct EXTRACTOR_PluginList *pos;
213 char *libname;
214
215 for (pos = prev; NULL != pos; pos = pos->next)
216 if (0 == strcmp (pos->short_libname, library))
217 return prev;
218 /* no change, library already loaded */
219 if (NULL == (libname = EXTRACTOR_find_plugin_ (library)))
220 {
221 LOG ("Could not load plugin `%s'\n",
222 library);
223 return prev;
224 }
225 if (NULL == (plugin = malloc (sizeof (struct EXTRACTOR_PluginList))))
226 return prev;
227 memset (plugin, 0, sizeof (struct EXTRACTOR_PluginList));
228 plugin->next = prev;
229 if (NULL == (plugin->short_libname = strdup (library)))
230 {
231 free (plugin);
232 return NULL;
233 }
234 plugin->libname = libname;
235 plugin->flags = flags;
236 if (NULL != options)
237 plugin->plugin_options = strdup (options);
238 else
239 plugin->plugin_options = NULL;
240 plugin->seek_request = -1;
241 return plugin;
242 }
243
244
245 /**
246 * Load multiple libraries as specified by the user.
247 *
248 * @param config a string given by the user that defines which
249 * libraries should be loaded. Has the format
250 * "[[-]LIBRARYNAME[(options)][:[-]LIBRARYNAME[(options)]]]*".
251 * For example, 'mp3:ogg.so' loads the
252 * mp3 and the ogg library. The '-' before the LIBRARYNAME
253 * indicates that the library should be removed from
254 * the library list.
255 * @param prev the previous list of libraries, may be NULL
256 * @param flags options to use
257 * @return the new list of libraries, equal to prev iff an error occurred
258 * or if config was empty (or NULL).
259 */
260 struct EXTRACTOR_PluginList *
261 EXTRACTOR_plugin_add_config (struct EXTRACTOR_PluginList *prev,
262 const char *config,
263 enum EXTRACTOR_Options flags)
264 {
265 char *cpy;
266 size_t pos;
267 size_t last;
268 ssize_t lastconf;
269 size_t len;
270
271 if (NULL == config)
272 return prev;
273 if (NULL == (cpy = strdup (config)))
274 return prev;
275 len = strlen (config);
276 pos = 0;
277 last = 0;
278 lastconf = 0;
279 while (pos < len)
280 {
281 while ( (':' != cpy[pos]) &&
282 ('\0' != cpy[pos]) &&
283 ('(' != cpy[pos]) )
284 pos++;
285 switch (cpy[pos])
286 {
287 case '(':
288 cpy[pos++] = '\0'; /* replace '(' by termination */
289 lastconf = pos; /* start config from here, after (. */
290 while ( ('\0' != cpy[pos]) &&
291 (')' != cpy[pos]))
292 pos++; /* config until ) or EOS. */
293 if (')' == cpy[pos])
294 {
295 cpy[pos++] = '\0'; /* write end of config here. */
296 while ( (':' != cpy[pos]) &&
297 ('\0' != cpy[pos]) )
298 pos++; /* forward until real end of string found. */
299 cpy[pos++] = '\0';
300 }
301 else
302 {
303 cpy[pos++] = '\0'; /* end of string. */
304 }
305 break;
306 case ':':
307 case '\0':
308 lastconf = -1; /* NULL config when no (). */
309 cpy[pos++] = '\0'; /* replace ':' by termination */
310 break;
311 default:
312 ABORT ();
313 }
314 if ('-' == cpy[last])
315 {
316 last++;
317 prev = EXTRACTOR_plugin_remove (prev,
318 &cpy[last]);
319 }
320 else
321 {
322 prev = EXTRACTOR_plugin_add (prev,
323 &cpy[last],
324 (-1 != lastconf) ? &cpy[lastconf] : NULL,
325 flags);
326 }
327 last = pos;
328 }
329 free (cpy);
330 return prev;
331 }
332
333
334 /**
335 * Remove a plugin from a list.
336 *
337 * @param prev the current list of plugins
338 * @param library the name of the plugin to remove
339 * @return the reduced list, unchanged if the plugin was not loaded
340 */
341 struct EXTRACTOR_PluginList *
342 EXTRACTOR_plugin_remove (struct EXTRACTOR_PluginList *prev,
343 const char *library)
344 {
345 struct EXTRACTOR_PluginList *pos;
346 struct EXTRACTOR_PluginList *first;
347
348 pos = prev;
349 first = prev;
350 while ( (NULL != pos) &&
351 (0 != strcmp (pos->short_libname, library)) )
352 {
353 prev = pos;
354 pos = pos->next;
355 }
356 if (NULL == pos)
357 {
358 LOG ("Unloading plugin `%s' failed!\n",
359 library);
360 return first;
361 }
362 /* found, close library */
363 if (first == pos)
364 first = pos->next;
365 else
366 prev->next = pos->next;
367 if (NULL != pos->channel)
368 EXTRACTOR_IPC_channel_destroy_ (pos->channel);
369 if ( (NULL != pos->shm) &&
370 (0 == EXTRACTOR_IPC_shared_memory_change_rc_ (pos->shm, -1)) )
371 EXTRACTOR_IPC_shared_memory_destroy_ (pos->shm);
372 if (NULL != pos->short_libname)
373 free (pos->short_libname);
374 if (NULL != pos->libname)
375 free (pos->libname);
376 free (pos->plugin_options);
377 if (NULL != pos->libraryHandle)
378 lt_dlclose (pos->libraryHandle);
379 free (pos);
380 return first;
381 }
382
383
384 /**
385 * Remove all plugins from the given list (destroys the list).
386 *
387 * @param plugin the list of plugins
388 */
389 void
390 EXTRACTOR_plugin_remove_all (struct EXTRACTOR_PluginList *plugins)
391 {
392 while (NULL != plugins)
393 plugins = EXTRACTOR_plugin_remove (plugins, plugins->short_libname);
394 }
395
396
397 /* end of extractor_plugins.c */