OSDN Git Service

* config/h8300/h8300.md: Fix a comment typo.
[pf3gnuchains/gcc-fork.git] / libjava / libltdl / ltdl.c
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 }