1 | /* ltdl.c -- system independent dlopen wrapper
|
---|
2 | Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
|
---|
3 | Originally by Thomas Tanner <tanner@ffii.org>
|
---|
4 | This file is part of GNU Libtool.
|
---|
5 |
|
---|
6 | This library is free software; you can redistribute it and/or
|
---|
7 | modify it under the terms of the GNU Lesser General Public
|
---|
8 | License as published by the Free Software Foundation; either
|
---|
9 | version 2 of the License, or (at your option) any later version.
|
---|
10 |
|
---|
11 | As a special exception to the GNU Lesser General Public License,
|
---|
12 | if you distribute this file as part of a program or library that
|
---|
13 | is built using GNU libtool, you may include it under the same
|
---|
14 | distribution terms that you use for the rest of that program.
|
---|
15 |
|
---|
16 | This library is distributed in the hope that it will be useful,
|
---|
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
19 | Lesser General Public License for more details.
|
---|
20 |
|
---|
21 | You should have received a copy of the GNU Lesser General Public
|
---|
22 | License along with this library; if not, write to the Free Software
|
---|
23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
---|
24 | 02111-1307 USA
|
---|
25 |
|
---|
26 | */
|
---|
27 |
|
---|
28 | #define _LTDL_COMPILE_
|
---|
29 |
|
---|
30 | #if HAVE_CONFIG_H
|
---|
31 | #include <config.h>
|
---|
32 | #endif
|
---|
33 |
|
---|
34 | #if HAVE_STRING_H
|
---|
35 | #include <string.h>
|
---|
36 | #endif
|
---|
37 |
|
---|
38 | #if HAVE_STRINGS_H
|
---|
39 | #include <strings.h>
|
---|
40 | #endif
|
---|
41 |
|
---|
42 | #if HAVE_CTYPE_H
|
---|
43 | #include <ctype.h>
|
---|
44 | #endif
|
---|
45 |
|
---|
46 | #if HAVE_MALLOC_H
|
---|
47 | #include <malloc.h>
|
---|
48 | #endif
|
---|
49 |
|
---|
50 | #if HAVE_MEMORY_H
|
---|
51 | #include <memory.h>
|
---|
52 | #endif
|
---|
53 |
|
---|
54 | #if HAVE_STDLIB_H
|
---|
55 | #include <stdlib.h>
|
---|
56 | #endif
|
---|
57 |
|
---|
58 | #if HAVE_STDIO_H
|
---|
59 | #include <stdio.h>
|
---|
60 | #endif
|
---|
61 |
|
---|
62 | #if HAVE_BOEHM_GC
|
---|
63 | #include <gc.h>
|
---|
64 | #endif
|
---|
65 |
|
---|
66 | #include "ltdl.h"
|
---|
67 |
|
---|
68 | #ifdef DLL_EXPORT
|
---|
69 | # define LTDL_GLOBAL_DATA __declspec(dllexport)
|
---|
70 | #else
|
---|
71 | # define LTDL_GLOBAL_DATA
|
---|
72 | #endif
|
---|
73 |
|
---|
74 | /* max. filename length */
|
---|
75 | #ifndef LTDL_FILENAME_MAX
|
---|
76 | #define LTDL_FILENAME_MAX 1024
|
---|
77 | #endif
|
---|
78 |
|
---|
79 | #undef LTDL_READTEXT_MODE
|
---|
80 | /* fopen() mode flags for reading a text file */
|
---|
81 | #ifdef _WIN32
|
---|
82 | #define LTDL_READTEXT_MODE "rt"
|
---|
83 | #else
|
---|
84 | #define LTDL_READTEXT_MODE "r"
|
---|
85 | #endif
|
---|
86 |
|
---|
87 | #undef LTDL_SYMBOL_LENGTH
|
---|
88 | /* This is the maximum symbol size that won't require malloc/free */
|
---|
89 | #define LTDL_SYMBOL_LENGTH 128
|
---|
90 |
|
---|
91 | #undef LTDL_SYMBOL_OVERHEAD
|
---|
92 | /* This accounts for the _LTX_ separator */
|
---|
93 | #define LTDL_SYMBOL_OVERHEAD 5
|
---|
94 |
|
---|
95 | /* NOTE: typedefed in ltdl.h
|
---|
96 | This structure is used for the list of registered loaders. */
|
---|
97 | struct lt_dlloader_t {
|
---|
98 | struct lt_dlloader_t *next;
|
---|
99 | const char *loader_name; /* identifying name for each loader */
|
---|
100 | const char *sym_prefix; /* prefix for symbols */
|
---|
101 | lt_module_open_t *module_open;
|
---|
102 | lt_module_close_t *module_close;
|
---|
103 | lt_find_sym_t *find_sym;
|
---|
104 | lt_dlloader_exit_t *dlloader_exit;
|
---|
105 | lt_dlloader_data_t dlloader_data;
|
---|
106 | };
|
---|
107 |
|
---|
108 | typedef struct lt_dlhandle_t {
|
---|
109 | struct lt_dlhandle_t *next;
|
---|
110 | lt_dlloader_t *loader; /* dlopening interface */
|
---|
111 | lt_dlinfo info;
|
---|
112 | int depcount; /* number of dependencies */
|
---|
113 | lt_dlhandle *deplibs; /* dependencies */
|
---|
114 | lt_module_t module; /* system module handle */
|
---|
115 | lt_ptr_t system; /* system specific data */
|
---|
116 | lt_ptr_t app_private; /* application private data */
|
---|
117 | } lt_dlhandle_t;
|
---|
118 |
|
---|
119 | static const char objdir[] = LTDL_OBJDIR;
|
---|
120 | #ifdef LTDL_SHLIB_EXT
|
---|
121 | static const char shlib_ext[] = LTDL_SHLIB_EXT;
|
---|
122 | #endif
|
---|
123 | #ifdef LTDL_SYSSEARCHPATH
|
---|
124 | static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
|
---|
125 | #endif
|
---|
126 |
|
---|
127 | /* Extract the diagnostic strings from the error table macro in the same
|
---|
128 | order as the enumberated indices in ltdl.h. */
|
---|
129 | #define LTDL_ERROR(name, diagnostic) (diagnostic),
|
---|
130 | static const char *ltdl_error_strings[] = {
|
---|
131 | ltdl_error_table
|
---|
132 | 0
|
---|
133 | };
|
---|
134 | #undef LTDL_ERROR
|
---|
135 |
|
---|
136 | #ifdef __STDC__
|
---|
137 | # define LT_DLSTRERROR(name) ltdl_error_strings[LTDL_ERROR_##name]
|
---|
138 | #else
|
---|
139 | # define LT_DLSTRERROR(name) ltdl_error_strings[LTDL_ERROR_/**/name]
|
---|
140 | #endif
|
---|
141 |
|
---|
142 | static const char *last_error = 0;
|
---|
143 |
|
---|
144 | LTDL_GLOBAL_DATA lt_ptr_t (*lt_dlmalloc) LTDL_PARAMS((size_t size)) = (lt_ptr_t(*)LTDL_PARAMS((size_t)))malloc;
|
---|
145 | LTDL_GLOBAL_DATA void (*lt_dlfree) LTDL_PARAMS((lt_ptr_t ptr)) = (void(*)LTDL_PARAMS((lt_ptr_t)))free;
|
---|
146 |
|
---|
147 | #undef strdup
|
---|
148 | #define strdup xstrdup
|
---|
149 |
|
---|
150 | static inline char *
|
---|
151 | strdup(str)
|
---|
152 | const char *str;
|
---|
153 | {
|
---|
154 | char *tmp;
|
---|
155 |
|
---|
156 | if (!str)
|
---|
157 | return 0;
|
---|
158 | tmp = (char*) lt_dlmalloc(strlen(str)+1);
|
---|
159 | if (tmp)
|
---|
160 | strcpy(tmp, str);
|
---|
161 | return tmp;
|
---|
162 | }
|
---|
163 |
|
---|
164 | #if ! HAVE_STRCMP
|
---|
165 |
|
---|
166 | #undef strcmp
|
---|
167 | #define strcmp xstrcmp
|
---|
168 |
|
---|
169 | static inline int
|
---|
170 | strcmp (str1, str2)
|
---|
171 | const char *str1;
|
---|
172 | const char *str2;
|
---|
173 | {
|
---|
174 | if (str1 == str2)
|
---|
175 | return 0;
|
---|
176 | if (str1 == 0)
|
---|
177 | return -1;
|
---|
178 | if (str2 == 0)
|
---|
179 | return 1;
|
---|
180 |
|
---|
181 | for (;*str1 && *str2; str1++, str2++)
|
---|
182 | if (*str1 != *str2)
|
---|
183 | break;
|
---|
184 |
|
---|
185 | return (int)(*str1 - *str2);
|
---|
186 | }
|
---|
187 | #endif
|
---|
188 |
|
---|
189 |
|
---|
190 | #if ! HAVE_STRCHR
|
---|
191 |
|
---|
192 | # if HAVE_INDEX
|
---|
193 |
|
---|
194 | # define strchr index
|
---|
195 |
|
---|
196 | # else
|
---|
197 |
|
---|
198 | # define strchr xstrchr
|
---|
199 |
|
---|
200 | static inline const char*
|
---|
201 | strchr(str, ch)
|
---|
202 | const char *str;
|
---|
203 | int ch;
|
---|
204 | {
|
---|
205 | const char *p;
|
---|
206 |
|
---|
207 | for (p = str; *p != (char)ch && *p != '\0'; p++)
|
---|
208 | /*NOWORK*/;
|
---|
209 |
|
---|
210 | return (*p == (char)ch) ? p : 0;
|
---|
211 | }
|
---|
212 |
|
---|
213 | # endif
|
---|
214 |
|
---|
215 | #endif
|
---|
216 |
|
---|
217 | #if ! HAVE_STRRCHR
|
---|
218 |
|
---|
219 | # if HAVE_RINDEX
|
---|
220 |
|
---|
221 | # define strrchr rindex
|
---|
222 |
|
---|
223 | # else
|
---|
224 |
|
---|
225 | # define strrchr xstrrchr
|
---|
226 |
|
---|
227 | static inline const char*
|
---|
228 | strrchr(str, ch)
|
---|
229 | const char *str;
|
---|
230 | int ch;
|
---|
231 | {
|
---|
232 | const char *p;
|
---|
233 |
|
---|
234 | for (p = str; *p != '\0'; p++)
|
---|
235 | /*NOWORK*/;
|
---|
236 |
|
---|
237 | while (*p != (char)ch && p >= str)
|
---|
238 | p--;
|
---|
239 |
|
---|
240 | return (*p == (char)ch) ? p : 0;
|
---|
241 | }
|
---|
242 |
|
---|
243 | # endif
|
---|
244 |
|
---|
245 | #endif
|
---|
246 |
|
---|
247 | /* The Cygwin dlopen implementation prints a spurious error message to
|
---|
248 | stderr if its call to LoadLibrary() fails for any reason. We can
|
---|
249 | mitigate this by not using the Cygwin implementation, and falling
|
---|
250 | back to our own LoadLibrary() wrapper. */
|
---|
251 | #if HAVE_LIBDL && !defined(__CYGWIN__)
|
---|
252 |
|
---|
253 | /* dynamic linking with dlopen/dlsym */
|
---|
254 |
|
---|
255 | #if HAVE_DLFCN_H
|
---|
256 | # include <dlfcn.h>
|
---|
257 | #endif
|
---|
258 |
|
---|
259 | #ifdef RTLD_GLOBAL
|
---|
260 | # define LTDL_GLOBAL RTLD_GLOBAL
|
---|
261 | #else
|
---|
262 | # ifdef DL_GLOBAL
|
---|
263 | # define LTDL_GLOBAL DL_GLOBAL
|
---|
264 | # else
|
---|
265 | # define LTDL_GLOBAL 0
|
---|
266 | # endif
|
---|
267 | #endif
|
---|
268 |
|
---|
269 | /* We may have to define LTDL_LAZY_OR_NOW in the command line if we
|
---|
270 | find out it does not work in some platform. */
|
---|
271 | #ifndef LTDL_LAZY_OR_NOW
|
---|
272 | # ifdef RTLD_LAZY
|
---|
273 | # define LTDL_LAZY_OR_NOW RTLD_LAZY
|
---|
274 | # else
|
---|
275 | # ifdef DL_LAZY
|
---|
276 | # define LTDL_LAZY_OR_NOW DL_LAZY
|
---|
277 | # else
|
---|
278 | # ifdef RTLD_NOW
|
---|
279 | # define LTDL_LAZY_OR_NOW RTLD_NOW
|
---|
280 | # else
|
---|
281 | # ifdef DL_NOW
|
---|
282 | # define LTDL_LAZY_OR_NOW DL_NOW
|
---|
283 | # else
|
---|
284 | # define LTDL_LAZY_OR_NOW 0
|
---|
285 | # endif
|
---|
286 | # endif
|
---|
287 | # endif
|
---|
288 | # endif
|
---|
289 | #endif
|
---|
290 |
|
---|
291 | static lt_module_t
|
---|
292 | sys_dl_open (loader_data, filename)
|
---|
293 | lt_dlloader_data_t loader_data;
|
---|
294 | const char *filename;
|
---|
295 | {
|
---|
296 | lt_module_t module = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW);
|
---|
297 | if (!module) {
|
---|
298 | #if HAVE_DLERROR
|
---|
299 | last_error = dlerror();
|
---|
300 | #else
|
---|
301 | last_error = LT_DLSTRERROR(CANNOT_OPEN);
|
---|
302 | #endif
|
---|
303 | }
|
---|
304 | return module;
|
---|
305 | }
|
---|
306 |
|
---|
307 | static int
|
---|
308 | sys_dl_close (loader_data, module)
|
---|
309 | lt_dlloader_data_t loader_data;
|
---|
310 | lt_module_t module;
|
---|
311 | {
|
---|
312 | if (dlclose(module) != 0) {
|
---|
313 | #if HAVE_DLERROR
|
---|
314 | last_error = dlerror();
|
---|
315 | #else
|
---|
316 | last_error = LT_DLSTRERROR(CANNOT_CLOSE);
|
---|
317 | #endif
|
---|
318 | return 1;
|
---|
319 | }
|
---|
320 | return 0;
|
---|
321 | }
|
---|
322 |
|
---|
323 | static lt_ptr_t
|
---|
324 | sys_dl_sym (loader_data, module, symbol)
|
---|
325 | lt_dlloader_data_t loader_data;
|
---|
326 | lt_module_t module;
|
---|
327 | const char *symbol;
|
---|
328 | {
|
---|
329 | lt_ptr_t address = dlsym(module, symbol);
|
---|
330 |
|
---|
331 | if (!address)
|
---|
332 | #if HAVE_DLERROR
|
---|
333 | last_error = dlerror();
|
---|
334 | #else
|
---|
335 | last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
|
---|
336 | #endif
|
---|
337 | return address;
|
---|
338 | }
|
---|
339 |
|
---|
340 | static struct lt_user_dlloader sys_dl = {
|
---|
341 | # ifdef NEED_USCORE
|
---|
342 | "_",
|
---|
343 | # else
|
---|
344 | 0,
|
---|
345 | # endif
|
---|
346 | sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
|
---|
347 | #endif
|
---|
348 |
|
---|
349 | #if HAVE_SHL_LOAD
|
---|
350 |
|
---|
351 | /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
|
---|
352 |
|
---|
353 | #ifdef HAVE_DL_H
|
---|
354 | #include <dl.h>
|
---|
355 | #endif
|
---|
356 |
|
---|
357 | /* some flags are missing on some systems, so we provide
|
---|
358 | * harmless defaults.
|
---|
359 | *
|
---|
360 | * Mandatory:
|
---|
361 | * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
|
---|
362 | * BIND_DEFERRED - Delay code symbol resolution until actual reference.
|
---|
363 | *
|
---|
364 | * Optionally:
|
---|
365 | * BIND_FIRST - Place the library at the head of the symbol search order.
|
---|
366 | * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all unsatisfied
|
---|
367 | * symbols as fatal. This flag allows binding of unsatisfied code
|
---|
368 | * symbols to be deferred until use.
|
---|
369 | * [Perl: For certain libraries, like DCE, deferred binding often
|
---|
370 | * causes run time problems. Adding BIND_NONFATAL to BIND_IMMEDIATE
|
---|
371 | * still allows unresolved references in situations like this.]
|
---|
372 | * BIND_NOSTART - Do not call the initializer for the shared library when the
|
---|
373 | * library is loaded, nor on a future call to shl_unload().
|
---|
374 | * BIND_VERBOSE - Print verbose messages concerning possible unsatisfied symbols.
|
---|
375 | *
|
---|
376 | * hp9000s700/hp9000s800:
|
---|
377 | * BIND_RESTRICTED - Restrict symbols visible by the library to those present at
|
---|
378 | * library load time.
|
---|
379 | * DYNAMIC_PATH - Allow the loader to dynamically search for the library specified
|
---|
380 | * by the path argument.
|
---|
381 | */
|
---|
382 |
|
---|
383 | #ifndef DYNAMIC_PATH
|
---|
384 | #define DYNAMIC_PATH 0
|
---|
385 | #endif /* DYNAMIC_PATH */
|
---|
386 | #ifndef BIND_RESTRICTED
|
---|
387 | #define BIND_RESTRICTED 0
|
---|
388 | #endif /* BIND_RESTRICTED */
|
---|
389 |
|
---|
390 | #define LTDL_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
|
---|
391 |
|
---|
392 | static lt_module_t
|
---|
393 | sys_shl_open (loader_data, filename)
|
---|
394 | lt_dlloader_data_t loader_data;
|
---|
395 | const char *filename;
|
---|
396 | {
|
---|
397 | lt_module_t module = shl_load(filename, LTDL_BIND_FLAGS, 0L);
|
---|
398 | if (!module) {
|
---|
399 | last_error = LT_DLSTRERROR(CANNOT_OPEN);
|
---|
400 | }
|
---|
401 | return module;
|
---|
402 | }
|
---|
403 |
|
---|
404 | static int
|
---|
405 | sys_shl_close (loader_data, module)
|
---|
406 | lt_dlloader_data_t loader_data;
|
---|
407 | lt_module_t module;
|
---|
408 | {
|
---|
409 | if (shl_unload((shl_t) (module)) != 0) {
|
---|
410 | last_error = LT_DLSTRERROR(CANNOT_CLOSE);
|
---|
411 | return 1;
|
---|
412 | }
|
---|
413 | return 0;
|
---|
414 | }
|
---|
415 |
|
---|
416 | static lt_ptr_t
|
---|
417 | sys_shl_sym (loader_data, module, symbol)
|
---|
418 | lt_dlloader_data_t loader_data;
|
---|
419 | lt_module_t module;
|
---|
420 | const char *symbol;
|
---|
421 | {
|
---|
422 | lt_ptr_t address;
|
---|
423 |
|
---|
424 | if (module && shl_findsym((shl_t*) &module,
|
---|
425 | symbol, TYPE_UNDEFINED, &address) == 0)
|
---|
426 | if (address)
|
---|
427 | return address;
|
---|
428 | last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
|
---|
429 | return 0;
|
---|
430 | }
|
---|
431 |
|
---|
432 | static struct lt_user_dlloader
|
---|
433 | sys_shl = { 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 };
|
---|
434 |
|
---|
435 | #undef LTDL_TYPE_TOP
|
---|
436 | #define LTDL_TYPE_TOP &sys_shl
|
---|
437 |
|
---|
438 | #endif
|
---|
439 |
|
---|
440 | #ifdef _WIN32
|
---|
441 |
|
---|
442 | /* dynamic linking for Win32 */
|
---|
443 |
|
---|
444 | #include <windows.h>
|
---|
445 |
|
---|
446 | /* Forward declaration; required to implement handle search below. */
|
---|
447 | static lt_dlhandle handles;
|
---|
448 |
|
---|
449 | static lt_module_t
|
---|
450 | sys_wll_open (loader_data, filename)
|
---|
451 | lt_dlloader_data_t loader_data;
|
---|
452 | const char *filename;
|
---|
453 | {
|
---|
454 | lt_dlhandle cur;
|
---|
455 | lt_module_t module;
|
---|
456 | char *searchname = 0;
|
---|
457 | char *ext;
|
---|
458 | char self_name_buf[MAX_PATH];
|
---|
459 |
|
---|
460 | if (!filename) {
|
---|
461 | /* Get the name of main module */
|
---|
462 | *self_name_buf = 0;
|
---|
463 | GetModuleFileName(NULL, self_name_buf, sizeof(self_name_buf));
|
---|
464 | filename = ext = self_name_buf;
|
---|
465 | }
|
---|
466 | else ext = strrchr(filename, '.');
|
---|
467 |
|
---|
468 | if (ext) {
|
---|
469 | /* FILENAME already has an extension. */
|
---|
470 | searchname = strdup(filename);
|
---|
471 | } else {
|
---|
472 | /* Append a `.' to stop Windows from adding an
|
---|
473 | implicit `.dll' extension. */
|
---|
474 | searchname = (char*)lt_dlmalloc(2+ strlen(filename));
|
---|
475 | if (!searchname) {
|
---|
476 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
477 | return 0;
|
---|
478 | }
|
---|
479 | strcpy(searchname, filename);
|
---|
480 | strcat(searchname, ".");
|
---|
481 | }
|
---|
482 |
|
---|
483 | module = LoadLibrary(searchname);
|
---|
484 | lt_dlfree(searchname);
|
---|
485 |
|
---|
486 | /* libltdl expects this function to fail if it is unable
|
---|
487 | to physically load the library. Sadly, LoadLibrary
|
---|
488 | will search the loaded libraries for a match and return
|
---|
489 | one of them if the path search load fails.
|
---|
490 |
|
---|
491 | We check whether LoadLibrary is returning a handle to
|
---|
492 | an already loaded module, and simulate failure if we
|
---|
493 | find one. */
|
---|
494 | cur = handles;
|
---|
495 | while (cur) {
|
---|
496 | if (!cur->module) {
|
---|
497 | cur = 0;
|
---|
498 | break;
|
---|
499 | }
|
---|
500 | if (cur->module == module)
|
---|
501 | break;
|
---|
502 | cur = cur->next;
|
---|
503 | }
|
---|
504 |
|
---|
505 | if (cur || !module) {
|
---|
506 | last_error = LT_DLSTRERROR(CANNOT_OPEN);
|
---|
507 | return 0;
|
---|
508 | }
|
---|
509 |
|
---|
510 | return module;
|
---|
511 | }
|
---|
512 |
|
---|
513 | static int
|
---|
514 | sys_wll_close (loader_data, module)
|
---|
515 | lt_dlloader_data_t loader_data;
|
---|
516 | lt_module_t module;
|
---|
517 | {
|
---|
518 | if (FreeLibrary(module) == 0) {
|
---|
519 | last_error = LT_DLSTRERROR(CANNOT_CLOSE);
|
---|
520 | return 1;
|
---|
521 | }
|
---|
522 | return 0;
|
---|
523 | }
|
---|
524 |
|
---|
525 | static lt_ptr_t
|
---|
526 | sys_wll_sym (loader_data, module, symbol)
|
---|
527 | lt_dlloader_data_t loader_data;
|
---|
528 | lt_module_t module;
|
---|
529 | const char *symbol;
|
---|
530 | {
|
---|
531 | lt_ptr_t address = GetProcAddress(module, symbol);
|
---|
532 |
|
---|
533 | if (!address)
|
---|
534 | last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
|
---|
535 | return address;
|
---|
536 | }
|
---|
537 |
|
---|
538 | static struct lt_user_dlloader
|
---|
539 | sys_wll = { 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 };
|
---|
540 |
|
---|
541 | #endif
|
---|
542 |
|
---|
543 | #ifdef __BEOS__
|
---|
544 |
|
---|
545 | /* dynamic linking for BeOS */
|
---|
546 |
|
---|
547 | #include <kernel/image.h>
|
---|
548 |
|
---|
549 | static lt_module_t
|
---|
550 | sys_bedl_open (loader_data, filename)
|
---|
551 | lt_dlloader_data_t loader_data;
|
---|
552 | const char *filename;
|
---|
553 | {
|
---|
554 | image_id image = 0;
|
---|
555 |
|
---|
556 | if (filename) {
|
---|
557 | image = load_add_on(filename);
|
---|
558 | } else {
|
---|
559 | image_info info;
|
---|
560 | int32 cookie = 0;
|
---|
561 | if (get_next_image_info(0, &cookie, &info) == B_OK)
|
---|
562 | image = load_add_on(info.name);
|
---|
563 | }
|
---|
564 | if (image <= 0) {
|
---|
565 | last_error = LT_DLSTRERROR(CANNOT_OPEN);
|
---|
566 | return 0;
|
---|
567 | }
|
---|
568 |
|
---|
569 | return (lt_module_t) image;
|
---|
570 | }
|
---|
571 |
|
---|
572 | static int
|
---|
573 | sys_bedl_close (loader_data, module)
|
---|
574 | lt_dlloader_data_t loader_data;
|
---|
575 | lt_module_t module;
|
---|
576 | {
|
---|
577 | if (unload_add_on((image_id)module) != B_OK) {
|
---|
578 | last_error = LT_DLSTRERROR(CANNOT_CLOSE);
|
---|
579 | return 1;
|
---|
580 | }
|
---|
581 | return 0;
|
---|
582 | }
|
---|
583 |
|
---|
584 | static lt_ptr_t
|
---|
585 | sys_bedl_sym (loader_data, module, symbol)
|
---|
586 | lt_dlloader_data_t loader_data;
|
---|
587 | lt_module_t module;
|
---|
588 | const char *symbol;
|
---|
589 | {
|
---|
590 | lt_ptr_t address = 0;
|
---|
591 | image_id image = (image_id)module;
|
---|
592 |
|
---|
593 | if (get_image_symbol(image, symbol, B_SYMBOL_TYPE_ANY,
|
---|
594 | &address) != B_OK) {
|
---|
595 | last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
|
---|
596 | return 0;
|
---|
597 | }
|
---|
598 | return address;
|
---|
599 | }
|
---|
600 |
|
---|
601 | static struct lt_user_dlloader
|
---|
602 | sys_bedl = { 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 };
|
---|
603 |
|
---|
604 | #endif
|
---|
605 |
|
---|
606 | #if HAVE_DLD
|
---|
607 |
|
---|
608 | /* dynamic linking with dld */
|
---|
609 |
|
---|
610 | #if HAVE_DLD_H
|
---|
611 | #include <dld.h>
|
---|
612 | #endif
|
---|
613 |
|
---|
614 | static lt_module_t
|
---|
615 | sys_dld_open (loader_data, filename)
|
---|
616 | lt_dlloader_data_t loader_data;
|
---|
617 | const char *filename;
|
---|
618 | {
|
---|
619 | lt_module_t module = strdup(filename);
|
---|
620 | if (!module) {
|
---|
621 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
622 | return 0;
|
---|
623 | }
|
---|
624 | if (dld_link(filename) != 0) {
|
---|
625 | last_error = LT_DLSTRERROR(CANNOT_OPEN);
|
---|
626 | lt_dlfree(module);
|
---|
627 | return 0;
|
---|
628 | }
|
---|
629 | return module;
|
---|
630 | }
|
---|
631 |
|
---|
632 | static int
|
---|
633 | sys_dld_close (loader_data, module)
|
---|
634 | lt_dlloader_data_t loader_data;
|
---|
635 | lt_module_t module;
|
---|
636 | {
|
---|
637 | if (dld_unlink_by_file((char*)(module), 1) != 0) {
|
---|
638 | last_error = LT_DLSTRERROR(CANNOT_CLOSE);
|
---|
639 | return 1;
|
---|
640 | }
|
---|
641 | lt_dlfree(module);
|
---|
642 | return 0;
|
---|
643 | }
|
---|
644 |
|
---|
645 | static lt_ptr_t
|
---|
646 | sys_dld_sym (loader_data, module, symbol)
|
---|
647 | lt_dlloader_data_t loader_data;
|
---|
648 | lt_module_t module;
|
---|
649 | const char *symbol;
|
---|
650 | {
|
---|
651 | lt_ptr_t address = dld_get_func(symbol);
|
---|
652 |
|
---|
653 | if (!address)
|
---|
654 | last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
|
---|
655 | return address;
|
---|
656 | }
|
---|
657 |
|
---|
658 | static struct lt_user_dlloader
|
---|
659 | sys_dld = { 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 };
|
---|
660 |
|
---|
661 | #endif
|
---|
662 |
|
---|
663 | /* emulate dynamic linking using preloaded_symbols */
|
---|
664 |
|
---|
665 | typedef struct lt_dlsymlists_t {
|
---|
666 | struct lt_dlsymlists_t *next;
|
---|
667 | const lt_dlsymlist *syms;
|
---|
668 | } lt_dlsymlists_t;
|
---|
669 |
|
---|
670 | static const lt_dlsymlist *default_preloaded_symbols = 0;
|
---|
671 | static lt_dlsymlists_t *preloaded_symbols = 0;
|
---|
672 |
|
---|
673 | static int
|
---|
674 | presym_init (loader_data)
|
---|
675 | lt_dlloader_data_t loader_data;
|
---|
676 | {
|
---|
677 | preloaded_symbols = 0;
|
---|
678 | if (default_preloaded_symbols)
|
---|
679 | return lt_dlpreload(default_preloaded_symbols);
|
---|
680 | return 0;
|
---|
681 | }
|
---|
682 |
|
---|
683 | static int
|
---|
684 | presym_free_symlists LTDL_PARAMS((void))
|
---|
685 | {
|
---|
686 | lt_dlsymlists_t *lists = preloaded_symbols;
|
---|
687 |
|
---|
688 | while (lists) {
|
---|
689 | lt_dlsymlists_t *tmp = lists;
|
---|
690 |
|
---|
691 | lists = lists->next;
|
---|
692 | lt_dlfree(tmp);
|
---|
693 | }
|
---|
694 | preloaded_symbols = 0;
|
---|
695 | return 0;
|
---|
696 | }
|
---|
697 |
|
---|
698 | static int
|
---|
699 | presym_exit (loader_data)
|
---|
700 | lt_dlloader_data_t loader_data;
|
---|
701 | {
|
---|
702 | presym_free_symlists();
|
---|
703 | return 0;
|
---|
704 | }
|
---|
705 |
|
---|
706 | static int
|
---|
707 | presym_add_symlist (preloaded)
|
---|
708 | const lt_dlsymlist *preloaded;
|
---|
709 | {
|
---|
710 | lt_dlsymlists_t *tmp;
|
---|
711 | lt_dlsymlists_t *lists = preloaded_symbols;
|
---|
712 |
|
---|
713 | while (lists) {
|
---|
714 | if (lists->syms == preloaded)
|
---|
715 | return 0;
|
---|
716 | lists = lists->next;
|
---|
717 | }
|
---|
718 |
|
---|
719 | tmp = (lt_dlsymlists_t*) lt_dlmalloc(sizeof(lt_dlsymlists_t));
|
---|
720 | if (!tmp) {
|
---|
721 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
722 | return 1;
|
---|
723 | }
|
---|
724 | tmp->syms = preloaded;
|
---|
725 | tmp->next = preloaded_symbols;
|
---|
726 | preloaded_symbols = tmp;
|
---|
727 | return 0;
|
---|
728 | }
|
---|
729 |
|
---|
730 | static lt_module_t
|
---|
731 | presym_open (loader_data, filename)
|
---|
732 | lt_dlloader_data_t loader_data;
|
---|
733 | const char *filename;
|
---|
734 | {
|
---|
735 | lt_dlsymlists_t *lists = preloaded_symbols;
|
---|
736 |
|
---|
737 | if (!lists) {
|
---|
738 | last_error = LT_DLSTRERROR(NO_SYMBOLS);
|
---|
739 | return 0;
|
---|
740 | }
|
---|
741 | if (!filename)
|
---|
742 | filename = "@PROGRAM@";
|
---|
743 | while (lists) {
|
---|
744 | const lt_dlsymlist *syms = lists->syms;
|
---|
745 |
|
---|
746 | while (syms->name) {
|
---|
747 | if (!syms->address &&
|
---|
748 | strcmp(syms->name, filename) == 0) {
|
---|
749 | return (lt_module_t) syms;
|
---|
750 | }
|
---|
751 | syms++;
|
---|
752 | }
|
---|
753 | lists = lists->next;
|
---|
754 | }
|
---|
755 | last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
|
---|
756 | return 0;
|
---|
757 | }
|
---|
758 |
|
---|
759 | static int
|
---|
760 | presym_close (loader_data, module)
|
---|
761 | lt_dlloader_data_t loader_data;
|
---|
762 | lt_module_t module;
|
---|
763 | {
|
---|
764 | /* Just to silence gcc -Wall */
|
---|
765 | module = 0;
|
---|
766 | return 0;
|
---|
767 | }
|
---|
768 |
|
---|
769 | static lt_ptr_t
|
---|
770 | presym_sym (loader_data, module, symbol)
|
---|
771 | lt_dlloader_data_t loader_data;
|
---|
772 | lt_module_t module;
|
---|
773 | const char *symbol;
|
---|
774 | {
|
---|
775 | lt_dlsymlist *syms = (lt_dlsymlist*)(module);
|
---|
776 |
|
---|
777 | syms++;
|
---|
778 | while (syms->address) {
|
---|
779 | if (strcmp(syms->name, symbol) == 0)
|
---|
780 | return syms->address;
|
---|
781 | syms++;
|
---|
782 | }
|
---|
783 | last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
|
---|
784 | return 0;
|
---|
785 | }
|
---|
786 |
|
---|
787 | static struct lt_user_dlloader
|
---|
788 | presym = { 0, presym_open, presym_close, presym_sym, presym_exit, 0 };
|
---|
789 |
|
---|
790 |
|
---|
791 | static char *user_search_path = 0;
|
---|
792 | static lt_dlloader_t *loaders = 0;
|
---|
793 | static lt_dlhandle handles = 0;
|
---|
794 | static int initialized = 0;
|
---|
795 |
|
---|
796 | int
|
---|
797 | lt_dlinit LTDL_PARAMS((void))
|
---|
798 | {
|
---|
799 | /* initialize libltdl */
|
---|
800 | int errors = 0;
|
---|
801 |
|
---|
802 | if (initialized) { /* Initialize only at first call. */
|
---|
803 | initialized++;
|
---|
804 | return 0;
|
---|
805 | }
|
---|
806 | handles = 0;
|
---|
807 | user_search_path = 0; /* empty search path */
|
---|
808 |
|
---|
809 | #if HAVE_LIBDL && !defined(__CYGWIN__)
|
---|
810 | errors += lt_dlloader_add (lt_dlloader_next(0), &sys_dl, "dlopen");
|
---|
811 | #endif
|
---|
812 | #if HAVE_SHL_LOAD
|
---|
813 | errors += lt_dlloader_add (lt_dlloader_next(0), &sys_shl, "dlopen");
|
---|
814 | #endif
|
---|
815 | #ifdef _WIN32
|
---|
816 | errors += lt_dlloader_add (lt_dlloader_next(0), &sys_wll, "dlopen");
|
---|
817 | #endif
|
---|
818 | #ifdef __BEOS__
|
---|
819 | errors += lt_dlloader_add (lt_dlloader_next(0), &sys_bedl, "dlopen");
|
---|
820 | #endif
|
---|
821 | #if HAVE_DLD
|
---|
822 | errors += lt_dlloader_add (lt_dlloader_next(0), &sys_dld, "dld");
|
---|
823 | #endif
|
---|
824 | errors += lt_dlloader_add (lt_dlloader_next(0), &presym, "dlpreload");
|
---|
825 | if (presym_init(presym.dlloader_data)) {
|
---|
826 | last_error = LT_DLSTRERROR(INIT_LOADER);
|
---|
827 | return 1;
|
---|
828 | }
|
---|
829 |
|
---|
830 | if (errors != 0) {
|
---|
831 | last_error = LT_DLSTRERROR(DLOPEN_NOT_SUPPORTED);
|
---|
832 | return 1;
|
---|
833 | }
|
---|
834 | last_error = 0;
|
---|
835 | initialized = 1;
|
---|
836 | return 0;
|
---|
837 | }
|
---|
838 |
|
---|
839 | int
|
---|
840 | lt_dlpreload (preloaded)
|
---|
841 | const lt_dlsymlist *preloaded;
|
---|
842 | {
|
---|
843 | if (preloaded)
|
---|
844 | return presym_add_symlist(preloaded);
|
---|
845 | presym_free_symlists();
|
---|
846 | if (default_preloaded_symbols)
|
---|
847 | return lt_dlpreload(default_preloaded_symbols);
|
---|
848 | return 0;
|
---|
849 | }
|
---|
850 |
|
---|
851 | int
|
---|
852 | lt_dlpreload_default (preloaded)
|
---|
853 | const lt_dlsymlist *preloaded;
|
---|
854 | {
|
---|
855 | default_preloaded_symbols = preloaded;
|
---|
856 | return 0;
|
---|
857 | }
|
---|
858 |
|
---|
859 | int
|
---|
860 | lt_dlexit LTDL_PARAMS((void))
|
---|
861 | {
|
---|
862 | /* shut down libltdl */
|
---|
863 | lt_dlloader_t *loader = loaders;
|
---|
864 | int errors, level;
|
---|
865 |
|
---|
866 | if (!initialized) {
|
---|
867 | last_error = LT_DLSTRERROR(SHUTDOWN);
|
---|
868 | return 1;
|
---|
869 | }
|
---|
870 | if (initialized != 1) { /* shut down only at last call. */
|
---|
871 | initialized--;
|
---|
872 | return 0;
|
---|
873 | }
|
---|
874 | /* close all modules */
|
---|
875 | errors = 0;
|
---|
876 | for (level = 1; handles; level++) {
|
---|
877 | lt_dlhandle cur = handles;
|
---|
878 | while (cur) {
|
---|
879 | lt_dlhandle tmp = cur;
|
---|
880 | cur = cur->next;
|
---|
881 | if (tmp->info.ref_count <= level)
|
---|
882 | if (lt_dlclose(tmp))
|
---|
883 | errors++;
|
---|
884 | }
|
---|
885 | }
|
---|
886 | /* close all loaders */
|
---|
887 | while (loader) {
|
---|
888 | lt_dlloader_t *next = loader->next;
|
---|
889 | lt_dlloader_data_t data = loader->dlloader_data;
|
---|
890 | if (loader->dlloader_exit && loader->dlloader_exit(data))
|
---|
891 | errors++;
|
---|
892 | lt_dlfree (loader);
|
---|
893 | loader = next;
|
---|
894 | }
|
---|
895 |
|
---|
896 | initialized = 0;
|
---|
897 | return errors;
|
---|
898 | }
|
---|
899 |
|
---|
900 | static int
|
---|
901 | tryall_dlopen (handle, filename)
|
---|
902 | lt_dlhandle *handle;
|
---|
903 | const char *filename;
|
---|
904 | {
|
---|
905 | lt_dlhandle cur = handles;
|
---|
906 | lt_dlloader_t *loader = loaders;
|
---|
907 | const char *saved_error = last_error;
|
---|
908 |
|
---|
909 | /* check whether the module was already opened */
|
---|
910 | while (cur) {
|
---|
911 | /* try to dlopen the program itself? */
|
---|
912 | if (!cur->info.filename && !filename)
|
---|
913 | break;
|
---|
914 | if (cur->info.filename && filename &&
|
---|
915 | strcmp(cur->info.filename, filename) == 0)
|
---|
916 | break;
|
---|
917 | cur = cur->next;
|
---|
918 | }
|
---|
919 |
|
---|
920 | if (cur) {
|
---|
921 | cur->info.ref_count++;
|
---|
922 | *handle = cur;
|
---|
923 | return 0;
|
---|
924 | }
|
---|
925 |
|
---|
926 | cur = *handle;
|
---|
927 | if (filename) {
|
---|
928 | cur->info.filename = strdup(filename);
|
---|
929 | if (!cur->info.filename) {
|
---|
930 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
931 | return 1;
|
---|
932 | }
|
---|
933 | } else
|
---|
934 | cur->info.filename = 0;
|
---|
935 | while (loader) {
|
---|
936 | lt_dlloader_data_t data = loader->dlloader_data;
|
---|
937 | cur->module = loader->module_open(data, filename);
|
---|
938 | if (cur->module != 0)
|
---|
939 | break;
|
---|
940 | loader = loader->next;
|
---|
941 | }
|
---|
942 | if (!loader) {
|
---|
943 | if (cur->info.filename)
|
---|
944 | lt_dlfree(cur->info.filename);
|
---|
945 | return 1;
|
---|
946 | }
|
---|
947 | cur->loader = loader;
|
---|
948 | last_error = saved_error;
|
---|
949 | return 0;
|
---|
950 | }
|
---|
951 |
|
---|
952 | static int
|
---|
953 | find_module (handle, dir, libdir, dlname, old_name, installed)
|
---|
954 | lt_dlhandle *handle;
|
---|
955 | const char *dir;
|
---|
956 | const char *libdir;
|
---|
957 | const char *dlname;
|
---|
958 | const char *old_name;
|
---|
959 | int installed;
|
---|
960 | {
|
---|
961 | int error;
|
---|
962 | char *filename;
|
---|
963 | /* try to open the old library first; if it was dlpreopened,
|
---|
964 | we want the preopened version of it, even if a dlopenable
|
---|
965 | module is available */
|
---|
966 | if (old_name && tryall_dlopen(handle, old_name) == 0)
|
---|
967 | return 0;
|
---|
968 | /* try to open the dynamic library */
|
---|
969 | if (dlname) {
|
---|
970 | /* try to open the installed module */
|
---|
971 | if (installed && libdir) {
|
---|
972 | filename = (char*)
|
---|
973 | lt_dlmalloc(strlen(libdir)+1+strlen(dlname)+1);
|
---|
974 | if (!filename) {
|
---|
975 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
976 | return 1;
|
---|
977 | }
|
---|
978 | sprintf (filename, "%s/%s", libdir, dlname);
|
---|
979 | error = tryall_dlopen(handle, filename) != 0;
|
---|
980 | lt_dlfree(filename);
|
---|
981 | if (!error)
|
---|
982 | return 0;
|
---|
983 | }
|
---|
984 | /* try to open the not-installed module */
|
---|
985 | if (!installed) {
|
---|
986 | filename = (char*)
|
---|
987 | lt_dlmalloc((dir ? strlen(dir) : 0)
|
---|
988 | + strlen(objdir) + strlen(dlname) + 1);
|
---|
989 | if (!filename) {
|
---|
990 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
991 | return 1;
|
---|
992 | }
|
---|
993 | if (dir)
|
---|
994 | strcpy(filename, dir);
|
---|
995 | else
|
---|
996 | *filename = 0;
|
---|
997 | strcat(filename, objdir);
|
---|
998 | strcat(filename, dlname);
|
---|
999 |
|
---|
1000 | error = tryall_dlopen(handle, filename) != 0;
|
---|
1001 | lt_dlfree(filename);
|
---|
1002 | if (!error)
|
---|
1003 | return 0;
|
---|
1004 | }
|
---|
1005 | /* maybe it was moved to another directory */
|
---|
1006 | {
|
---|
1007 | filename = (char*)
|
---|
1008 | lt_dlmalloc((dir ? strlen(dir) : 0)
|
---|
1009 | + strlen(dlname) + 1);
|
---|
1010 | if (dir)
|
---|
1011 | strcpy(filename, dir);
|
---|
1012 | else
|
---|
1013 | *filename = 0;
|
---|
1014 | strcat(filename, dlname);
|
---|
1015 | error = tryall_dlopen(handle, filename) != 0;
|
---|
1016 | lt_dlfree(filename);
|
---|
1017 | if (!error)
|
---|
1018 | return 0;
|
---|
1019 | }
|
---|
1020 | }
|
---|
1021 | return 1;
|
---|
1022 | }
|
---|
1023 |
|
---|
1024 | static char*
|
---|
1025 | canonicalize_path (path)
|
---|
1026 | const char *path;
|
---|
1027 | {
|
---|
1028 | char *canonical = 0;
|
---|
1029 |
|
---|
1030 | if (path && *path) {
|
---|
1031 | char *ptr = strdup (path);
|
---|
1032 | canonical = ptr;
|
---|
1033 | #ifdef LTDL_DIRSEP_CHAR
|
---|
1034 | /* Avoid this overhead where '/' is the only separator. */
|
---|
1035 | while (ptr = strchr (ptr, LTDL_DIRSEP_CHAR))
|
---|
1036 | *ptr++ = '/';
|
---|
1037 | #endif
|
---|
1038 | }
|
---|
1039 |
|
---|
1040 | return canonical;
|
---|
1041 | }
|
---|
1042 |
|
---|
1043 | static lt_ptr_t
|
---|
1044 | find_file (basename, search_path, pdir, handle)
|
---|
1045 | const char *basename;
|
---|
1046 | const char *search_path;
|
---|
1047 | char **pdir;
|
---|
1048 | lt_dlhandle *handle;
|
---|
1049 | {
|
---|
1050 | /* when handle != NULL search a library, otherwise a file */
|
---|
1051 | /* return NULL on failure, otherwise the file/handle */
|
---|
1052 |
|
---|
1053 | lt_ptr_t result = 0;
|
---|
1054 | char *filename = 0;
|
---|
1055 | int filenamesize = 0;
|
---|
1056 | int lenbase = strlen(basename);
|
---|
1057 | char *canonical = 0, *next = 0;
|
---|
1058 |
|
---|
1059 | if (!search_path || !*search_path) {
|
---|
1060 | last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
|
---|
1061 | return 0;
|
---|
1062 | }
|
---|
1063 | canonical = canonicalize_path (search_path);
|
---|
1064 | if (!canonical) {
|
---|
1065 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1066 | goto cleanup;
|
---|
1067 | }
|
---|
1068 | next = canonical;
|
---|
1069 | while (next) {
|
---|
1070 | int lendir;
|
---|
1071 | char *cur = next;
|
---|
1072 |
|
---|
1073 | next = strchr(cur, LTDL_PATHSEP_CHAR);
|
---|
1074 | if (!next)
|
---|
1075 | next = cur + strlen(cur);
|
---|
1076 | lendir = next - cur;
|
---|
1077 | if (*next == LTDL_PATHSEP_CHAR)
|
---|
1078 | ++next;
|
---|
1079 | else
|
---|
1080 | next = 0;
|
---|
1081 | if (lendir == 0)
|
---|
1082 | continue;
|
---|
1083 | if (lendir + 1 + lenbase >= filenamesize) {
|
---|
1084 | if (filename)
|
---|
1085 | lt_dlfree(filename);
|
---|
1086 | filenamesize = lendir + 1 + lenbase + 1;
|
---|
1087 | filename = (char*) lt_dlmalloc(filenamesize);
|
---|
1088 | if (!filename) {
|
---|
1089 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1090 | goto cleanup;
|
---|
1091 | }
|
---|
1092 | }
|
---|
1093 | strncpy(filename, cur, lendir);
|
---|
1094 | if (filename[lendir-1] != '/')
|
---|
1095 | filename[lendir++] = '/';
|
---|
1096 | strcpy(filename+lendir, basename);
|
---|
1097 | if (handle) {
|
---|
1098 | if (tryall_dlopen(handle, filename) == 0) {
|
---|
1099 | result = (lt_ptr_t) handle;
|
---|
1100 | goto cleanup;
|
---|
1101 | }
|
---|
1102 | } else {
|
---|
1103 | FILE *file = fopen(filename, LTDL_READTEXT_MODE);
|
---|
1104 | if (file) {
|
---|
1105 | if (*pdir)
|
---|
1106 | lt_dlfree(*pdir);
|
---|
1107 | filename[lendir] = '\0';
|
---|
1108 | *pdir = strdup(filename);
|
---|
1109 | if (!*pdir) {
|
---|
1110 | /* We could have even avoided the
|
---|
1111 | strdup, but there would be some
|
---|
1112 | memory overhead. */
|
---|
1113 | *pdir = filename;
|
---|
1114 | filename = 0;
|
---|
1115 | }
|
---|
1116 | result = (lt_ptr_t) file;
|
---|
1117 | goto cleanup;
|
---|
1118 | }
|
---|
1119 | }
|
---|
1120 | }
|
---|
1121 | last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
|
---|
1122 | cleanup:
|
---|
1123 | if (filename)
|
---|
1124 | lt_dlfree(filename);
|
---|
1125 | if (canonical)
|
---|
1126 | lt_dlfree(canonical);
|
---|
1127 | return result;
|
---|
1128 | }
|
---|
1129 |
|
---|
1130 | static int
|
---|
1131 | load_deplibs(handle, deplibs)
|
---|
1132 | lt_dlhandle handle;
|
---|
1133 | char *deplibs;
|
---|
1134 | {
|
---|
1135 | char *p, *save_search_path;
|
---|
1136 | int i;
|
---|
1137 | int ret = 1, depcount = 0;
|
---|
1138 | char **names = 0;
|
---|
1139 | lt_dlhandle *handles = 0;
|
---|
1140 |
|
---|
1141 | handle->depcount = 0;
|
---|
1142 | if (!deplibs)
|
---|
1143 | return 0;
|
---|
1144 | save_search_path = strdup(user_search_path);
|
---|
1145 | if (user_search_path && !save_search_path) {
|
---|
1146 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1147 | return 1;
|
---|
1148 | }
|
---|
1149 | p = deplibs;
|
---|
1150 | /* extract search paths and count deplibs */
|
---|
1151 | while (*p) {
|
---|
1152 | if (!isspace(*p)) {
|
---|
1153 | char *end = p+1;
|
---|
1154 | while (*end && !isspace(*end)) end++;
|
---|
1155 | if (strncmp(p, "-L", 2) == 0 ||
|
---|
1156 | strncmp(p, "-R", 2) == 0) {
|
---|
1157 | char save = *end;
|
---|
1158 | *end = 0; /* set a temporary string terminator */
|
---|
1159 | if (lt_dladdsearchdir(p+2))
|
---|
1160 | goto cleanup;
|
---|
1161 | *end = save;
|
---|
1162 | } else
|
---|
1163 | depcount++;
|
---|
1164 | p = end;
|
---|
1165 | } else
|
---|
1166 | p++;
|
---|
1167 | }
|
---|
1168 | if (!depcount) {
|
---|
1169 | ret = 0;
|
---|
1170 | goto cleanup;
|
---|
1171 | }
|
---|
1172 | names = (char**)lt_dlmalloc(depcount * sizeof(char*));
|
---|
1173 | if (!names)
|
---|
1174 | goto cleanup;
|
---|
1175 | handles = (lt_dlhandle*)lt_dlmalloc(depcount * sizeof(lt_dlhandle*));
|
---|
1176 | if (!handles)
|
---|
1177 | goto cleanup;
|
---|
1178 | depcount = 0;
|
---|
1179 | /* now only extract the actual deplibs */
|
---|
1180 | p = deplibs;
|
---|
1181 | while (*p) {
|
---|
1182 | if (!isspace(*p)) {
|
---|
1183 | char *end = p+1;
|
---|
1184 | while (*end && !isspace(*end)) end++;
|
---|
1185 | if (strncmp(p, "-L", 2) != 0 &&
|
---|
1186 | strncmp(p, "-R", 2) != 0) {
|
---|
1187 | char *name;
|
---|
1188 | char save = *end;
|
---|
1189 | *end = 0; /* set a temporary string terminator */
|
---|
1190 | if (strncmp(p, "-l", 2) == 0) {
|
---|
1191 | name = lt_dlmalloc(3+ /* "lib" */
|
---|
1192 | strlen(p+2)+1);
|
---|
1193 | if (name)
|
---|
1194 | sprintf (name, "lib%s", p+2);
|
---|
1195 | } else
|
---|
1196 | name = strdup(p);
|
---|
1197 | if (name)
|
---|
1198 | names[depcount++] = name;
|
---|
1199 | else
|
---|
1200 | goto cleanup_names;
|
---|
1201 | *end = save;
|
---|
1202 | }
|
---|
1203 | p = end;
|
---|
1204 | } else
|
---|
1205 | p++;
|
---|
1206 | }
|
---|
1207 | /* load the deplibs (in reverse order) */
|
---|
1208 | for (i = 0; i < depcount; i++) {
|
---|
1209 | lt_dlhandle handle = lt_dlopenext(names[depcount-1-i]);
|
---|
1210 | if (!handle) {
|
---|
1211 | int j;
|
---|
1212 | for (j = 0; j < i; j++)
|
---|
1213 | lt_dlclose(handles[j]);
|
---|
1214 | last_error = LT_DLSTRERROR(DEPLIB_NOT_FOUND);
|
---|
1215 | goto cleanup_names;
|
---|
1216 | }
|
---|
1217 | handles[i] = handle;
|
---|
1218 | }
|
---|
1219 | handle->depcount = depcount;
|
---|
1220 | handle->deplibs = handles;
|
---|
1221 | handles = 0;
|
---|
1222 | ret = 0;
|
---|
1223 | cleanup_names:
|
---|
1224 | for (i = 0; i < depcount; i++)
|
---|
1225 | lt_dlfree(names[i]);
|
---|
1226 | cleanup:
|
---|
1227 | if (names)
|
---|
1228 | lt_dlfree(names);
|
---|
1229 | if (handles)
|
---|
1230 | lt_dlfree(handles);
|
---|
1231 | /* restore the old search path */
|
---|
1232 | if (user_search_path)
|
---|
1233 | lt_dlfree(user_search_path);
|
---|
1234 | user_search_path = save_search_path;
|
---|
1235 | return ret;
|
---|
1236 | }
|
---|
1237 |
|
---|
1238 | static int
|
---|
1239 | unload_deplibs(handle)
|
---|
1240 | lt_dlhandle handle;
|
---|
1241 | {
|
---|
1242 | int i;
|
---|
1243 | int errors = 0;
|
---|
1244 |
|
---|
1245 | if (!handle->depcount)
|
---|
1246 | return 0;
|
---|
1247 | for (i = 0; i < handle->depcount; i++)
|
---|
1248 | errors += lt_dlclose(handle->deplibs[i]);
|
---|
1249 | return errors;
|
---|
1250 | }
|
---|
1251 |
|
---|
1252 | static inline int
|
---|
1253 | trim (dest, str)
|
---|
1254 | char **dest;
|
---|
1255 | const char *str;
|
---|
1256 | {
|
---|
1257 | /* remove the leading and trailing "'" from str
|
---|
1258 | and store the result in dest */
|
---|
1259 | char *tmp;
|
---|
1260 | const char *end = strrchr(str, '\'');
|
---|
1261 | int len = strlen(str);
|
---|
1262 |
|
---|
1263 | if (*dest)
|
---|
1264 | lt_dlfree(*dest);
|
---|
1265 | if (len > 3 && str[0] == '\'') {
|
---|
1266 | tmp = (char*) lt_dlmalloc(end - str);
|
---|
1267 | if (!tmp) {
|
---|
1268 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1269 | return 1;
|
---|
1270 | }
|
---|
1271 | strncpy(tmp, &str[1], (end - str) - 1);
|
---|
1272 | tmp[len-3] = '\0';
|
---|
1273 | *dest = tmp;
|
---|
1274 | } else
|
---|
1275 | *dest = 0;
|
---|
1276 | return 0;
|
---|
1277 | }
|
---|
1278 |
|
---|
1279 | static inline int
|
---|
1280 | free_vars( dlname, oldname, libdir, deplibs)
|
---|
1281 | char *dlname;
|
---|
1282 | char *oldname;
|
---|
1283 | char *libdir;
|
---|
1284 | char *deplibs;
|
---|
1285 | {
|
---|
1286 | if (dlname)
|
---|
1287 | lt_dlfree(dlname);
|
---|
1288 | if (oldname)
|
---|
1289 | lt_dlfree(oldname);
|
---|
1290 | if (libdir)
|
---|
1291 | lt_dlfree(libdir);
|
---|
1292 | if (deplibs)
|
---|
1293 | lt_dlfree(deplibs);
|
---|
1294 | return 0;
|
---|
1295 | }
|
---|
1296 |
|
---|
1297 | lt_dlhandle
|
---|
1298 | lt_dlopen (filename)
|
---|
1299 | const char *filename;
|
---|
1300 | {
|
---|
1301 | lt_dlhandle handle = 0, newhandle;
|
---|
1302 | const char *ext;
|
---|
1303 | const char *saved_error = last_error;
|
---|
1304 | char *canonical = 0, *basename = 0, *dir = 0, *name = 0;
|
---|
1305 |
|
---|
1306 | if (!filename) {
|
---|
1307 | handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
|
---|
1308 | if (!handle) {
|
---|
1309 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1310 | return 0;
|
---|
1311 | }
|
---|
1312 | handle->info.ref_count = 0;
|
---|
1313 | handle->depcount = 0;
|
---|
1314 | handle->deplibs = 0;
|
---|
1315 | newhandle = handle;
|
---|
1316 | if (tryall_dlopen(&newhandle, 0) != 0) {
|
---|
1317 | lt_dlfree(handle);
|
---|
1318 | return 0;
|
---|
1319 | }
|
---|
1320 | goto register_handle;
|
---|
1321 | }
|
---|
1322 | canonical = canonicalize_path (filename);
|
---|
1323 | if (!canonical) {
|
---|
1324 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1325 | if (handle)
|
---|
1326 | lt_dlfree(handle);
|
---|
1327 | return 0;
|
---|
1328 | }
|
---|
1329 | basename = strrchr(canonical, '/');
|
---|
1330 | if (basename) {
|
---|
1331 | basename++;
|
---|
1332 | dir = (char*) lt_dlmalloc(basename - canonical + 1);
|
---|
1333 | if (!dir) {
|
---|
1334 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1335 | handle = 0;
|
---|
1336 | goto cleanup;
|
---|
1337 | }
|
---|
1338 | strncpy(dir, canonical, basename - canonical);
|
---|
1339 | dir[basename - canonical] = '\0';
|
---|
1340 | } else
|
---|
1341 | basename = canonical;
|
---|
1342 | /* check whether we open a libtool module (.la extension) */
|
---|
1343 | ext = strrchr(basename, '.');
|
---|
1344 | if (ext && strcmp(ext, ".la") == 0) {
|
---|
1345 | /* this seems to be a libtool module */
|
---|
1346 | FILE *file;
|
---|
1347 | int i;
|
---|
1348 | char *dlname = 0, *old_name = 0;
|
---|
1349 | char *libdir = 0, *deplibs = 0;
|
---|
1350 | char *line;
|
---|
1351 | int error = 0;
|
---|
1352 | /* if we can't find the installed flag, it is probably an
|
---|
1353 | installed libtool archive, produced with an old version
|
---|
1354 | of libtool */
|
---|
1355 | int installed = 1;
|
---|
1356 |
|
---|
1357 | /* extract the module name from the file name */
|
---|
1358 | name = (char*) lt_dlmalloc(ext - basename + 1);
|
---|
1359 | if (!name) {
|
---|
1360 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1361 | handle = 0;
|
---|
1362 | goto cleanup;
|
---|
1363 | }
|
---|
1364 | /* canonicalize the module name */
|
---|
1365 | for (i = 0; i < ext - basename; i++)
|
---|
1366 | if (isalnum((int)(basename[i])))
|
---|
1367 | name[i] = basename[i];
|
---|
1368 | else
|
---|
1369 | name[i] = '_';
|
---|
1370 | name[ext - basename] = '\0';
|
---|
1371 | /* now try to open the .la file */
|
---|
1372 | file = fopen(filename, LTDL_READTEXT_MODE);
|
---|
1373 | if (!file)
|
---|
1374 | last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
|
---|
1375 | if (!file && !dir) {
|
---|
1376 | /* try other directories */
|
---|
1377 | file = (FILE*) find_file(basename,
|
---|
1378 | user_search_path,
|
---|
1379 | &dir, 0);
|
---|
1380 | if (!file)
|
---|
1381 | file = (FILE*) find_file(basename,
|
---|
1382 | getenv("LTDL_LIBRARY_PATH"),
|
---|
1383 | &dir, 0);
|
---|
1384 | #ifdef LTDL_SHLIBPATH_VAR
|
---|
1385 | if (!file)
|
---|
1386 | file = (FILE*) find_file(basename,
|
---|
1387 | getenv(LTDL_SHLIBPATH_VAR),
|
---|
1388 | &dir, 0);
|
---|
1389 | #endif
|
---|
1390 | #ifdef LTDL_SYSSEARCHPATH
|
---|
1391 | if (!file)
|
---|
1392 | file = (FILE*) find_file(basename,
|
---|
1393 | sys_search_path,
|
---|
1394 | &dir, 0);
|
---|
1395 | #endif
|
---|
1396 | }
|
---|
1397 | if (!file) {
|
---|
1398 | handle = 0;
|
---|
1399 | goto cleanup;
|
---|
1400 | }
|
---|
1401 | line = (char*) lt_dlmalloc(LTDL_FILENAME_MAX);
|
---|
1402 | if (!line) {
|
---|
1403 | fclose(file);
|
---|
1404 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1405 | handle = 0;
|
---|
1406 | goto cleanup;
|
---|
1407 | }
|
---|
1408 | /* read the .la file */
|
---|
1409 | while (!feof(file)) {
|
---|
1410 | if (!fgets(line, LTDL_FILENAME_MAX, file))
|
---|
1411 | break;
|
---|
1412 | if (line[0] == '\n' || line[0] == '#')
|
---|
1413 | continue;
|
---|
1414 | # undef STR_DLNAME
|
---|
1415 | # define STR_DLNAME "dlname="
|
---|
1416 | if (strncmp(line, STR_DLNAME,
|
---|
1417 | sizeof(STR_DLNAME) - 1) == 0)
|
---|
1418 | error = trim(&dlname,
|
---|
1419 | &line[sizeof(STR_DLNAME) - 1]);
|
---|
1420 | else
|
---|
1421 | # undef STR_OLD_LIBRARY
|
---|
1422 | # define STR_OLD_LIBRARY "old_library="
|
---|
1423 | if (strncmp(line, STR_OLD_LIBRARY,
|
---|
1424 | sizeof(STR_OLD_LIBRARY) - 1) == 0)
|
---|
1425 | error = trim(&old_name,
|
---|
1426 | &line[sizeof(STR_OLD_LIBRARY) - 1]);
|
---|
1427 | else
|
---|
1428 | # undef STR_LIBDIR
|
---|
1429 | # define STR_LIBDIR "libdir="
|
---|
1430 | if (strncmp(line, STR_LIBDIR,
|
---|
1431 | sizeof(STR_LIBDIR) - 1) == 0)
|
---|
1432 | error = trim(&libdir,
|
---|
1433 | &line[sizeof(STR_LIBDIR) - 1]);
|
---|
1434 | else
|
---|
1435 | # undef STR_DL_DEPLIBS
|
---|
1436 | # define STR_DL_DEPLIBS "dl_dependency_libs="
|
---|
1437 | if (strncmp(line, STR_DL_DEPLIBS,
|
---|
1438 | sizeof(STR_DL_DEPLIBS) - 1) == 0)
|
---|
1439 | error = trim(&deplibs,
|
---|
1440 | &line[sizeof(STR_DL_DEPLIBS) - 1]);
|
---|
1441 | else
|
---|
1442 | if (strcmp(line, "installed=yes\n") == 0)
|
---|
1443 | installed = 1;
|
---|
1444 | else
|
---|
1445 | if (strcmp(line, "installed=no\n") == 0)
|
---|
1446 | installed = 0;
|
---|
1447 | else
|
---|
1448 | # undef STR_LIBRARY_NAMES
|
---|
1449 | # define STR_LIBRARY_NAMES "library_names="
|
---|
1450 | if (! dlname &&
|
---|
1451 | strncmp(line, STR_LIBRARY_NAMES,
|
---|
1452 | sizeof(STR_LIBRARY_NAMES) - 1) == 0) {
|
---|
1453 | char *last_libname;
|
---|
1454 | error = trim(&dlname,
|
---|
1455 | &line[sizeof(STR_LIBRARY_NAMES) - 1]);
|
---|
1456 | if (! error && dlname &&
|
---|
1457 | (last_libname = strrchr(dlname, ' ')) != NULL) {
|
---|
1458 | last_libname = strdup(last_libname + 1);
|
---|
1459 | free(dlname);
|
---|
1460 | dlname = last_libname;
|
---|
1461 | }
|
---|
1462 | }
|
---|
1463 | if (error)
|
---|
1464 | break;
|
---|
1465 | }
|
---|
1466 | fclose(file);
|
---|
1467 | lt_dlfree(line);
|
---|
1468 | /* allocate the handle */
|
---|
1469 | handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
|
---|
1470 | if (!handle || error) {
|
---|
1471 | if (handle)
|
---|
1472 | lt_dlfree(handle);
|
---|
1473 | if (!error)
|
---|
1474 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1475 | free_vars(dlname, old_name, libdir, deplibs);
|
---|
1476 | /* handle is already set to 0 */
|
---|
1477 | goto cleanup;
|
---|
1478 | }
|
---|
1479 | handle->info.ref_count = 0;
|
---|
1480 | if (load_deplibs(handle, deplibs) == 0) {
|
---|
1481 | newhandle = handle;
|
---|
1482 | /* find_module may replace newhandle */
|
---|
1483 | if (find_module(&newhandle, dir, libdir,
|
---|
1484 | dlname, old_name, installed)) {
|
---|
1485 | unload_deplibs(handle);
|
---|
1486 | error = 1;
|
---|
1487 | }
|
---|
1488 | } else
|
---|
1489 | error = 1;
|
---|
1490 | free_vars(dlname, old_name, libdir, deplibs);
|
---|
1491 | if (error) {
|
---|
1492 | lt_dlfree(handle);
|
---|
1493 | handle = 0;
|
---|
1494 | goto cleanup;
|
---|
1495 | }
|
---|
1496 | if (handle != newhandle)
|
---|
1497 | unload_deplibs(handle);
|
---|
1498 | } else {
|
---|
1499 | /* not a libtool module */
|
---|
1500 | handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
|
---|
1501 | if (!handle) {
|
---|
1502 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1503 | /* handle is already set to 0 */
|
---|
1504 | goto cleanup;
|
---|
1505 | }
|
---|
1506 | handle->info.ref_count = 0;
|
---|
1507 | /* non-libtool modules don't have dependencies */
|
---|
1508 | handle->depcount = 0;
|
---|
1509 | handle->deplibs = 0;
|
---|
1510 | newhandle = handle;
|
---|
1511 | if (tryall_dlopen(&newhandle, filename)
|
---|
1512 | && (dir
|
---|
1513 | || (!find_file(basename, user_search_path,
|
---|
1514 | 0, &newhandle)
|
---|
1515 | && !find_file(basename,
|
---|
1516 | getenv("LTDL_LIBRARY_PATH"),
|
---|
1517 | 0, &newhandle)
|
---|
1518 | #ifdef LTDL_SHLIBPATH_VAR
|
---|
1519 | && !find_file(basename,
|
---|
1520 | getenv(LTDL_SHLIBPATH_VAR),
|
---|
1521 | 0, &newhandle)
|
---|
1522 | #endif
|
---|
1523 | #ifdef LTDL_SYSSEARCHPATH
|
---|
1524 | && !find_file(basename, sys_search_path,
|
---|
1525 | 0, &newhandle)
|
---|
1526 | #endif
|
---|
1527 | ))) {
|
---|
1528 | lt_dlfree(handle);
|
---|
1529 | handle = 0;
|
---|
1530 | goto cleanup;
|
---|
1531 | }
|
---|
1532 | }
|
---|
1533 | register_handle:
|
---|
1534 | if (newhandle != handle) {
|
---|
1535 | lt_dlfree(handle);
|
---|
1536 | handle = newhandle;
|
---|
1537 | }
|
---|
1538 | if (!handle->info.ref_count) {
|
---|
1539 | handle->info.ref_count = 1;
|
---|
1540 | handle->info.name = name;
|
---|
1541 | handle->next = handles;
|
---|
1542 | handles = handle;
|
---|
1543 | name = 0; /* don't free this during `cleanup' */
|
---|
1544 | }
|
---|
1545 | last_error = saved_error;
|
---|
1546 | cleanup:
|
---|
1547 | if (dir)
|
---|
1548 | lt_dlfree(dir);
|
---|
1549 | if (name)
|
---|
1550 | lt_dlfree(name);
|
---|
1551 | if (canonical)
|
---|
1552 | lt_dlfree(canonical);
|
---|
1553 | return handle;
|
---|
1554 | }
|
---|
1555 |
|
---|
1556 | lt_dlhandle
|
---|
1557 | lt_dlopenext (filename)
|
---|
1558 | const char *filename;
|
---|
1559 | {
|
---|
1560 | lt_dlhandle handle;
|
---|
1561 | char *tmp;
|
---|
1562 | int len;
|
---|
1563 | const char *saved_error = last_error;
|
---|
1564 |
|
---|
1565 | if (!filename)
|
---|
1566 | return lt_dlopen(filename);
|
---|
1567 | len = strlen(filename);
|
---|
1568 | if (!len) {
|
---|
1569 | last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
|
---|
1570 | return 0;
|
---|
1571 | }
|
---|
1572 | /* try the normal file name */
|
---|
1573 | handle = lt_dlopen(filename);
|
---|
1574 | if (handle)
|
---|
1575 | return handle;
|
---|
1576 | /* try "filename.la" */
|
---|
1577 | tmp = (char*) lt_dlmalloc(len+4);
|
---|
1578 | if (!tmp) {
|
---|
1579 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1580 | return 0;
|
---|
1581 | }
|
---|
1582 | strcpy(tmp, filename);
|
---|
1583 | strcat(tmp, ".la");
|
---|
1584 | handle = lt_dlopen(tmp);
|
---|
1585 | if (handle) {
|
---|
1586 | last_error = saved_error;
|
---|
1587 | lt_dlfree(tmp);
|
---|
1588 | return handle;
|
---|
1589 | }
|
---|
1590 | #ifdef LTDL_SHLIB_EXT
|
---|
1591 | /* try "filename.EXT" */
|
---|
1592 | if (strlen(shlib_ext) > 3) {
|
---|
1593 | lt_dlfree(tmp);
|
---|
1594 | tmp = (char*) lt_dlmalloc(len + strlen(shlib_ext) + 1);
|
---|
1595 | if (!tmp) {
|
---|
1596 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1597 | return 0;
|
---|
1598 | }
|
---|
1599 | strcpy(tmp, filename);
|
---|
1600 | } else
|
---|
1601 | tmp[len] = '\0';
|
---|
1602 | strcat(tmp, shlib_ext);
|
---|
1603 | handle = lt_dlopen(tmp);
|
---|
1604 | if (handle) {
|
---|
1605 | last_error = saved_error;
|
---|
1606 | lt_dlfree(tmp);
|
---|
1607 | return handle;
|
---|
1608 | }
|
---|
1609 | #endif
|
---|
1610 | last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
|
---|
1611 | lt_dlfree(tmp);
|
---|
1612 | return 0;
|
---|
1613 | }
|
---|
1614 |
|
---|
1615 | int
|
---|
1616 | lt_dlclose (handle)
|
---|
1617 | lt_dlhandle handle;
|
---|
1618 | {
|
---|
1619 | lt_dlhandle cur, last;
|
---|
1620 |
|
---|
1621 | /* check whether the handle is valid */
|
---|
1622 | last = cur = handles;
|
---|
1623 | while (cur && handle != cur) {
|
---|
1624 | last = cur;
|
---|
1625 | cur = cur->next;
|
---|
1626 | }
|
---|
1627 | if (!cur) {
|
---|
1628 | last_error = LT_DLSTRERROR(INVALID_HANDLE);
|
---|
1629 | return 1;
|
---|
1630 | }
|
---|
1631 | handle->info.ref_count--;
|
---|
1632 | if (!handle->info.ref_count) {
|
---|
1633 | int error;
|
---|
1634 | lt_dlloader_data_t data = handle->loader->dlloader_data;
|
---|
1635 |
|
---|
1636 | if (handle != handles)
|
---|
1637 | last->next = handle->next;
|
---|
1638 | else
|
---|
1639 | handles = handle->next;
|
---|
1640 | error = handle->loader->module_close(data, handle->module);
|
---|
1641 | error += unload_deplibs(handle);
|
---|
1642 | if (handle->info.filename)
|
---|
1643 | lt_dlfree(handle->info.filename);
|
---|
1644 | if (handle->info.name)
|
---|
1645 | lt_dlfree(handle->info.name);
|
---|
1646 | lt_dlfree(handle);
|
---|
1647 | return error;
|
---|
1648 | }
|
---|
1649 | return 0;
|
---|
1650 | }
|
---|
1651 |
|
---|
1652 | lt_ptr_t
|
---|
1653 | lt_dlsym (handle, symbol)
|
---|
1654 | lt_dlhandle handle;
|
---|
1655 | const char *symbol;
|
---|
1656 | {
|
---|
1657 | int lensym;
|
---|
1658 | char lsym[LTDL_SYMBOL_LENGTH];
|
---|
1659 | char *sym;
|
---|
1660 | lt_ptr_t address;
|
---|
1661 | lt_dlloader_data_t data;
|
---|
1662 |
|
---|
1663 | if (!handle) {
|
---|
1664 | last_error = LT_DLSTRERROR(INVALID_HANDLE);
|
---|
1665 | return 0;
|
---|
1666 | }
|
---|
1667 | if (!symbol) {
|
---|
1668 | last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
|
---|
1669 | return 0;
|
---|
1670 | }
|
---|
1671 | lensym = strlen(symbol);
|
---|
1672 | if (handle->loader->sym_prefix)
|
---|
1673 | lensym += strlen(handle->loader->sym_prefix);
|
---|
1674 | if (handle->info.name)
|
---|
1675 | lensym += strlen(handle->info.name);
|
---|
1676 | if (lensym + LTDL_SYMBOL_OVERHEAD < LTDL_SYMBOL_LENGTH)
|
---|
1677 | sym = lsym;
|
---|
1678 | else
|
---|
1679 | sym = (char*) lt_dlmalloc(lensym + LTDL_SYMBOL_OVERHEAD + 1);
|
---|
1680 | if (!sym) {
|
---|
1681 | last_error = LT_DLSTRERROR(BUFFER_OVERFLOW);
|
---|
1682 | return 0;
|
---|
1683 | }
|
---|
1684 | data = handle->loader->dlloader_data;
|
---|
1685 | if (handle->info.name) {
|
---|
1686 | const char *saved_error = last_error;
|
---|
1687 |
|
---|
1688 | /* this is a libtool module */
|
---|
1689 | if (handle->loader->sym_prefix) {
|
---|
1690 | strcpy(sym, handle->loader->sym_prefix);
|
---|
1691 | strcat(sym, handle->info.name);
|
---|
1692 | } else
|
---|
1693 | strcpy(sym, handle->info.name);
|
---|
1694 | strcat(sym, "_LTX_");
|
---|
1695 | strcat(sym, symbol);
|
---|
1696 | /* try "modulename_LTX_symbol" */
|
---|
1697 | address = handle->loader->find_sym(data, handle->module, sym);
|
---|
1698 | if (address) {
|
---|
1699 | if (sym != lsym)
|
---|
1700 | lt_dlfree(sym);
|
---|
1701 | return address;
|
---|
1702 | }
|
---|
1703 | last_error = saved_error;
|
---|
1704 | }
|
---|
1705 | /* otherwise try "symbol" */
|
---|
1706 | if (handle->loader->sym_prefix) {
|
---|
1707 | strcpy(sym, handle->loader->sym_prefix);
|
---|
1708 | strcat(sym, symbol);
|
---|
1709 | } else
|
---|
1710 | strcpy(sym, symbol);
|
---|
1711 | address = handle->loader->find_sym(data, handle->module, sym);
|
---|
1712 | if (sym != lsym)
|
---|
1713 | lt_dlfree(sym);
|
---|
1714 | return address;
|
---|
1715 | }
|
---|
1716 |
|
---|
1717 | const char *
|
---|
1718 | lt_dlerror LTDL_PARAMS((void))
|
---|
1719 | {
|
---|
1720 | const char *error = last_error;
|
---|
1721 |
|
---|
1722 | last_error = 0;
|
---|
1723 | return error;
|
---|
1724 | }
|
---|
1725 |
|
---|
1726 | int
|
---|
1727 | lt_dladdsearchdir (search_dir)
|
---|
1728 | const char *search_dir;
|
---|
1729 | {
|
---|
1730 | if (!search_dir || !strlen(search_dir))
|
---|
1731 | return 0;
|
---|
1732 | if (!user_search_path) {
|
---|
1733 | user_search_path = strdup(search_dir);
|
---|
1734 | if (!user_search_path) {
|
---|
1735 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1736 | return 1;
|
---|
1737 | }
|
---|
1738 | } else {
|
---|
1739 | char *new_search_path = (char*)
|
---|
1740 | lt_dlmalloc(strlen(user_search_path) +
|
---|
1741 | strlen(search_dir) + 2); /* ':' + '\0' == 2 */
|
---|
1742 | if (!new_search_path) {
|
---|
1743 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1744 | return 1;
|
---|
1745 | }
|
---|
1746 | sprintf (new_search_path, "%s%c%s", user_search_path,
|
---|
1747 | LTDL_PATHSEP_CHAR, search_dir);
|
---|
1748 | lt_dlfree(user_search_path);
|
---|
1749 | user_search_path = new_search_path;
|
---|
1750 | }
|
---|
1751 | return 0;
|
---|
1752 | }
|
---|
1753 |
|
---|
1754 | int
|
---|
1755 | lt_dlsetsearchpath (search_path)
|
---|
1756 | const char *search_path;
|
---|
1757 | {
|
---|
1758 | if (user_search_path)
|
---|
1759 | lt_dlfree(user_search_path);
|
---|
1760 | user_search_path = 0; /* reset the search path */
|
---|
1761 | if (!search_path || !strlen(search_path))
|
---|
1762 | return 0;
|
---|
1763 | user_search_path = strdup(search_path);
|
---|
1764 | if (!user_search_path)
|
---|
1765 | return 1;
|
---|
1766 | return 0;
|
---|
1767 | }
|
---|
1768 |
|
---|
1769 | const char *
|
---|
1770 | lt_dlgetsearchpath LTDL_PARAMS((void))
|
---|
1771 | {
|
---|
1772 | return user_search_path;
|
---|
1773 | }
|
---|
1774 |
|
---|
1775 | const lt_dlinfo *
|
---|
1776 | lt_dlgetinfo (handle)
|
---|
1777 | lt_dlhandle handle;
|
---|
1778 | {
|
---|
1779 | if (!handle) {
|
---|
1780 | last_error = LT_DLSTRERROR(INVALID_HANDLE);
|
---|
1781 | return 0;
|
---|
1782 | }
|
---|
1783 | return &(handle->info);
|
---|
1784 | }
|
---|
1785 |
|
---|
1786 | int
|
---|
1787 | lt_dlforeach (func, data)
|
---|
1788 | int (*func) LTDL_PARAMS((lt_dlhandle handle, lt_ptr_t data));
|
---|
1789 | lt_ptr_t data;
|
---|
1790 | {
|
---|
1791 | lt_dlhandle cur = handles;
|
---|
1792 | while (cur) {
|
---|
1793 | lt_dlhandle tmp = cur;
|
---|
1794 | cur = cur->next;
|
---|
1795 | if (func(tmp, data))
|
---|
1796 | return 1;
|
---|
1797 | }
|
---|
1798 | return 0;
|
---|
1799 | }
|
---|
1800 |
|
---|
1801 | int
|
---|
1802 | lt_dlloader_add (place, dlloader, loader_name)
|
---|
1803 | lt_dlloader_t *place;
|
---|
1804 | const struct lt_user_dlloader *dlloader;
|
---|
1805 | const char *loader_name;
|
---|
1806 | {
|
---|
1807 | lt_dlloader_t *node = 0, *ptr = 0;
|
---|
1808 |
|
---|
1809 | if ((dlloader == 0) /* diagnose null parameters */
|
---|
1810 | || (dlloader->module_open == 0)
|
---|
1811 | || (dlloader->module_close == 0)
|
---|
1812 | || (dlloader->find_sym == 0)) {
|
---|
1813 | last_error = LT_DLSTRERROR(INVALID_LOADER);
|
---|
1814 | return 1;
|
---|
1815 | }
|
---|
1816 |
|
---|
1817 | /* Create a new dlloader node with copies of the user callbacks. */
|
---|
1818 | node = (lt_dlloader_t *) lt_dlmalloc (sizeof (lt_dlloader_t));
|
---|
1819 | if (node == 0) {
|
---|
1820 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1821 | return 1;
|
---|
1822 | }
|
---|
1823 | node->next = 0;
|
---|
1824 | node->loader_name = loader_name;
|
---|
1825 | node->sym_prefix = dlloader->sym_prefix;
|
---|
1826 | node->dlloader_exit = dlloader->dlloader_exit;
|
---|
1827 | node->module_open = dlloader->module_open;
|
---|
1828 | node->module_close = dlloader->module_close;
|
---|
1829 | node->find_sym = dlloader->find_sym;
|
---|
1830 | node->dlloader_data = dlloader->dlloader_data;
|
---|
1831 |
|
---|
1832 | if (!loaders)
|
---|
1833 | /* If there are no loaders, NODE becomes the list! */
|
---|
1834 | loaders = node;
|
---|
1835 | else if (!place) {
|
---|
1836 | /* If PLACE is not set, add NODE to the end of the
|
---|
1837 | LOADERS list. */
|
---|
1838 | for (ptr = loaders; ptr->next; ptr = ptr->next)
|
---|
1839 | /*NOWORK*/;
|
---|
1840 | ptr->next = node;
|
---|
1841 | } else if (loaders == place) {
|
---|
1842 | /* If PLACE is the first loader, NODE goes first. */
|
---|
1843 | node->next = place;
|
---|
1844 | loaders = node;
|
---|
1845 | } else {
|
---|
1846 | /* Find the node immediately preceding PLACE. */
|
---|
1847 | for (ptr = loaders; ptr->next != place; ptr = ptr->next)
|
---|
1848 | /*NOWORK*/;
|
---|
1849 |
|
---|
1850 | if (ptr->next != place) {
|
---|
1851 | last_error = LT_DLSTRERROR(INVALID_LOADER);
|
---|
1852 | return 1;
|
---|
1853 | }
|
---|
1854 |
|
---|
1855 | /* Insert NODE between PTR and PLACE. */
|
---|
1856 | node->next = place;
|
---|
1857 | ptr->next = node;
|
---|
1858 | }
|
---|
1859 |
|
---|
1860 | return 0;
|
---|
1861 | }
|
---|
1862 |
|
---|
1863 | int
|
---|
1864 | lt_dlloader_remove (loader_name)
|
---|
1865 | const char *loader_name;
|
---|
1866 | {
|
---|
1867 | lt_dlloader_t *place = lt_dlloader_find (loader_name);
|
---|
1868 | lt_dlhandle handle;
|
---|
1869 | int result = 0;
|
---|
1870 |
|
---|
1871 | if (!place) {
|
---|
1872 | last_error = LT_DLSTRERROR(INVALID_LOADER);
|
---|
1873 | return 1;
|
---|
1874 | }
|
---|
1875 |
|
---|
1876 | /* Fail if there are any open modules which use this loader. */
|
---|
1877 | for (handle = handles; handle; handle = handle->next)
|
---|
1878 | if (handle->loader == place) {
|
---|
1879 | last_error = LT_DLSTRERROR(REMOVE_LOADER);
|
---|
1880 | return 1;
|
---|
1881 | }
|
---|
1882 |
|
---|
1883 | if (place == loaders)
|
---|
1884 | /* PLACE is the first loader in the list. */
|
---|
1885 | loaders = loaders->next;
|
---|
1886 | else {
|
---|
1887 | /* Find the loader before the one being removed. */
|
---|
1888 | lt_dlloader_t *prev;
|
---|
1889 | for (prev = loaders; prev->next; prev = prev->next)
|
---|
1890 | if (!strcmp (prev->next->loader_name, loader_name))
|
---|
1891 | break;
|
---|
1892 |
|
---|
1893 | place = prev->next;
|
---|
1894 | prev->next = prev->next->next;
|
---|
1895 | }
|
---|
1896 | if (place->dlloader_exit)
|
---|
1897 | result = place->dlloader_exit (place->dlloader_data);
|
---|
1898 | lt_dlfree (place);
|
---|
1899 |
|
---|
1900 | return result;
|
---|
1901 | }
|
---|
1902 |
|
---|
1903 | lt_dlloader_t *
|
---|
1904 | lt_dlloader_next (place)
|
---|
1905 | lt_dlloader_t *place;
|
---|
1906 | {
|
---|
1907 | return place ? place->next : loaders;
|
---|
1908 | }
|
---|
1909 |
|
---|
1910 | const char *
|
---|
1911 | lt_dlloader_name (place)
|
---|
1912 | lt_dlloader_t *place;
|
---|
1913 | {
|
---|
1914 | if (!place)
|
---|
1915 | last_error = LT_DLSTRERROR(INVALID_LOADER);
|
---|
1916 | return place ? place->loader_name : 0;
|
---|
1917 | }
|
---|
1918 |
|
---|
1919 | lt_dlloader_data_t *
|
---|
1920 | lt_dlloader_data (place)
|
---|
1921 | lt_dlloader_t *place;
|
---|
1922 | {
|
---|
1923 | if (!place)
|
---|
1924 | last_error = LT_DLSTRERROR(INVALID_LOADER);
|
---|
1925 | return place ? &(place->dlloader_data) : 0;
|
---|
1926 | }
|
---|
1927 |
|
---|
1928 | lt_dlloader_t *
|
---|
1929 | lt_dlloader_find (loader_name)
|
---|
1930 | const char *loader_name;
|
---|
1931 | {
|
---|
1932 | lt_dlloader_t *place = 0;
|
---|
1933 |
|
---|
1934 | for (place = loaders; place; place = place->next)
|
---|
1935 | if (strcmp (place->loader_name, loader_name) == 0)
|
---|
1936 | break;
|
---|
1937 |
|
---|
1938 | return place;
|
---|
1939 | }
|
---|
1940 |
|
---|
1941 | static const char **user_error_strings = 0;
|
---|
1942 | static int errorcode = LTDL_ERROR_MAX;
|
---|
1943 |
|
---|
1944 | int
|
---|
1945 | lt_dladderror (diagnostic)
|
---|
1946 | const char *diagnostic;
|
---|
1947 | {
|
---|
1948 | int index = errorcode - LTDL_ERROR_MAX;
|
---|
1949 | const char **temp = 0;
|
---|
1950 |
|
---|
1951 | /* realloc is not entirely portable, so simulate it using
|
---|
1952 | lt_dlmalloc and lt_dlfree. */
|
---|
1953 | temp = (const char **) lt_dlmalloc ((1+index) * sizeof(const char*));
|
---|
1954 | if (temp == 0) {
|
---|
1955 | last_error = LT_DLSTRERROR(NO_MEMORY);
|
---|
1956 | return -1;
|
---|
1957 | }
|
---|
1958 |
|
---|
1959 | /* Build the new vector in the memory addressed by temp. */
|
---|
1960 | temp[index] = diagnostic;
|
---|
1961 | while (--index >= 0)
|
---|
1962 | temp[index] = user_error_strings[index];
|
---|
1963 |
|
---|
1964 | lt_dlfree (user_error_strings);
|
---|
1965 | user_error_strings = temp;
|
---|
1966 | return errorcode++;
|
---|
1967 | }
|
---|
1968 |
|
---|
1969 | int
|
---|
1970 | lt_dlseterror (index)
|
---|
1971 | int index;
|
---|
1972 | {
|
---|
1973 | if (index >= errorcode || index < 0) {
|
---|
1974 | last_error = LT_DLSTRERROR(INVALID_ERRORCODE);
|
---|
1975 | return 1;
|
---|
1976 | }
|
---|
1977 |
|
---|
1978 | if (index < LTDL_ERROR_MAX)
|
---|
1979 | last_error = ltdl_error_strings[errorcode];
|
---|
1980 | else
|
---|
1981 | last_error = user_error_strings[errorcode - LTDL_ERROR_MAX];
|
---|
1982 |
|
---|
1983 | return 0;
|
---|
1984 | }
|
---|