FSF GCC merge 02/23/03
[official-gcc.git] / libjava / libltdl / ltdl.c
blob5ecbee5d2cb14e38a9e2b1581fb75e9bb4bd7dd5
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.
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.
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.
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.
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
28 #define _LTDL_COMPILE_
30 #if HAVE_CONFIG_H
31 #include <config.h>
32 #endif
34 #if HAVE_STRING_H
35 #include <string.h>
36 #endif
38 #if HAVE_STRINGS_H
39 #include <strings.h>
40 #endif
42 #if HAVE_CTYPE_H
43 #include <ctype.h>
44 #endif
46 #if HAVE_MALLOC_H
47 #include <malloc.h>
48 #endif
50 #if HAVE_MEMORY_H
51 #include <memory.h>
52 #endif
54 #if HAVE_STDLIB_H
55 #include <stdlib.h>
56 #endif
58 #if HAVE_STDIO_H
59 #include <stdio.h>
60 #endif
62 #if HAVE_BOEHM_GC
63 #include <gc.h>
64 #endif
66 #include "ltdl.h"
68 #ifdef DLL_EXPORT
69 # define LTDL_GLOBAL_DATA __declspec(dllexport)
70 #else
71 # define LTDL_GLOBAL_DATA
72 #endif
74 /* max. filename length */
75 #ifndef LTDL_FILENAME_MAX
76 #define LTDL_FILENAME_MAX 1024
77 #endif
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
87 #undef LTDL_SYMBOL_LENGTH
88 /* This is the maximum symbol size that won't require malloc/free */
89 #define LTDL_SYMBOL_LENGTH 128
91 #undef LTDL_SYMBOL_OVERHEAD
92 /* This accounts for the _LTX_ separator */
93 #define LTDL_SYMBOL_OVERHEAD 5
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;
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;
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
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
134 #undef LTDL_ERROR
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
142 static const char *last_error = 0;
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;
147 #undef strdup
148 #define strdup xstrdup
150 static inline char *
151 strdup(str)
152 const char *str;
154 char *tmp;
156 if (!str)
157 return 0;
158 tmp = (char*) lt_dlmalloc(strlen(str)+1);
159 if (tmp)
160 strcpy(tmp, str);
161 return tmp;
164 #if ! HAVE_STRCMP
166 #undef strcmp
167 #define strcmp xstrcmp
169 static inline int
170 strcmp (str1, str2)
171 const char *str1;
172 const char *str2;
174 if (str1 == str2)
175 return 0;
176 if (str1 == 0)
177 return -1;
178 if (str2 == 0)
179 return 1;
181 for (;*str1 && *str2; str1++, str2++)
182 if (*str1 != *str2)
183 break;
185 return (int)(*str1 - *str2);
187 #endif
190 #if ! HAVE_STRCHR
192 # if HAVE_INDEX
194 # define strchr index
196 # else
198 # define strchr xstrchr
200 static inline const char*
201 strchr(str, ch)
202 const char *str;
203 int ch;
205 const char *p;
207 for (p = str; *p != (char)ch && *p != '\0'; p++)
208 /*NOWORK*/;
210 return (*p == (char)ch) ? p : 0;
213 # endif
215 #endif
217 #if ! HAVE_STRRCHR
219 # if HAVE_RINDEX
221 # define strrchr rindex
223 # else
225 # define strrchr xstrrchr
227 static inline const char*
228 strrchr(str, ch)
229 const char *str;
230 int ch;
232 const char *p;
234 for (p = str; *p != '\0'; p++)
235 /*NOWORK*/;
237 while (*p != (char)ch && p >= str)
238 p--;
240 return (*p == (char)ch) ? p : 0;
243 # endif
245 #endif
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__)
253 /* dynamic linking with dlopen/dlsym */
255 #if HAVE_DLFCN_H
256 # include <dlfcn.h>
257 #endif
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
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
291 static lt_module_t
292 sys_dl_open (loader_data, filename)
293 lt_dlloader_data_t loader_data;
294 const char *filename;
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
304 return module;
307 static int
308 sys_dl_close (loader_data, module)
309 lt_dlloader_data_t loader_data;
310 lt_module_t module;
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;
320 return 0;
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;
329 lt_ptr_t address = dlsym(module, symbol);
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;
340 static struct lt_user_dlloader sys_dl = {
341 # ifdef NEED_USCORE
342 "_",
343 # else
345 # endif
346 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
347 #endif
349 #if HAVE_SHL_LOAD
351 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
353 #ifdef HAVE_DL_H
354 #include <dl.h>
355 #endif
357 /* some flags are missing on some systems, so we provide
358 * harmless defaults.
360 * Mandatory:
361 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
362 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
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.
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.
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 */
390 #define LTDL_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
392 static lt_module_t
393 sys_shl_open (loader_data, filename)
394 lt_dlloader_data_t loader_data;
395 const char *filename;
397 lt_module_t module = shl_load(filename, LTDL_BIND_FLAGS, 0L);
398 if (!module) {
399 last_error = LT_DLSTRERROR(CANNOT_OPEN);
401 return module;
404 static int
405 sys_shl_close (loader_data, module)
406 lt_dlloader_data_t loader_data;
407 lt_module_t module;
409 if (shl_unload((shl_t) (module)) != 0) {
410 last_error = LT_DLSTRERROR(CANNOT_CLOSE);
411 return 1;
413 return 0;
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;
422 lt_ptr_t address;
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;
432 static struct lt_user_dlloader
433 sys_shl = { 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 };
435 #undef LTDL_TYPE_TOP
436 #define LTDL_TYPE_TOP &sys_shl
438 #endif
440 #ifdef _WIN32
442 /* dynamic linking for Win32 */
444 #include <windows.h>
446 /* Forward declaration; required to implement handle search below. */
447 static lt_dlhandle handles;
449 static lt_module_t
450 sys_wll_open (loader_data, filename)
451 lt_dlloader_data_t loader_data;
452 const char *filename;
454 lt_dlhandle cur;
455 lt_module_t module;
456 char *searchname = 0;
457 char *ext;
458 char self_name_buf[MAX_PATH];
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;
466 else ext = strrchr(filename, '.');
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;
479 strcpy(searchname, filename);
480 strcat(searchname, ".");
483 module = LoadLibrary(searchname);
484 lt_dlfree(searchname);
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.
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;
500 if (cur->module == module)
501 break;
502 cur = cur->next;
505 if (cur || !module) {
506 last_error = LT_DLSTRERROR(CANNOT_OPEN);
507 return 0;
510 return module;
513 static int
514 sys_wll_close (loader_data, module)
515 lt_dlloader_data_t loader_data;
516 lt_module_t module;
518 if (FreeLibrary(module) == 0) {
519 last_error = LT_DLSTRERROR(CANNOT_CLOSE);
520 return 1;
522 return 0;
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;
531 lt_ptr_t address = GetProcAddress(module, symbol);
533 if (!address)
534 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
535 return address;
538 static struct lt_user_dlloader
539 sys_wll = { 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 };
541 #endif
543 #ifdef __BEOS__
545 /* dynamic linking for BeOS */
547 #include <kernel/image.h>
549 static lt_module_t
550 sys_bedl_open (loader_data, filename)
551 lt_dlloader_data_t loader_data;
552 const char *filename;
554 image_id image = 0;
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);
564 if (image <= 0) {
565 last_error = LT_DLSTRERROR(CANNOT_OPEN);
566 return 0;
569 return (lt_module_t) image;
572 static int
573 sys_bedl_close (loader_data, module)
574 lt_dlloader_data_t loader_data;
575 lt_module_t module;
577 if (unload_add_on((image_id)module) != B_OK) {
578 last_error = LT_DLSTRERROR(CANNOT_CLOSE);
579 return 1;
581 return 0;
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;
590 lt_ptr_t address = 0;
591 image_id image = (image_id)module;
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;
598 return address;
601 static struct lt_user_dlloader
602 sys_bedl = { 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 };
604 #endif
606 #if HAVE_DLD
608 /* dynamic linking with dld */
610 #if HAVE_DLD_H
611 #include <dld.h>
612 #endif
614 static lt_module_t
615 sys_dld_open (loader_data, filename)
616 lt_dlloader_data_t loader_data;
617 const char *filename;
619 lt_module_t module = strdup(filename);
620 if (!module) {
621 last_error = LT_DLSTRERROR(NO_MEMORY);
622 return 0;
624 if (dld_link(filename) != 0) {
625 last_error = LT_DLSTRERROR(CANNOT_OPEN);
626 lt_dlfree(module);
627 return 0;
629 return module;
632 static int
633 sys_dld_close (loader_data, module)
634 lt_dlloader_data_t loader_data;
635 lt_module_t module;
637 if (dld_unlink_by_file((char*)(module), 1) != 0) {
638 last_error = LT_DLSTRERROR(CANNOT_CLOSE);
639 return 1;
641 lt_dlfree(module);
642 return 0;
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;
651 lt_ptr_t address = dld_get_func(symbol);
653 if (!address)
654 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
655 return address;
658 static struct lt_user_dlloader
659 sys_dld = { 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 };
661 #endif
663 /* emulate dynamic linking using preloaded_symbols */
665 typedef struct lt_dlsymlists_t {
666 struct lt_dlsymlists_t *next;
667 const lt_dlsymlist *syms;
668 } lt_dlsymlists_t;
670 static const lt_dlsymlist *default_preloaded_symbols = 0;
671 static lt_dlsymlists_t *preloaded_symbols = 0;
673 static int
674 presym_init (loader_data)
675 lt_dlloader_data_t loader_data;
677 preloaded_symbols = 0;
678 if (default_preloaded_symbols)
679 return lt_dlpreload(default_preloaded_symbols);
680 return 0;
683 static int
684 presym_free_symlists LTDL_PARAMS((void))
686 lt_dlsymlists_t *lists = preloaded_symbols;
688 while (lists) {
689 lt_dlsymlists_t *tmp = lists;
691 lists = lists->next;
692 lt_dlfree(tmp);
694 preloaded_symbols = 0;
695 return 0;
698 static int
699 presym_exit (loader_data)
700 lt_dlloader_data_t loader_data;
702 presym_free_symlists();
703 return 0;
706 static int
707 presym_add_symlist (preloaded)
708 const lt_dlsymlist *preloaded;
710 lt_dlsymlists_t *tmp;
711 lt_dlsymlists_t *lists = preloaded_symbols;
713 while (lists) {
714 if (lists->syms == preloaded)
715 return 0;
716 lists = lists->next;
719 tmp = (lt_dlsymlists_t*) lt_dlmalloc(sizeof(lt_dlsymlists_t));
720 if (!tmp) {
721 last_error = LT_DLSTRERROR(NO_MEMORY);
722 return 1;
724 tmp->syms = preloaded;
725 tmp->next = preloaded_symbols;
726 preloaded_symbols = tmp;
727 return 0;
730 static lt_module_t
731 presym_open (loader_data, filename)
732 lt_dlloader_data_t loader_data;
733 const char *filename;
735 lt_dlsymlists_t *lists = preloaded_symbols;
737 if (!lists) {
738 last_error = LT_DLSTRERROR(NO_SYMBOLS);
739 return 0;
741 if (!filename)
742 filename = "@PROGRAM@";
743 while (lists) {
744 const lt_dlsymlist *syms = lists->syms;
746 while (syms->name) {
747 if (!syms->address &&
748 strcmp(syms->name, filename) == 0) {
749 return (lt_module_t) syms;
751 syms++;
753 lists = lists->next;
755 last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
756 return 0;
759 static int
760 presym_close (loader_data, module)
761 lt_dlloader_data_t loader_data;
762 lt_module_t module;
764 /* Just to silence gcc -Wall */
765 module = 0;
766 return 0;
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;
775 lt_dlsymlist *syms = (lt_dlsymlist*)(module);
777 syms++;
778 while (syms->address) {
779 if (strcmp(syms->name, symbol) == 0)
780 return syms->address;
781 syms++;
783 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
784 return 0;
787 static struct lt_user_dlloader
788 presym = { 0, presym_open, presym_close, presym_sym, presym_exit, 0 };
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;
797 lt_dlinit LTDL_PARAMS((void))
799 /* initialize libltdl */
800 int errors = 0;
802 if (initialized) { /* Initialize only at first call. */
803 initialized++;
804 return 0;
806 handles = 0;
807 user_search_path = 0; /* empty search path */
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;
830 if (errors != 0) {
831 last_error = LT_DLSTRERROR(DLOPEN_NOT_SUPPORTED);
832 return 1;
834 last_error = 0;
835 initialized = 1;
836 return 0;
840 lt_dlpreload (preloaded)
841 const lt_dlsymlist *preloaded;
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;
852 lt_dlpreload_default (preloaded)
853 const lt_dlsymlist *preloaded;
855 default_preloaded_symbols = preloaded;
856 return 0;
860 lt_dlexit LTDL_PARAMS((void))
862 /* shut down libltdl */
863 lt_dlloader_t *loader = loaders;
864 int errors, level;
866 if (!initialized) {
867 last_error = LT_DLSTRERROR(SHUTDOWN);
868 return 1;
870 if (initialized != 1) { /* shut down only at last call. */
871 initialized--;
872 return 0;
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++;
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;
896 initialized = 0;
897 return errors;
900 static int
901 tryall_dlopen (handle, filename)
902 lt_dlhandle *handle;
903 const char *filename;
905 lt_dlhandle cur = handles;
906 lt_dlloader_t *loader = loaders;
907 const char *saved_error = last_error;
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;
920 if (cur) {
921 cur->info.ref_count++;
922 *handle = cur;
923 return 0;
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;
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;
942 if (!loader) {
943 if (cur->info.filename)
944 lt_dlfree(cur->info.filename);
945 return 1;
947 cur->loader = loader;
948 last_error = saved_error;
949 return 0;
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;
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;
978 sprintf (filename, "%s/%s", libdir, dlname);
979 error = tryall_dlopen(handle, filename) != 0;
980 lt_dlfree(filename);
981 if (!error)
982 return 0;
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;
993 if (dir)
994 strcpy(filename, dir);
995 else
996 *filename = 0;
997 strcat(filename, objdir);
998 strcat(filename, dlname);
1000 error = tryall_dlopen(handle, filename) != 0;
1001 lt_dlfree(filename);
1002 if (!error)
1003 return 0;
1005 /* maybe it was moved to another directory */
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;
1021 return 1;
1024 static char*
1025 canonicalize_path (path)
1026 const char *path;
1028 char *canonical = 0;
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
1040 return canonical;
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;
1050 /* when handle != NULL search a library, otherwise a file */
1051 /* return NULL on failure, otherwise the file/handle */
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;
1059 if (!search_path || !*search_path) {
1060 last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
1061 return 0;
1063 canonical = canonicalize_path (search_path);
1064 if (!canonical) {
1065 last_error = LT_DLSTRERROR(NO_MEMORY);
1066 goto cleanup;
1068 next = canonical;
1069 while (next) {
1070 int lendir;
1071 char *cur = next;
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;
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;
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;
1116 result = (lt_ptr_t) file;
1117 goto cleanup;
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;
1130 static int
1131 load_deplibs(handle, deplibs)
1132 lt_dlhandle handle;
1133 char *deplibs;
1135 char *p, *save_search_path;
1136 int i;
1137 int ret = 1, depcount = 0;
1138 char **names = 0;
1139 lt_dlhandle *handles = 0;
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;
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++;
1168 if (!depcount) {
1169 ret = 0;
1170 goto cleanup;
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;
1203 p = end;
1204 } else
1205 p++;
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;
1217 handles[i] = handle;
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;
1238 static int
1239 unload_deplibs(handle)
1240 lt_dlhandle handle;
1242 int i;
1243 int errors = 0;
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;
1252 static inline int
1253 trim (dest, str)
1254 char **dest;
1255 const char *str;
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);
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;
1271 strncpy(tmp, &str[1], (end - str) - 1);
1272 tmp[len-3] = '\0';
1273 *dest = tmp;
1274 } else
1275 *dest = 0;
1276 return 0;
1279 static inline int
1280 free_vars( dlname, oldname, libdir, deplibs)
1281 char *dlname;
1282 char *oldname;
1283 char *libdir;
1284 char *deplibs;
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;
1297 lt_dlhandle
1298 lt_dlopen (filename)
1299 const char *filename;
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;
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;
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;
1320 goto register_handle;
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;
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;
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;
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;
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
1397 if (!file) {
1398 handle = 0;
1399 goto cleanup;
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;
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;
1463 if (error)
1464 break;
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;
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;
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;
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;
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;
1533 register_handle:
1534 if (newhandle != handle) {
1535 lt_dlfree(handle);
1536 handle = newhandle;
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' */
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;
1556 lt_dlhandle
1557 lt_dlopenext (filename)
1558 const char *filename;
1560 lt_dlhandle handle;
1561 char *tmp;
1562 int len;
1563 const char *saved_error = last_error;
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;
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;
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;
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;
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;
1609 #endif
1610 last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
1611 lt_dlfree(tmp);
1612 return 0;
1616 lt_dlclose (handle)
1617 lt_dlhandle handle;
1619 lt_dlhandle cur, last;
1621 /* check whether the handle is valid */
1622 last = cur = handles;
1623 while (cur && handle != cur) {
1624 last = cur;
1625 cur = cur->next;
1627 if (!cur) {
1628 last_error = LT_DLSTRERROR(INVALID_HANDLE);
1629 return 1;
1631 handle->info.ref_count--;
1632 if (!handle->info.ref_count) {
1633 int error;
1634 lt_dlloader_data_t data = handle->loader->dlloader_data;
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;
1649 return 0;
1652 lt_ptr_t
1653 lt_dlsym (handle, symbol)
1654 lt_dlhandle handle;
1655 const char *symbol;
1657 int lensym;
1658 char lsym[LTDL_SYMBOL_LENGTH];
1659 char *sym;
1660 lt_ptr_t address;
1661 lt_dlloader_data_t data;
1663 if (!handle) {
1664 last_error = LT_DLSTRERROR(INVALID_HANDLE);
1665 return 0;
1667 if (!symbol) {
1668 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
1669 return 0;
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;
1684 data = handle->loader->dlloader_data;
1685 if (handle->info.name) {
1686 const char *saved_error = last_error;
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;
1703 last_error = saved_error;
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;
1717 const char *
1718 lt_dlerror LTDL_PARAMS((void))
1720 const char *error = last_error;
1722 last_error = 0;
1723 return error;
1727 lt_dladdsearchdir (search_dir)
1728 const char *search_dir;
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;
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;
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;
1751 return 0;
1755 lt_dlsetsearchpath (search_path)
1756 const char *search_path;
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;
1769 const char *
1770 lt_dlgetsearchpath LTDL_PARAMS((void))
1772 return user_search_path;
1775 const lt_dlinfo *
1776 lt_dlgetinfo (handle)
1777 lt_dlhandle handle;
1779 if (!handle) {
1780 last_error = LT_DLSTRERROR(INVALID_HANDLE);
1781 return 0;
1783 return &(handle->info);
1787 lt_dlforeach (func, data)
1788 int (*func) LTDL_PARAMS((lt_dlhandle handle, lt_ptr_t data));
1789 lt_ptr_t data;
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;
1798 return 0;
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;
1807 lt_dlloader_t *node = 0, *ptr = 0;
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;
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;
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;
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*/;
1850 if (ptr->next != place) {
1851 last_error = LT_DLSTRERROR(INVALID_LOADER);
1852 return 1;
1855 /* Insert NODE between PTR and PLACE. */
1856 node->next = place;
1857 ptr->next = node;
1860 return 0;
1864 lt_dlloader_remove (loader_name)
1865 const char *loader_name;
1867 lt_dlloader_t *place = lt_dlloader_find (loader_name);
1868 lt_dlhandle handle;
1869 int result = 0;
1871 if (!place) {
1872 last_error = LT_DLSTRERROR(INVALID_LOADER);
1873 return 1;
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;
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;
1893 place = prev->next;
1894 prev->next = prev->next->next;
1896 if (place->dlloader_exit)
1897 result = place->dlloader_exit (place->dlloader_data);
1898 lt_dlfree (place);
1900 return result;
1903 lt_dlloader_t *
1904 lt_dlloader_next (place)
1905 lt_dlloader_t *place;
1907 return place ? place->next : loaders;
1910 const char *
1911 lt_dlloader_name (place)
1912 lt_dlloader_t *place;
1914 if (!place)
1915 last_error = LT_DLSTRERROR(INVALID_LOADER);
1916 return place ? place->loader_name : 0;
1919 lt_dlloader_data_t *
1920 lt_dlloader_data (place)
1921 lt_dlloader_t *place;
1923 if (!place)
1924 last_error = LT_DLSTRERROR(INVALID_LOADER);
1925 return place ? &(place->dlloader_data) : 0;
1928 lt_dlloader_t *
1929 lt_dlloader_find (loader_name)
1930 const char *loader_name;
1932 lt_dlloader_t *place = 0;
1934 for (place = loaders; place; place = place->next)
1935 if (strcmp (place->loader_name, loader_name) == 0)
1936 break;
1938 return place;
1941 static const char **user_error_strings = 0;
1942 static int errorcode = LTDL_ERROR_MAX;
1945 lt_dladderror (diagnostic)
1946 const char *diagnostic;
1948 int index = errorcode - LTDL_ERROR_MAX;
1949 const char **temp = 0;
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;
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];
1964 lt_dlfree (user_error_strings);
1965 user_error_strings = temp;
1966 return errorcode++;
1970 lt_dlseterror (index)
1971 int index;
1973 if (index >= errorcode || index < 0) {
1974 last_error = LT_DLSTRERROR(INVALID_ERRORCODE);
1975 return 1;
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];
1983 return 0;