OSDN Git Service

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