fd7fc28b92276bdf37578cf1e585782308dc360a
[freeradius.git] / libltdl / ltdl.c
1 /* ltdl.c -- system independent dlopen wrapper
2    Copyright (C) 1998-1999 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 Library 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 Library General Public License,
12 if you distribute this file as part of a program that uses GNU libtool
13 to create libraries and programs, 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 Library General Public License for more details.
20
21 You should have received a copy of the GNU Library 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 #define _LTDL_COMPILE_
28
29 #if HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32
33 #if HAVE_STRING_H
34 #include <string.h>
35 #endif
36
37 #if HAVE_STRINGS_H
38 #include <strings.h>
39 #endif
40
41 #if HAVE_CTYPE_H
42 #include <ctype.h>
43 #endif
44
45 #if HAVE_MALLOC_H
46 #include <malloc.h>
47 #endif
48
49 #if HAVE_MEMORY_H
50 #include <memory.h>
51 #endif
52
53 #if HAVE_STDLIB_H
54 #include <stdlib.h>
55 #endif
56
57 #if HAVE_STDIO_H
58 #include <stdio.h>
59 #endif
60
61 #include "ltdl.h"
62
63 /* max. filename length */
64 #ifndef LTDL_FILENAME_MAX
65 #define LTDL_FILENAME_MAX 1024
66 #endif
67
68 #undef  LTDL_READTEXT_MODE
69 /* fopen() mode flags for reading a text file */
70 #ifdef _WIN32
71 #define LTDL_READTEXT_MODE "rt"
72 #else
73 #define LTDL_READTEXT_MODE "r"
74 #endif
75
76 #undef  LTDL_SYMBOL_LENGTH
77 /* This is the maximum symbol size that won't require malloc/free */
78 #define LTDL_SYMBOL_LENGTH      128
79
80 #undef  LTDL_SYMBOL_OVERHEAD
81 /* This accounts for the _LTX_ separator */
82 #define LTDL_SYMBOL_OVERHEAD    5
83
84 static const char objdir[] = LTDL_OBJDIR;
85 #ifdef  LTDL_SHLIB_EXT
86 static const char shlib_ext[] = LTDL_SHLIB_EXT;
87 #endif
88
89 static const char unknown_error[] = "unknown error";
90 static const char dlopen_not_supported_error[] = "dlopen support not available";
91 static const char file_not_found_error[] = "file not found";
92 static const char no_symbols_error[] = "no symbols defined";
93 static const char cannot_open_error[] = "can't open the module";
94 static const char cannot_close_error[] = "can't close the module";
95 static const char symbol_error[] = "symbol not found";
96 static const char memory_error[] = "not enough memory";
97 static const char invalid_handle_error[] = "invalid handle";
98 static const char buffer_overflow_error[] = "internal buffer overflow";
99 static const char shutdown_error[] = "library already shutdown";
100
101 #ifndef HAVE_PRELOADED_SYMBOLS
102 /* If libtool won't define it, we'd better do */
103 const lt_dlsymlist lt_preloaded_symbols[1] = { { 0, 0 } };
104 #endif
105
106 static const char *last_error = 0;
107
108 lt_ptr_t (*lt_dlmalloc) LTDL_PARAMS((size_t size)) = (lt_ptr_t(*)LTDL_PARAMS((size_t)))malloc;
109 void     (*lt_dlfree)  LTDL_PARAMS((lt_ptr_t ptr)) = (void(*)LTDL_PARAMS((lt_ptr_t)))free;
110
111 typedef struct lt_dltype_t {
112         struct lt_dltype_t *next;
113         const char *sym_prefix; /* prefix for symbols */
114         int (*mod_init) LTDL_PARAMS((void));
115         int (*mod_exit) LTDL_PARAMS((void));
116         int (*lib_open) LTDL_PARAMS((lt_dlhandle handle, const char *filename));
117         int (*lib_close) LTDL_PARAMS((lt_dlhandle handle));
118         lt_ptr_t (*find_sym) LTDL_PARAMS((lt_dlhandle handle, const char *symbol));
119 } lt_dltype_t;
120
121 #define LTDL_TYPE_TOP 0
122
123 typedef struct lt_dlhandle_t {
124         struct lt_dlhandle_t *next;
125         lt_dltype_t *type;      /* dlopening interface */
126         char    *filename;      /* file name */
127         char    *name;          /* module name */
128         int     usage;          /* usage */
129         int     depcount;       /* number of dependencies */
130         lt_dlhandle *deplibs;   /* dependencies */
131         lt_ptr_t handle;        /* system handle */
132         lt_ptr_t system;        /* system specific data */
133 } lt_dlhandle_t;
134
135 #undef strdup
136 #define strdup xstrdup
137
138 static inline char *
139 strdup(str)
140         const char *str;
141 {
142         char *tmp;
143
144         if (!str)
145                 return 0;
146         tmp = (char*) lt_dlmalloc(strlen(str)+1);
147         if (tmp)
148                 strcpy(tmp, str);
149         return tmp;
150 }
151
152 #if ! HAVE_STRCHR
153
154 # if HAVE_INDEX
155
156 #  define strchr index
157
158 # else
159
160 #  define strchr xstrchr
161
162 static inline const char*
163 strchr(str, ch)
164         const char *str;
165         int ch;
166 {
167         const char *p;
168
169         for (p = str; *p != (char)ch && *p != '\0'; p++)
170                 /*NOWORK*/;
171
172         return (*p == (char)ch) ? p : 0;
173 }
174
175 # endif
176
177 #endif
178
179 #if ! HAVE_STRRCHR
180
181 # if HAVE_RINDEX
182
183 #  define strrchr rindex
184
185 # else
186
187 #  define strrchr xstrrchr
188
189 static inline const char*
190 strrchr(str, ch)
191         const char *str;
192         int ch;
193 {
194         const char *p;
195
196         for (p = str; *p != '\0'; p++)
197                 /*NOWORK*/;
198
199         while (*p != (char)ch && p >= str)
200                 p--;
201
202         return (*p == (char)ch) ? p : 0;
203 }
204
205 # endif
206
207 #endif
208
209 #if HAVE_LIBDL
210
211 /* dynamic linking with dlopen/dlsym */
212
213 #if HAVE_DLFCN_H
214 # include <dlfcn.h>
215 #endif
216
217 #ifdef RTLD_GLOBAL
218 # define LTDL_GLOBAL    RTLD_GLOBAL
219 #else
220 # ifdef DL_GLOBAL
221 #  define LTDL_GLOBAL   DL_GLOBAL
222 # else
223 #  define LTDL_GLOBAL   0
224 # endif
225 #endif
226
227 /* We may have to define LTDL_LAZY_OR_NOW in the command line if we
228    find out it does not work in some platform. */
229 #ifndef LTDL_LAZY_OR_NOW
230 # ifdef RTLD_LAZY
231 #  define LTDL_LAZY_OR_NOW      RTLD_LAZY
232 # else
233 #  ifdef DL_LAZY
234 #   define LTDL_LAZY_OR_NOW     DL_LAZY
235 #  else
236 #   ifdef RTLD_NOW
237 #    define LTDL_LAZY_OR_NOW    RTLD_NOW
238 #   else
239 #    ifdef DL_NOW
240 #     define LTDL_LAZY_OR_NOW   DL_NOW
241 #    else
242 #     define LTDL_LAZY_OR_NOW   0
243 #    endif
244 #   endif
245 #  endif
246 # endif
247 #endif
248
249 static int
250 sys_dl_init LTDL_PARAMS((void))
251 {
252         return 0;
253 }
254
255 static int
256 sys_dl_exit LTDL_PARAMS((void))
257 {
258         return 0;
259 }
260
261 static int
262 sys_dl_open (handle, filename)
263         lt_dlhandle handle;
264         const char *filename;
265 {
266         handle->handle = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW);
267         if (!handle->handle) {
268 #if HAVE_DLERROR
269                 last_error = dlerror();
270 #else
271                 last_error = cannot_open_error;
272 #endif
273                 return 1;
274         }
275         return 0;
276 }
277
278 static int
279 sys_dl_close (handle)
280         lt_dlhandle handle;
281 {
282         if (dlclose(handle->handle) != 0) {
283 #if HAVE_DLERROR
284                 last_error = dlerror();
285 #else
286                 last_error = cannot_close_error;
287 #endif
288                 return 1;
289         }
290         return 0;
291 }
292
293 static lt_ptr_t
294 sys_dl_sym (handle, symbol)
295         lt_dlhandle handle;
296         const char *symbol;
297 {
298         lt_ptr_t address = dlsym(handle->handle, symbol);
299         
300         if (!address)
301 #if HAVE_DLERROR
302                 last_error = dlerror();
303 #else
304                 last_error = symbol_error;
305 #endif
306         return address;
307 }
308
309 static
310 lt_dltype_t
311 #ifdef NEED_USCORE
312 sys_dl = { LTDL_TYPE_TOP, "_", sys_dl_init, sys_dl_exit,
313         sys_dl_open, sys_dl_close, sys_dl_sym };
314 #else
315 sys_dl = { LTDL_TYPE_TOP, 0, sys_dl_init, sys_dl_exit,
316         sys_dl_open, sys_dl_close, sys_dl_sym };
317 #endif
318
319 #undef LTDL_TYPE_TOP
320 #define LTDL_TYPE_TOP &sys_dl
321
322 #endif
323
324 #if HAVE_SHL_LOAD
325
326 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
327
328 #ifdef HAVE_DL_H
329 #include <dl.h>
330 #endif
331
332 /* some flags are missing on some systems, so we provide
333  * harmless defaults.
334  *
335  * Mandatory:
336  * BIND_IMMEDIATE  - Resolve symbol references when the library is loaded.
337  * BIND_DEFERRED   - Delay code symbol resolution until actual reference.
338  *
339  * Optionally:
340  * BIND_FIRST      - Place the library at the head of the symbol search order.
341  * BIND_NONFATAL   - The default BIND_IMMEDIATE behavior is to treat all unsatisfied
342  *                   symbols as fatal.  This flag allows binding of unsatisfied code
343  *                   symbols to be deferred until use.
344  *                   [Perl: For certain libraries, like DCE, deferred binding often
345  *                   causes run time problems.  Adding BIND_NONFATAL to BIND_IMMEDIATE
346  *                   still allows unresolved references in situations like this.]
347  * BIND_NOSTART    - Do not call the initializer for the shared library when the
348  *                   library is loaded, nor on a future call to shl_unload().
349  * BIND_VERBOSE    - Print verbose messages concerning possible unsatisfied symbols.
350  *
351  * hp9000s700/hp9000s800:
352  * BIND_RESTRICTED - Restrict symbols visible by the library to those present at
353  *                   library load time.
354  * DYNAMIC_PATH    - Allow the loader to dynamically search for the library specified
355  *                   by the path argument.
356  */
357
358 #ifndef DYNAMIC_PATH
359 #define DYNAMIC_PATH    0
360 #endif  /* DYNAMIC_PATH */
361 #ifndef BIND_RESTRICTED
362 #define BIND_RESTRICTED 0
363 #endif  /* BIND_RESTRICTED */
364
365 #define LTDL_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
366
367 static int
368 sys_shl_init LTDL_PARAMS((void))
369 {
370         return 0;
371 }
372
373 static int
374 sys_shl_exit LTDL_PARAMS((void))
375 {
376         return 0;
377 }
378
379 static int
380 sys_shl_open (handle, filename)
381         lt_dlhandle handle;
382         const char *filename;
383 {
384         handle->handle = shl_load(filename, LTDL_BIND_FLAGS, 0L);
385         if (!handle->handle) {
386                 last_error = cannot_open_error;
387                 return 1;
388         }
389         return 0;
390 }
391
392 static int
393 sys_shl_close (handle)
394         lt_dlhandle handle;
395 {
396         if (shl_unload((shl_t) (handle->handle)) != 0) {
397                 last_error = cannot_close_error;
398                 return 1;
399         }
400         return 0;
401 }
402
403 static lt_ptr_t
404 sys_shl_sym (handle, symbol)
405         lt_dlhandle handle;
406         const char *symbol;
407 {
408         lt_ptr_t address;
409
410         if (handle->handle && shl_findsym((shl_t*) &(handle->handle),
411             symbol, TYPE_UNDEFINED, &address) == 0)
412                 if (address)
413                         return address;
414         last_error = symbol_error;
415         return 0;
416 }
417
418 static
419 lt_dltype_t
420 sys_shl = { LTDL_TYPE_TOP, 0, sys_shl_init, sys_shl_exit,
421         sys_shl_open, sys_shl_close, sys_shl_sym };
422
423 #undef LTDL_TYPE_TOP
424 #define LTDL_TYPE_TOP &sys_shl
425
426 #endif
427
428 #if HAVE_DLD
429
430 /* dynamic linking with dld */
431
432 #if HAVE_DLD_H
433 #include <dld.h>
434 #endif
435
436 static int
437 sys_dld_init LTDL_PARAMS((void))
438 {
439         return 0;
440 }
441
442 static int
443 sys_dld_exit LTDL_PARAMS((void))
444 {
445         return 0;
446 }
447
448 static int
449 sys_dld_open (handle, filename)
450         lt_dlhandle handle;
451         const char *filename;
452 {
453         handle->handle = strdup(filename);
454         if (!handle->handle) {
455                 last_error = memory_error;
456                 return 1;
457         }
458         if (dld_link(filename) != 0) {
459                 last_error = cannot_open_error;
460                 lt_dlfree(handle->handle);
461                 return 1;
462         }
463         return 0;
464 }
465
466 static int
467 sys_dld_close (handle)
468         lt_dlhandle handle;
469 {
470         if (dld_unlink_by_file((char*)(handle->handle), 1) != 0) {
471                 last_error = cannot_close_error;
472                 return 1;
473         }
474         lt_dlfree(handle->filename);
475         return 0;
476 }
477
478 static lt_ptr_t
479 sys_dld_sym (handle, symbol)
480         lt_dlhandle handle;
481         const char *symbol;
482 {
483         lt_ptr_t address = dld_get_func(symbol);
484         
485         if (!address)
486                 last_error = symbol_error;
487         return address;
488 }
489
490 static
491 lt_dltype_t
492 sys_dld = { LTDL_TYPE_TOP, 0, sys_dld_init, sys_dld_exit,
493         sys_dld_open, sys_dld_close, sys_dld_sym };
494
495 #undef LTDL_TYPE_TOP
496 #define LTDL_TYPE_TOP &sys_dld
497
498 #endif
499
500 #ifdef _WIN32
501
502 /* dynamic linking for Win32 */
503
504 #include <windows.h>
505
506 static int
507 sys_wll_init LTDL_PARAMS((void))
508 {
509         return 0;
510 }
511
512 static int
513 sys_wll_exit LTDL_PARAMS((void))
514 {
515         return 0;
516 }
517
518 /* Forward declaration; required to implement handle search below. */
519 static lt_dlhandle handles;
520
521 static int
522 sys_wll_open (handle, filename)
523         lt_dlhandle handle;
524         const char *filename;
525 {
526         lt_dlhandle cur;
527         char *searchname = NULL;
528         char *ext = strrchr(filename, '.');
529
530         if (ext) {
531                 /* FILENAME already has an extension. */
532                 searchname = strdup(filename);
533         } else {
534                 /* Append a `.' to stop Windows from adding an
535                    implicit `.dll' extension. */
536                 searchname = (char*)lt_dlmalloc(2+ strlen(filename));
537                 strcpy(searchname, filename);
538                 strcat(searchname, ".");
539         }
540     
541         handle->handle = LoadLibrary(searchname);
542         lt_dlfree(searchname);
543         
544         /* libltdl expects this function to fail if it is unable
545            to physically load the library.  Sadly, LoadLibrary
546            will search the loaded libraries for a match and return
547            one of them if the path search load fails.
548
549            We check whether LoadLibrary is returning a handle to
550            an already loaded module, and simulate failure if we
551            find one. */
552         cur = handles;
553         while (cur) {
554                 if (!cur->handle) {
555                         cur = 0;
556                         break;
557                 }
558                 if (cur->handle == handle->handle)
559                         break;
560                 cur = cur->next;
561         }
562
563         if (cur || !handle->handle) {
564                 last_error = cannot_open_error;
565                 return 1;
566         }
567
568         return 0;
569 }
570
571 static int
572 sys_wll_close (handle)
573         lt_dlhandle handle;
574 {
575         if (FreeLibrary(handle->handle) == 0) {
576                 last_error = cannot_close_error;
577                 return 1;
578         }
579         return 0;
580 }
581
582 static lt_ptr_t
583 sys_wll_sym (handle, symbol)
584         lt_dlhandle handle;
585         const char *symbol;
586 {
587         lt_ptr_t address = GetProcAddress(handle->handle, symbol);
588         
589         if (!address)
590                 last_error = symbol_error;
591         return address;
592 }
593
594 static
595 lt_dltype_t
596 sys_wll = { LTDL_TYPE_TOP, 0, sys_wll_init, sys_wll_exit,
597         sys_wll_open, sys_wll_close, sys_wll_sym };
598
599 #undef LTDL_TYPE_TOP
600 #define LTDL_TYPE_TOP &sys_wll
601
602 #endif
603
604 #ifdef __BEOS__
605
606 /* dynamic linking for BeOS */
607
608 #include <kernel/image.h>
609
610 static int
611 sys_bedl_init LTDL_PARAMS((void))
612 {
613         return 0;
614 }
615
616 static int
617 sys_bedl_exit LTDL_PARAMS((void))
618 {
619         return 0;
620 }
621
622 static int
623 sys_bedl_open (handle, filename)
624         lt_dlhandle handle;
625         const char *filename;
626 {
627         image_id image = 0;
628         
629         if (filename) {
630                 image = load_add_on(filename);
631         } else {
632                 image_info info; 
633                 int32 cookie = 0; 
634                 if (get_next_image_info(0, &cookie, &info) == B_OK)
635                         image = load_add_on(info.name);
636         }
637         if (image <= 0) {
638                 last_error = cannot_open_error;
639                 return 1;
640         }
641         handle->handle = (void*) image;
642         return 0;
643 }
644
645 static int
646 sys_bedl_close (handle)
647         lt_dlhandle handle;
648 {
649         if (unload_add_on((image_id)handle->handle) != B_OK) {
650                 last_error = cannot_close_error;
651                 return 1;
652         }
653         return 0;
654 }
655
656 static lt_ptr_t
657 sys_bedl_sym (handle, symbol)
658         lt_dlhandle handle;
659         const char *symbol;
660 {
661         lt_ptr_t address = 0;
662         image_id image = (image_id)handle->handle;
663    
664         if (get_image_symbol(image, symbol, B_SYMBOL_TYPE_ANY,
665                 &address) != B_OK) {
666                 last_error = symbol_error;
667                 return 0;
668         }
669         return address;
670 }
671
672 static
673 lt_dltype_t
674 sys_bedl = { LTDL_TYPE_TOP, 0, sys_bedl_init, sys_bedl_exit,
675         sys_bedl_open, sys_bedl_close, sys_bedl_sym };
676
677 #undef LTDL_TYPE_TOP
678 #define LTDL_TYPE_TOP &sys_bedl
679
680 #endif
681
682 /* emulate dynamic linking using preloaded_symbols */
683
684 typedef struct lt_dlsymlists_t {
685         struct lt_dlsymlists_t *next;
686         const lt_dlsymlist *syms;
687 } lt_dlsymlists_t;
688
689 static const lt_dlsymlist *default_preloaded_symbols = 0;
690 static lt_dlsymlists_t *preloaded_symbols = 0;
691
692 static int
693 presym_init LTDL_PARAMS((void))
694 {
695         preloaded_symbols = 0;
696         if (default_preloaded_symbols)
697                 return lt_dlpreload(default_preloaded_symbols);
698         return 0;
699 }
700
701 static int
702 presym_free_symlists LTDL_PARAMS((void))
703 {
704         lt_dlsymlists_t *lists = preloaded_symbols;
705         
706         while (lists) {
707                 lt_dlsymlists_t *tmp = lists;
708                 
709                 lists = lists->next;
710                 lt_dlfree(tmp);
711         }
712         preloaded_symbols = 0;
713         return 0;
714 }
715
716 static int
717 presym_exit LTDL_PARAMS((void))
718 {
719         presym_free_symlists();
720         return 0;
721 }
722
723 static int
724 presym_add_symlist (preloaded)
725         const lt_dlsymlist *preloaded;
726 {
727         lt_dlsymlists_t *tmp;
728         lt_dlsymlists_t *lists = preloaded_symbols;
729         
730         while (lists) {
731                 if (lists->syms == preloaded)
732                         return 0;
733                 lists = lists->next;
734         }
735
736         tmp = (lt_dlsymlists_t*) lt_dlmalloc(sizeof(lt_dlsymlists_t));
737         if (!tmp) {
738                 last_error = memory_error;
739                 return 1;
740         }
741         tmp->syms = preloaded;
742         tmp->next = 0;
743         if (!preloaded_symbols)
744                 preloaded_symbols = tmp;
745         else {
746                 /* append to the end */
747                 lists = preloaded_symbols;
748                 while (lists->next)
749                         lists = lists->next;
750                 lists->next = tmp;
751         }
752         return 0;
753 }
754
755 static int
756 presym_open (handle, filename)
757         lt_dlhandle handle;
758         const char *filename;
759 {
760         lt_dlsymlists_t *lists = preloaded_symbols;
761
762         if (!lists) {
763                 last_error = no_symbols_error;
764                 return 1;
765         }
766         if (!filename)
767                 filename = "@PROGRAM@";
768         while (lists) {
769                 const lt_dlsymlist *syms = lists->syms;
770         
771                 while (syms->name) {
772                         if (!syms->address &&
773                             strcmp(syms->name, filename) == 0) {
774                                 handle->handle = (lt_ptr_t) syms;
775                                 return 0;
776                         }
777                         syms++;
778                 }
779                 lists = lists->next;
780         }
781         last_error = file_not_found_error;
782         return 1;
783 }
784
785 static int
786 presym_close (handle)
787         lt_dlhandle handle;
788 {
789         /* Just to silence gcc -Wall */
790         handle = 0;
791         return 0;
792 }
793
794 static lt_ptr_t
795 presym_sym (handle, symbol)
796         lt_dlhandle handle;
797         const char *symbol;
798 {
799         lt_dlsymlist *syms = (lt_dlsymlist*)(handle->handle);
800
801         syms++;
802         while (syms->address) {
803                 if (strcmp(syms->name, symbol) == 0)
804                         return syms->address;
805                 syms++;
806         }
807         last_error = symbol_error;
808         return 0;
809 }
810
811 static
812 lt_dltype_t
813 presym = { LTDL_TYPE_TOP, 0, presym_init, presym_exit,
814            presym_open, presym_close, presym_sym };
815
816 #undef LTDL_TYPE_TOP
817 #define LTDL_TYPE_TOP &presym
818
819 static char *user_search_path = 0;
820 static lt_dlhandle handles = 0;
821 static int initialized = 0;
822
823 static lt_dltype_t *types = LTDL_TYPE_TOP;
824 #undef LTDL_TYPE_TOP
825
826 int
827 lt_dlinit LTDL_PARAMS((void))
828 {
829         /* initialize libltdl */
830         lt_dltype_t **type = &types;
831         int typecount = 0;
832
833         if (initialized) {      /* Initialize only at first call. */
834                 initialized++;
835                 return 0;
836         }
837         handles = 0;
838         user_search_path = 0; /* empty search path */
839
840         while (*type) {
841                 if ((*type)->mod_init())
842                         *type = (*type)->next; /* Remove it from the list */
843                 else {
844                         type = &(*type)->next; /* Keep it */
845                         typecount++;
846                 }
847         }
848         if (typecount == 0) {
849                 last_error = dlopen_not_supported_error;
850                 return 1;
851         }
852         last_error = 0;
853         initialized = 1;
854         return 0;
855 }
856
857 int
858 lt_dlpreload (preloaded)
859         const lt_dlsymlist *preloaded;
860 {
861         if (preloaded)
862                 return presym_add_symlist(preloaded);
863         presym_free_symlists();
864         if (default_preloaded_symbols)
865                 return lt_dlpreload(default_preloaded_symbols);
866         return 0;
867 }
868
869 int
870 lt_dlpreload_default (preloaded)
871         const lt_dlsymlist *preloaded;
872 {
873         default_preloaded_symbols = preloaded;
874         return 0;
875 }
876
877 int
878 lt_dlexit LTDL_PARAMS((void))
879 {
880         /* shut down libltdl */
881         lt_dltype_t *type = types;
882         int     errors;
883         
884         if (!initialized) {
885                 last_error = shutdown_error;
886                 return 1;
887         }
888         if (initialized != 1) { /* shut down only at last call. */
889                 initialized--;
890                 return 0;
891         }
892         /* close all modules */
893         errors = 0;
894         while (handles) {
895                 /* FIXME: what if a module depends on another one? */
896                 if (lt_dlclose(handles))
897                         errors++;
898         }
899         initialized = 0;
900         while (type) {
901                 if (type->mod_exit())
902                         errors++;
903                 type = type->next;
904         }
905         return errors;
906 }
907
908 static int
909 tryall_dlopen (handle, filename)
910         lt_dlhandle *handle;
911         const char *filename;
912 {
913         lt_dlhandle cur;
914         lt_dltype_t *type = types;
915         const char *saved_error = last_error;
916         
917         /* check whether the module was already opened */
918         cur = handles;
919         while (cur) {
920                 if (!cur->filename && !filename)
921                         break;
922                 if (cur->filename && filename && 
923                     strcmp(cur->filename, filename) == 0)
924                         break;
925                 cur = cur->next;
926         }
927         if (cur) {
928                 cur->usage++;
929                 *handle = cur;
930                 return 0;
931         }
932         
933         cur = *handle;
934         if (filename) {
935                 cur->filename = strdup(filename);
936                 if (!cur->filename) {
937                         last_error = memory_error;
938                         return 1;
939                 }
940         } else
941                 cur->filename = 0;
942         while (type) {
943                 if (type->lib_open(cur, filename) == 0)
944                         break;
945                 type = type->next;
946         }
947         if (!type) {
948                 if (cur->filename)
949                         lt_dlfree(cur->filename);
950                 return 1;
951         }
952         cur->type = type;
953         last_error = saved_error;
954         return 0;
955 }
956
957 static int
958 find_module (handle, dir, libdir, dlname, old_name, installed)
959         lt_dlhandle *handle;
960         const char *dir;
961         const char *libdir;
962         const char *dlname;
963         const char *old_name;
964         int installed;
965 {
966         int     error;
967         char    *filename;
968         /* try to open the old library first; if it was dlpreopened, 
969            we want the preopened version of it, even if a dlopenable
970            module is available */
971         if (old_name && tryall_dlopen(handle, old_name) == 0)
972                 return 0;
973         /* try to open the dynamic library */
974         if (dlname) {
975                 /* try to open the installed module */
976                 if (installed && libdir) {
977                         filename = (char*)
978                                 lt_dlmalloc(strlen(libdir)+1+strlen(dlname)+1);
979                         if (!filename) {
980                                 last_error = memory_error;
981                                 return 1;
982                         }
983                         strcpy(filename, libdir);
984                         strcat(filename, "/");
985                         strcat(filename, dlname);
986                         error = tryall_dlopen(handle, filename) == 0;
987                         lt_dlfree(filename);
988                         if (error)
989                                 return 0;
990                 }
991                 /* try to open the not-installed module */
992                 if (!installed) {
993                         filename = (char*)
994                                 lt_dlmalloc((dir ? strlen(dir) : 0)
995                                        + strlen(objdir) + strlen(dlname) + 1);
996                         if (!filename) {
997                                 last_error = memory_error;
998                                 return 1;
999                         }
1000                         if (dir)
1001                                 strcpy(filename, dir);
1002                         else
1003                                 *filename = 0;
1004                         strcat(filename, objdir);
1005                         strcat(filename, dlname);
1006
1007                         error = tryall_dlopen(handle, filename) == 0;
1008                         lt_dlfree(filename);
1009                         if (error)
1010                                 return 0;
1011                 }
1012                 /* hmm, maybe it was moved to another directory */
1013                 {
1014                         filename = (char*)
1015                                 lt_dlmalloc((dir ? strlen(dir) : 0)
1016                                        + strlen(dlname) + 1);
1017                         if (dir)
1018                                 strcpy(filename, dir);
1019                         else
1020                                 *filename = 0;
1021                         strcat(filename, dlname);
1022                         error = tryall_dlopen(handle, filename) == 0;
1023                         lt_dlfree(filename);
1024                         if (error)
1025                                 return 0;
1026                 }
1027         }
1028         last_error = file_not_found_error;
1029         return 1;
1030 }
1031
1032 static lt_ptr_t
1033 find_file (basename, search_path, pdir, handle)
1034         const char *basename;
1035         const char *search_path;
1036         char **pdir;
1037         lt_dlhandle *handle;
1038 {
1039         /* when handle != NULL search a library, otherwise a file */
1040         /* return NULL on failure, otherwise the file/handle */
1041
1042         char    *filename = 0;
1043         int     filenamesize = 0;
1044         const char *next = search_path;
1045         int     lenbase = strlen(basename);
1046         
1047         if (!next || !*next) {
1048                 last_error = file_not_found_error;
1049                 return 0;
1050         }
1051         while (next) {
1052                 int lendir;
1053                 const char *cur = next;
1054
1055                 next = strchr(cur, ':');
1056                 if (!next)
1057                         next = cur + strlen(cur);
1058                 lendir = next - cur;
1059                 if (*next == ':')
1060                         ++next;
1061                 else
1062                         next = 0;
1063                 if (lendir == 0)
1064                         continue;
1065                 if (lendir + 1 + lenbase >= filenamesize) {
1066                         if (filename)
1067                                 lt_dlfree(filename);
1068                         filenamesize = lendir + 1 + lenbase + 1;
1069                         filename = (char*) lt_dlmalloc(filenamesize);
1070                         if (!filename) {
1071                                 last_error = memory_error;
1072                                 return 0;
1073                         }
1074                 }
1075                 strncpy(filename, cur, lendir);
1076                 if (filename[lendir-1] != '/')
1077                         filename[lendir++] = '/';
1078                 strcpy(filename+lendir, basename);
1079                 if (handle) {
1080                         if (tryall_dlopen(handle, filename) == 0) {
1081                                 lt_dlfree(filename);
1082                                 return (lt_ptr_t) handle;
1083                         }
1084                 } else {
1085                         FILE *file = fopen(filename, LTDL_READTEXT_MODE);
1086                         if (file) {
1087                                 if (*pdir)
1088                                         lt_dlfree(*pdir);
1089                                 filename[lendir] = '\0';
1090                                 *pdir = strdup(filename);
1091                                 if (!*pdir) {
1092                                         /* We could have even avoided the
1093                                            strdup, but there would be some
1094                                            memory overhead. */
1095                                         *pdir = filename;
1096                                 } else
1097                                         lt_dlfree(filename);
1098                                 return (lt_ptr_t) file;
1099                         }
1100                 }
1101         }
1102         if (filename)
1103                 lt_dlfree(filename);
1104         last_error = file_not_found_error;
1105         return 0;
1106 }
1107
1108 static int
1109 load_deplibs(handle, deplibs)
1110         lt_dlhandle handle;
1111         const char *deplibs;
1112 {
1113         /* FIXME: load deplibs */
1114         handle->depcount = 0;
1115         handle->deplibs = 0;
1116         /* Just to silence gcc -Wall */
1117         deplibs = 0;
1118         return 0;
1119 }
1120
1121 static int
1122 unload_deplibs(handle)
1123         lt_dlhandle handle;
1124 {
1125         /* FIXME: unload deplibs */
1126         /* Just to silence gcc -Wall */
1127         handle = 0;
1128         return 0;
1129 }
1130
1131 static inline int
1132 trim (dest, str)
1133         char **dest;
1134         const char *str;
1135 {
1136         /* remove the leading and trailing "'" from str 
1137            and store the result in dest */
1138         char *tmp;
1139         const char *end = strrchr(str, '\'');
1140         int len = strlen(str);
1141
1142         if (*dest)
1143                 lt_dlfree(*dest);
1144         if (len > 3 && str[0] == '\'') {
1145                 tmp = (char*) lt_dlmalloc(end - str);
1146                 if (!tmp) {
1147                         last_error = memory_error;
1148                         return 1;
1149                 }
1150                 strncpy(tmp, &str[1], (end - str) - 1);
1151                 tmp[len-3] = '\0';
1152                 *dest = tmp;
1153         } else
1154                 *dest = 0;
1155         return 0;
1156 }
1157
1158 static inline int
1159 free_vars(dir, name, dlname, oldname, libdir, deplibs)
1160         char *dir;
1161         char *name;
1162         char *dlname;
1163         char *oldname;
1164         char *libdir;
1165         char *deplibs;
1166 {
1167         if (dir)
1168                 lt_dlfree(dir);
1169         if (name)
1170                 lt_dlfree(name);
1171         if (dlname)
1172                 lt_dlfree(dlname);
1173         if (oldname)
1174                 lt_dlfree(oldname);
1175         if (libdir)
1176                 lt_dlfree(libdir);
1177         if (deplibs)
1178                 lt_dlfree(deplibs);
1179         return 0;
1180 }
1181
1182 lt_dlhandle
1183 lt_dlopen (filename)
1184         const char *filename;
1185 {
1186         lt_dlhandle handle, newhandle;
1187         const char *basename, *ext;
1188         const char *saved_error = last_error;
1189         char    *dir = 0, *name = 0;
1190         
1191         if (!filename) {
1192                 handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
1193                 if (!handle) {
1194                         last_error = memory_error;
1195                         return 0;
1196                 }
1197                 handle->usage = 0;
1198                 handle->depcount = 0;
1199                 handle->deplibs = 0;
1200                 newhandle = handle;
1201                 if (tryall_dlopen(&newhandle, 0) != 0) {
1202                         lt_dlfree(handle);
1203                         return 0;
1204                 }
1205                 goto register_handle;
1206         }
1207         basename = strrchr(filename, '/');
1208         if (basename) {
1209                 basename++;
1210                 dir = (char*) lt_dlmalloc(basename - filename + 1);
1211                 if (!dir) {
1212                         last_error = memory_error;
1213                         return 0;
1214                 }
1215                 strncpy(dir, filename, basename - filename);
1216                 dir[basename - filename] = '\0';
1217         } else
1218                 basename = filename;
1219         /* check whether we open a libtool module (.la extension) */
1220         ext = strrchr(basename, '.');
1221         if (ext && strcmp(ext, ".la") == 0) {
1222                 /* this seems to be a libtool module */
1223                 FILE    *file;
1224                 int     i;
1225                 char    *dlname = 0, *old_name = 0;
1226                 char    *libdir = 0, *deplibs = 0;
1227                 char    *line;
1228                 int     error = 0;
1229                 /* if we can't find the installed flag, it is probably an
1230                    installed libtool archive, produced with an old version
1231                    of libtool */
1232                 int     installed = 1; 
1233
1234                 /* extract the module name from the file name */
1235                 name = (char*) lt_dlmalloc(ext - basename + 1);
1236                 if (!name) {
1237                         last_error = memory_error;
1238                         if (dir)
1239                                 lt_dlfree(dir);
1240                         return 0;
1241                 }
1242                 /* canonicalize the module name */
1243                 for (i = 0; i < ext - basename; i++)
1244                         if (isalnum((int)(basename[i])))
1245                                 name[i] = basename[i];
1246                         else
1247                                 name[i] = '_';
1248                 name[ext - basename] = '\0';
1249                 /* now try to open the .la file */
1250                 file = fopen(filename, LTDL_READTEXT_MODE);
1251                 if (!file)
1252                         last_error = file_not_found_error;
1253                 if (!file && !dir) {
1254                         /* try other directories */
1255                         file = (FILE*) find_file(basename, 
1256                                                  user_search_path,
1257                                                  &dir, 0);
1258                         if (!file)
1259                                 file = (FILE*) find_file(basename,
1260                                                  getenv("LTDL_LIBRARY_PATH"),
1261                                                  &dir, 0);
1262 #ifdef LTDL_SHLIBPATH_VAR
1263                         if (!file)
1264                                 file = (FILE*) find_file(basename,
1265                                                  getenv(LTDL_SHLIBPATH_VAR),
1266                                                  &dir, 0);
1267 #endif
1268                 }
1269                 if (!file) {
1270                         if (name)
1271                                 lt_dlfree(name);
1272                         if (dir)
1273                                 lt_dlfree(dir);
1274                         return 0;
1275                 }
1276                 line = (char*) lt_dlmalloc(LTDL_FILENAME_MAX);
1277                 if (!line) {
1278                         fclose(file);
1279                         last_error = memory_error;
1280                         return 0;
1281                 }
1282                 /* read the .la file */
1283                 while (!feof(file)) {
1284                         if (!fgets(line, LTDL_FILENAME_MAX, file))
1285                                 break;
1286                         if (line[0] == '\n' || line[0] == '#')
1287                                 continue;
1288 #                       undef  STR_DLNAME
1289 #                       define STR_DLNAME       "dlname="
1290                         if (strncmp(line, STR_DLNAME,
1291                                 sizeof(STR_DLNAME) - 1) == 0)
1292                                 error = trim(&dlname,
1293                                         &line[sizeof(STR_DLNAME) - 1]);
1294                         else
1295 #                       undef  STR_OLD_LIBRARY
1296 #                       define STR_OLD_LIBRARY  "old_library="
1297                         if (strncmp(line, STR_OLD_LIBRARY,
1298                                 sizeof(STR_OLD_LIBRARY) - 1) == 0)
1299                                 error = trim(&old_name,
1300                                         &line[sizeof(STR_OLD_LIBRARY) - 1]);
1301                         else
1302 #                       undef  STR_LIBDIR
1303 #                       define STR_LIBDIR       "libdir="
1304                         if (strncmp(line, STR_LIBDIR,
1305                                 sizeof(STR_LIBDIR) - 1) == 0)
1306                                 error = trim(&libdir,
1307                                         &line[sizeof(STR_LIBDIR) - 1]);
1308                         else
1309 #                       undef  STR_DL_DEPLIBS
1310 #                       define STR_DL_DEPLIBS   "dl_dependency_libs="
1311                         if (strncmp(line, STR_DL_DEPLIBS,
1312                                 sizeof(STR_DL_DEPLIBS) - 1) == 0)
1313                                 error = trim(&deplibs,
1314                                         &line[sizeof(STR_DL_DEPLIBS) - 1]);
1315                         else
1316                         if (strcmp(line, "installed=yes\n") == 0)
1317                                 installed = 1;
1318                         else
1319                         if (strcmp(line, "installed=no\n") == 0)
1320                                 installed = 0;
1321                         if (error)
1322                                 break;
1323                 }
1324                 fclose(file);
1325                 lt_dlfree(line);
1326                 /* allocate the handle */
1327                 handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
1328                 if (!handle || error) {
1329                         if (handle)
1330                                 lt_dlfree(handle);
1331                         if (!error)
1332                                 last_error = memory_error;
1333                         free_vars(name, dir, dlname, old_name, libdir, deplibs);
1334                         return 0;
1335                 }
1336                 handle->usage = 0;
1337                 if (load_deplibs(handle, deplibs) == 0) {
1338                         newhandle = handle;
1339                         /* find_module may replace newhandle */
1340                         if (find_module(&newhandle, dir, libdir, 
1341                                         dlname, old_name, installed)) {
1342                                 unload_deplibs(handle);
1343                                 error = 1;
1344                         }
1345                 } else
1346                         error = 1;
1347                 if (error) {
1348                         lt_dlfree(handle);
1349                         free_vars(name, dir, dlname, old_name, libdir, deplibs);
1350                         return 0;
1351                 }
1352                 free_vars(NULL, NULL, dlname, old_name, libdir, deplibs);
1353                 if (handle != newhandle) {
1354                         unload_deplibs(handle);
1355                 }
1356         } else {
1357                 /* not a libtool module */
1358                 handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
1359                 if (!handle) {
1360                         last_error = memory_error;
1361                         if (dir)
1362                                 lt_dlfree(dir);
1363                         return 0;
1364                 }
1365                 handle->usage = 0;
1366                 /* non-libtool modules don't have dependencies */
1367                 handle->depcount = 0;
1368                 handle->deplibs = 0;
1369                 newhandle = handle;
1370                 if (tryall_dlopen(&newhandle, filename)
1371                     && (dir
1372                         || (!find_file(basename, user_search_path,
1373                                           0, &newhandle)
1374                             && !find_file(basename,
1375                                           getenv("LTDL_LIBRARY_PATH"),
1376                                           0, &newhandle)
1377 #ifdef LTDL_SHLIBPATH_VAR
1378                             && !find_file(basename,
1379                                           getenv(LTDL_SHLIBPATH_VAR),
1380                                           0, &newhandle)
1381 #endif
1382                                 ))) {
1383                         lt_dlfree(handle);
1384                         if (dir)
1385                                 lt_dlfree(dir);
1386                         return 0;
1387                 }
1388         }
1389 register_handle:
1390         if (newhandle != handle) {
1391                 lt_dlfree(handle);
1392                 handle = newhandle;
1393         }
1394         if (!handle->usage) {
1395                 handle->usage = 1;
1396                 handle->name = name;
1397                 handle->next = handles;
1398                 handles = handle;
1399         } else if (name)
1400                 lt_dlfree(name);
1401         if (dir)
1402                 lt_dlfree(dir);
1403         last_error = saved_error;
1404         return handle;
1405 }
1406
1407 lt_dlhandle
1408 lt_dlopenext (filename)
1409         const char *filename;
1410 {
1411         lt_dlhandle handle;
1412         char    *tmp;
1413         int     len;
1414         const char *saved_error = last_error;
1415         
1416         if (!filename)
1417                 return lt_dlopen(filename);
1418         len = strlen(filename);
1419         if (!len) {
1420                 last_error = file_not_found_error;
1421                 return 0;
1422         }
1423         /* try the normal file name */
1424         handle = lt_dlopen(filename);
1425         if (handle)
1426                 return handle;
1427         /* try "filename.la" */
1428         tmp = (char*) lt_dlmalloc(len+4);
1429         if (!tmp) {
1430                 last_error = memory_error;
1431                 return 0;
1432         }
1433         strcpy(tmp, filename);
1434         strcat(tmp, ".la");
1435         handle = lt_dlopen(tmp);
1436         if (handle) {
1437                 last_error = saved_error;
1438                 lt_dlfree(tmp);
1439                 return handle;
1440         }
1441 #ifdef LTDL_SHLIB_EXT
1442         /* try "filename.EXT" */
1443         if (strlen(shlib_ext) > 3) {
1444                 lt_dlfree(tmp);
1445                 tmp = (char*) lt_dlmalloc(len + strlen(shlib_ext) + 1);
1446                 if (!tmp) {
1447                         last_error = memory_error;
1448                         return 0;
1449                 }
1450                 strcpy(tmp, filename);
1451         } else
1452                 tmp[len] = '\0';
1453         strcat(tmp, shlib_ext);
1454         handle = lt_dlopen(tmp);
1455         if (handle) {
1456                 last_error = saved_error;
1457                 lt_dlfree(tmp);
1458                 return handle;
1459         }
1460 #endif  
1461         /*
1462          *      WTF?  It's SUPPOSED to look for statically linked libraries,
1463          *      but the bugger doesn't!
1464          */
1465         strcpy(tmp, filename);
1466         strcat(tmp, ".a");
1467         handle = lt_dlopen(tmp);
1468         if (handle) {
1469                 last_error = saved_error;
1470                 lt_dlfree(tmp);
1471                 return handle;
1472         }
1473         last_error = file_not_found_error;
1474         lt_dlfree(tmp);
1475         return 0;
1476 }
1477
1478 int
1479 lt_dlclose (handle)
1480         lt_dlhandle handle;
1481 {
1482         lt_dlhandle cur, last;
1483         
1484         /* check whether the handle is valid */
1485         last = cur = handles;
1486         while (cur && handle != cur) {
1487                 last = cur;
1488                 cur = cur->next;
1489         }
1490         if (!cur) {
1491                 last_error = invalid_handle_error;
1492                 return 1;
1493         }
1494         handle->usage--;
1495         if (!handle->usage) {
1496                 int     error;
1497         
1498                 if (handle != handles)
1499                         last->next = handle->next;
1500                 else
1501                         handles = handle->next;
1502                 error = handle->type->lib_close(handle);
1503                 error += unload_deplibs(handle);
1504                 if (handle->filename)
1505                         lt_dlfree(handle->filename);
1506                 if (handle->name)
1507                         lt_dlfree(handle->name);
1508                 lt_dlfree(handle);
1509                 return error;
1510         }
1511         return 0;
1512 }
1513
1514 lt_ptr_t
1515 lt_dlsym (handle, symbol)
1516         lt_dlhandle handle;
1517         const char *symbol;
1518 {
1519         int     lensym;
1520         char    lsym[LTDL_SYMBOL_LENGTH];
1521         char    *sym;
1522         lt_ptr_t address;
1523
1524         if (!handle) {
1525                 last_error = invalid_handle_error;
1526                 return 0;
1527         }
1528         if (!symbol) {
1529                 last_error = symbol_error;
1530                 return 0;
1531         }
1532         lensym = strlen(symbol);
1533         if (handle->type->sym_prefix)
1534                 lensym += strlen(handle->type->sym_prefix);
1535         if (handle->name)
1536                 lensym += strlen(handle->name);
1537         if (lensym + LTDL_SYMBOL_OVERHEAD < LTDL_SYMBOL_LENGTH)
1538                 sym = lsym;
1539         else
1540                 sym = (char*) lt_dlmalloc(lensym + LTDL_SYMBOL_OVERHEAD + 1);
1541         if (!sym) {
1542                 last_error = buffer_overflow_error;
1543                 return 0;
1544         }
1545         if (handle->name) {
1546                 const char *saved_error = last_error;
1547                 
1548                 /* this is a libtool module */
1549                 if (handle->type->sym_prefix) {
1550                         strcpy(sym, handle->type->sym_prefix);
1551                         strcat(sym, handle->name);
1552                 } else
1553                         strcpy(sym, handle->name);
1554                 strcat(sym, "_LTX_");
1555                 strcat(sym, symbol);
1556                 /* try "modulename_LTX_symbol" */
1557                 address = handle->type->find_sym(handle, sym);
1558                 if (address) {
1559                         if (sym != lsym)
1560                                 lt_dlfree(sym);
1561                         return address;
1562                 }
1563                 last_error = saved_error;
1564         }
1565         /* otherwise try "symbol" */
1566         if (handle->type->sym_prefix) {
1567                 strcpy(sym, handle->type->sym_prefix);
1568                 strcat(sym, symbol);
1569         } else
1570                 strcpy(sym, symbol);
1571         address = handle->type->find_sym(handle, sym);
1572         if (sym != lsym)
1573                 lt_dlfree(sym);
1574         return address;
1575 }
1576
1577 const char *
1578 lt_dlerror LTDL_PARAMS((void))
1579 {
1580         const char *error = last_error;
1581         
1582         last_error = 0;
1583         return error;
1584 }
1585
1586 int
1587 lt_dladdsearchdir (search_dir)
1588         const char *search_dir;
1589 {
1590         if (!search_dir || !strlen(search_dir))
1591                 return 0;
1592         if (!user_search_path) {
1593                 user_search_path = strdup(search_dir);
1594                 if (!user_search_path) {
1595                         last_error = memory_error;
1596                         return 1;
1597                 }
1598         } else {
1599                 char    *new_search_path = (char*)
1600                         lt_dlmalloc(strlen(user_search_path) + 
1601                                 strlen(search_dir) + 2); /* ':' + '\0' == 2 */
1602                 if (!new_search_path) {
1603                         last_error = memory_error;
1604                         return 1;
1605                 }
1606                 strcpy(new_search_path, user_search_path);
1607                 strcat(new_search_path, ":");
1608                 strcat(new_search_path, search_dir);
1609                 lt_dlfree(user_search_path);
1610                 user_search_path = new_search_path;
1611         }
1612         return 0;
1613 }
1614
1615 int
1616 lt_dlsetsearchpath (search_path)
1617         const char *search_path;
1618 {
1619         if (user_search_path)
1620                 lt_dlfree(user_search_path);
1621         user_search_path = 0; /* reset the search path */
1622         if (!search_path || !strlen(search_path))
1623                 return 0;
1624         user_search_path = strdup(search_path);
1625         if (!user_search_path)
1626                 return 1;
1627         return 0;
1628 }
1629
1630 const char *
1631 lt_dlgetsearchpath LTDL_PARAMS((void))
1632 {
1633         return user_search_path;
1634 }