f3f8f2cd85bfa8aca78c1fc72de9840480f69ed0
[freeradius.git] / libltdl / ltdl.c
1 /* ltdl.c -- system independent dlopen wrapper
2    Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3    Originally by Thomas Tanner <tanner@ffii.org>
4    This file is part of GNU Libtool.
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 As a special exception to the GNU Lesser General Public License,
12 if you distribute this file as part of a program or library that
13 is built using GNU libtool, you may include it under the same
14 distribution terms that you use for the rest of that program.
15
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 Lesser General Public License for more details.
20
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 02111-1307  USA
25
26 */
27
28 #if HAVE_CONFIG_H
29 #  include <config.h>
30 #endif
31
32 #if HAVE_UNISTD_H
33 #  include <unistd.h>
34 #endif
35
36 #if HAVE_STDIO_H
37 #  include <stdio.h>
38 #endif
39
40 #if HAVE_STDLIB_H
41 #  include <stdlib.h>
42 #endif
43
44 #if HAVE_STRING_H
45 #  include <string.h>
46 #else
47 #  if HAVE_STRINGS_H
48 #    include <strings.h>
49 #  endif
50 #endif
51
52 #if HAVE_CTYPE_H
53 #  include <ctype.h>
54 #endif
55
56 #if HAVE_MALLOC_H
57 #  include <malloc.h>
58 #endif
59
60 #if HAVE_MEMORY_H
61 #  include <memory.h>
62 #endif
63
64 #if HAVE_ERRNO_H
65 #  include <errno.h>
66 #endif
67
68 #if HAVE_DIRENT_H
69 #  include <dirent.h>
70 #  define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
71 #else
72 #  define dirent direct
73 #  define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
74 #  if HAVE_SYS_NDIR_H
75 #    include <sys/ndir.h>
76 #  endif
77 #  if HAVE_SYS_DIR_H
78 #    include <sys/dir.h>
79 #  endif
80 #  if HAVE_NDIR_H
81 #    include <ndir.h>
82 #  endif
83 #endif
84
85 #if HAVE_ARGZ_H
86 #  include <argz.h>
87 #endif
88
89 #if HAVE_ASSERT_H
90 #  include <assert.h>
91 #else
92 #  define assert(arg)   ((void) 0)
93 #endif
94
95 #include "ltdl.h"
96
97
98
99 \f
100 /* --- WINDOWS SUPPORT --- */
101
102
103 #ifdef DLL_EXPORT
104 #  define LT_GLOBAL_DATA        __declspec(dllexport)
105 #else
106 #  define LT_GLOBAL_DATA
107 #endif
108
109 /* fopen() mode flags for reading a text file */
110 #undef  LT_READTEXT_MODE
111 #ifdef __WINDOWS__
112 #  define LT_READTEXT_MODE "rt"
113 #else
114 #  define LT_READTEXT_MODE "r"
115 #endif
116
117
118
119 \f
120 /* --- MANIFEST CONSTANTS --- */
121
122
123 /* Standard libltdl search path environment variable name  */
124 #undef  LTDL_SEARCHPATH_VAR
125 #define LTDL_SEARCHPATH_VAR     "LTDL_LIBRARY_PATH"
126
127 /* Standard libtool archive file extension.  */
128 #undef  LTDL_ARCHIVE_EXT
129 #define LTDL_ARCHIVE_EXT        ".la"
130
131 /* max. filename length */
132 #ifndef LT_FILENAME_MAX
133 #  define LT_FILENAME_MAX       1024
134 #endif
135
136 /* This is the maximum symbol size that won't require malloc/free */
137 #undef  LT_SYMBOL_LENGTH
138 #define LT_SYMBOL_LENGTH        128
139
140 /* This accounts for the _LTX_ separator */
141 #undef  LT_SYMBOL_OVERHEAD
142 #define LT_SYMBOL_OVERHEAD      5
143
144
145
146 \f
147 /* --- MEMORY HANDLING --- */
148
149
150 /* These are the functions used internally.  In addition to making
151    use of the associated function pointers above, they also perform
152    error handling.  */
153 static char   *lt_estrdup       LT_PARAMS((const char *str));
154 static lt_ptr lt_emalloc        LT_PARAMS((size_t size));
155 static lt_ptr lt_erealloc       LT_PARAMS((lt_ptr addr, size_t size));
156
157 static lt_ptr rpl_realloc       LT_PARAMS((lt_ptr ptr, size_t size));
158
159 /* These are the pointers that can be changed by the caller:  */
160 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)    LT_PARAMS((size_t size))
161                         = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
162 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc)   LT_PARAMS((lt_ptr ptr, size_t size))
163                         = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
164 LT_GLOBAL_DATA void   (*lt_dlfree)      LT_PARAMS((lt_ptr ptr))
165                         = (void (*) LT_PARAMS((lt_ptr))) free;
166
167 /* The following macros reduce the amount of typing needed to cast
168    assigned memory.  */
169 #define LT_DLMALLOC(tp, n)      ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
170 #define LT_DLREALLOC(tp, p, n)  ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
171 #define LT_DLFREE(p)                                            \
172         LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
173
174 #define LT_EMALLOC(tp, n)       ((tp *) lt_emalloc ((n) * sizeof(tp)))
175 #define LT_EREALLOC(tp, p, n)   ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
176
177 #define LT_DLMEM_REASSIGN(p, q)                 LT_STMT_START { \
178         if ((p) != (q)) { lt_dlfree (p); (p) = (q); (q) = 0; }  \
179                                                 } LT_STMT_END
180
181 \f
182 /* --- REPLACEMENT FUNCTIONS --- */
183
184
185 #undef strdup
186 #define strdup rpl_strdup
187
188 static char *strdup LT_PARAMS((const char *str));
189
190 char *
191 strdup(str)
192      const char *str;
193 {
194   char *tmp = 0;
195
196   if (str)
197     {
198       tmp = LT_DLMALLOC (char, 1+ strlen (str));
199       if (tmp)
200         {
201           strcpy(tmp, str);
202         }
203     }
204
205   return tmp;
206 }
207
208
209 #if ! HAVE_STRCMP
210
211 #undef strcmp
212 #define strcmp rpl_strcmp
213
214 static int strcmp LT_PARAMS((const char *str1, const char *str2));
215
216 int
217 strcmp (str1, str2)
218      const char *str1;
219      const char *str2;
220 {
221   if (str1 == str2)
222     return 0;
223   if (str1 == 0)
224     return -1;
225   if (str2 == 0)
226     return 1;
227
228   for (;*str1 && *str2; ++str1, ++str2)
229     {
230       if (*str1 != *str2)
231         break;
232     }
233
234   return (int)(*str1 - *str2);
235 }
236 #endif
237
238
239 #if ! HAVE_STRCHR
240
241 #  if HAVE_INDEX
242 #    define strchr index
243 #  else
244 #    define strchr rpl_strchr
245
246 static const char *strchr LT_PARAMS((const char *str, int ch));
247
248 const char*
249 strchr(str, ch)
250      const char *str;
251      int ch;
252 {
253   const char *p;
254
255   for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
256     /*NOWORK*/;
257
258   return (*p == (char)ch) ? p : 0;
259 }
260
261 #  endif
262 #endif /* !HAVE_STRCHR */
263
264
265 #if ! HAVE_STRRCHR
266
267 #  if HAVE_RINDEX
268 #    define strrchr rindex
269 #  else
270 #    define strrchr rpl_strrchr
271
272 static const char *strrchr LT_PARAMS((const char *str, int ch));
273
274 const char*
275 strrchr(str, ch)
276      const char *str;
277      int ch;
278 {
279   const char *p, *q = 0;
280
281   for (p = str; *p != LT_EOS_CHAR; ++p)
282     {
283       if (*p == (char) ch)
284         {
285           q = p;
286         }
287     }
288
289   return q;
290 }
291
292 # endif
293 #endif
294
295 /* NOTE:  Neither bcopy nor the memcpy implementation below can
296           reliably handle copying in overlapping areas of memory.  Use
297           memmove (for which there is a fallback implmentation below)
298           if you need that behaviour.  */
299 #if ! HAVE_MEMCPY
300
301 #  if HAVE_BCOPY
302 #    define memcpy(dest, src, size)     bcopy (src, dest, size)
303 #  else
304 #    define memcpy rpl_memcpy
305
306 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
307
308 lt_ptr
309 memcpy (dest, src, size)
310      lt_ptr dest;
311      const lt_ptr src;
312      size_t size;
313 {
314   size_t i = 0;
315
316   for (i = 0; i < size; ++i)
317     {
318       dest[i] = src[i];
319     }
320
321   return dest;
322 }
323
324 #  endif /* !HAVE_BCOPY */
325 #endif   /* !HAVE_MEMCPY */
326
327 #if ! HAVE_MEMMOVE
328 #  define memmove rpl_memmove
329
330 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
331
332 lt_ptr
333 memmove (dest, src, size)
334      lt_ptr dest;
335      const lt_ptr src;
336      size_t size;
337 {
338   size_t i;
339
340   if (dest < src)
341     for (i = 0; i < size; ++i)
342       {
343         dest[i] = src[i];
344       }
345   else if (dest > src)
346     for (i = size -1; i >= 0; --i)
347       {
348         dest[i] = src[i];
349       }
350
351   return dest;
352 }
353
354 #endif /* !HAVE_MEMMOVE */
355
356
357 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
358     ``realloc is not entirely portable''
359    In any case we want to use the allocator supplied by the user without
360    burdening them with an lt_dlrealloc function pointer to maintain.
361    Instead implement our own version (with known boundary conditions)
362    using lt_dlmalloc and lt_dlfree. */
363
364 #undef realloc
365 #define realloc rpl_realloc
366
367 lt_ptr
368 realloc (ptr, size)
369      lt_ptr ptr;
370      size_t size;
371 {
372   if (size <= 0)
373     {
374       /* For zero or less bytes, free the original memory */
375       if (ptr != 0)
376         {
377           lt_dlfree (ptr);
378         }
379
380       return (lt_ptr) 0;
381     }
382   else if (ptr == 0)
383     {
384       /* Allow reallocation of a NULL pointer.  */
385       return lt_dlmalloc (size);
386     }
387   else
388     {
389       /* Allocate a new block, copy and free the old block.  */
390       lt_ptr mem = lt_dlmalloc (size);
391
392       if (mem)
393         {
394           memcpy (mem, ptr, size);
395           lt_dlfree (ptr);
396         }
397
398       /* Note that the contents of PTR are not damaged if there is
399          insufficient memory to realloc.  */
400       return mem;
401     }
402 }
403
404
405 #if ! HAVE_ARGZ_APPEND
406 #  define argz_append rpl_argz_append
407
408 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
409                                         const char *buf, size_t buf_len));
410
411 error_t
412 argz_append (pargz, pargz_len, buf, buf_len)
413      char **pargz;
414      size_t *pargz_len;
415      const char *buf;
416      size_t buf_len;
417 {
418   size_t argz_len;
419   char  *argz;
420
421   assert (pargz);
422   assert (pargz_len);
423   assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
424
425   /* If nothing needs to be appended, no more work is required.  */
426   if (buf_len == 0)
427     return 0;
428
429   /* Ensure there is enough room to append BUF_LEN.  */
430   argz_len = *pargz_len + buf_len;
431   argz = LT_DLREALLOC (char, *pargz, argz_len);
432   if (!argz)
433     return ENOMEM;
434
435   /* Copy characters from BUF after terminating '\0' in ARGZ.  */
436   memcpy (argz + *pargz_len, buf, buf_len);
437
438   /* Assign new values.  */
439   *pargz = argz;
440   *pargz_len = argz_len;
441
442   return 0;
443 }
444 #endif /* !HAVE_ARGZ_APPEND */
445
446
447 #if ! HAVE_ARGZ_CREATE_SEP
448 #  define argz_create_sep rpl_argz_create_sep
449
450 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
451                                             char **pargz, size_t *pargz_len));
452
453 error_t
454 argz_create_sep (str, delim, pargz, pargz_len)
455      const char *str;
456      int delim;
457      char **pargz;
458      size_t *pargz_len;
459 {
460   size_t argz_len;
461   char *argz = 0;
462
463   assert (str);
464   assert (pargz);
465   assert (pargz_len);
466
467   /* Make a copy of STR, but replacing each occurence of
468      DELIM with '\0'.  */
469   argz_len = 1+ LT_STRLEN (str);
470   if (argz_len)
471     {
472       const char *p;
473       char *q;
474
475       argz = LT_DLMALLOC (char, argz_len);
476       if (!argz)
477         return ENOMEM;
478
479       for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
480         {
481           if (*p == delim)
482             {
483               /* Ignore leading delimiters, and fold consecutive
484                  delimiters in STR into a single '\0' in ARGZ.  */
485               if ((q > argz) && (q[-1] != LT_EOS_CHAR))
486                 *q++ = LT_EOS_CHAR;
487               else
488                 --argz_len;
489             }
490           else
491             *q++ = *p;
492         }
493       /* Copy terminating LT_EOS_CHAR.  */
494       *q = *p;
495     }
496
497   /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory.  */
498   if (!argz_len)
499     LT_DLFREE (argz);
500
501   /* Assign new values.  */
502   *pargz = argz;
503   *pargz_len = argz_len;
504
505   return 0;
506 }
507 #endif /* !HAVE_ARGZ_CREATE_SEP */
508
509
510 #if ! HAVE_ARGZ_INSERT
511 #  define argz_insert rpl_argz_insert
512
513 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
514                                         char *before, const char *entry));
515
516 error_t
517 argz_insert (pargz, pargz_len, before, entry)
518      char **pargz;
519      size_t *pargz_len;
520      char *before;
521      const char *entry;
522 {
523   assert (pargz);
524   assert (pargz_len);
525   assert (entry && *entry);
526
527   /* Either PARGZ/PARGZ_LEN is empty and BEFORE is NULL,
528      or BEFORE points into an address within the ARGZ vector.  */
529   assert ((!*pargz && !*pargz_len && !before)
530           || ((*pargz <= before) && (before < (*pargz + *pargz_len))));
531
532   /* No BEFORE address indicates ENTRY should be inserted after the
533      current last element.  */
534   if (!before)
535     return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
536
537   /* This probably indicates a programmer error, but to preserve
538      semantics, scan back to the start of an entry if BEFORE points
539      into the middle of it.  */
540   while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR))
541     --before;
542
543   {
544     size_t entry_len    = 1+ LT_STRLEN (entry);
545     size_t argz_len     = *pargz_len + entry_len;
546     size_t offset       = before - *pargz;
547     char   *argz        = LT_DLREALLOC (char, *pargz, argz_len);
548
549     if (!argz)
550       return ENOMEM;
551
552     /* Make BEFORE point to the equivalent offset in ARGZ that it
553        used to have in *PARGZ incase realloc() moved the block.  */
554     before = argz + offset;
555
556     /* Move the ARGZ entries starting at BEFORE up into the new
557        space at the end -- making room to copy ENTRY into the
558        resulting gap.  */
559     memmove (before + entry_len, before, *pargz_len - offset);
560     memcpy  (before, entry, entry_len);
561
562     /* Assign new values.  */
563     *pargz = argz;
564     *pargz_len = argz_len;
565   }
566
567   return 0;
568 }
569 #endif /* !HAVE_ARGZ_INSERT */
570
571
572 #if ! HAVE_ARGZ_NEXT
573 #  define argz_next rpl_argz_next
574
575 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
576                                     const char *entry));
577
578 char *
579 argz_next (argz, argz_len, entry)
580      char *argz;
581      size_t argz_len;
582      const char *entry;
583 {
584   assert ((argz && argz_len) || (!argz && !argz_len));
585
586   if (entry)
587     {
588       /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
589          within the ARGZ vector.  */
590       assert ((!argz && !argz_len)
591               || ((argz <= entry) && (entry < (argz + argz_len))));
592
593       /* Move to the char immediately after the terminating
594          '\0' of ENTRY.  */
595       entry = 1+ strchr (entry, LT_EOS_CHAR);
596
597       /* Return either the new ENTRY, or else NULL if ARGZ is
598          exhausted.  */
599       return (entry >= argz + argz_len) ? 0 : (char *) entry;
600     }
601   else
602     {
603       /* This should probably be flagged as a programmer error,
604          since starting an argz_next loop with the iterator set
605          to ARGZ is safer.  To preserve semantics, handle the NULL
606          case by returning the start of ARGZ (if any).  */
607       if (argz_len > 0)
608         return argz;
609       else
610         return 0;
611     }
612 }
613 #endif /* !HAVE_ARGZ_NEXT */
614
615
616
617 #if ! HAVE_ARGZ_STRINGIFY
618 #  define argz_stringify rpl_argz_stringify
619
620 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
621                                        int sep));
622
623 void
624 argz_stringify (argz, argz_len, sep)
625      char *argz;
626      size_t argz_len;
627      int sep;
628 {
629   assert ((argz && argz_len) || (!argz && !argz_len));
630
631   if (sep)
632     {
633       --argz_len;               /* don't stringify the terminating EOS */
634       while (--argz_len > 0)
635         {
636           if (argz[argz_len] == LT_EOS_CHAR)
637             argz[argz_len] = sep;
638         }
639     }
640 }
641 #endif /* !HAVE_ARGZ_STRINGIFY */
642
643
644
645 \f
646 /* --- TYPE DEFINITIONS -- */
647
648
649 /* This type is used for the array of caller data sets in each handler. */
650 typedef struct {
651   lt_dlcaller_id        key;
652   lt_ptr                data;
653 } lt_caller_data;
654
655
656
657 \f
658 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
659
660
661 /* Extract the diagnostic strings from the error table macro in the same
662    order as the enumerated indices in ltdl.h. */
663
664 static const char *lt_dlerror_strings[] =
665   {
666 #define LT_ERROR(name, diagnostic)      (diagnostic),
667     lt_dlerror_table
668 #undef LT_ERROR
669
670     0
671   };
672
673 /* This structure is used for the list of registered loaders. */
674 struct lt_dlloader {
675   struct lt_dlloader   *next;
676   const char           *loader_name;    /* identifying name for each loader */
677   const char           *sym_prefix;     /* prefix for symbols */
678   lt_module_open       *module_open;
679   lt_module_close      *module_close;
680   lt_find_sym          *find_sym;
681   lt_dlloader_exit     *dlloader_exit;
682   lt_user_data          dlloader_data;
683 };
684
685 struct lt_dlhandle_struct {
686   struct lt_dlhandle_struct   *next;
687   lt_dlloader          *loader;         /* dlopening interface */
688   lt_dlinfo             info;
689   int                   depcount;       /* number of dependencies */
690   lt_dlhandle          *deplibs;        /* dependencies */
691   lt_module             module;         /* system module handle */
692   lt_ptr                system;         /* system specific data */
693   lt_caller_data       *caller_data;    /* per caller associated data */
694   int                   flags;          /* various boolean stats */
695 };
696
697 /* Various boolean flags can be stored in the flags field of an
698    lt_dlhandle_struct... */
699 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
700 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
701
702 #define LT_DLRESIDENT_FLAG          (0x01 << 0)
703 /* ...add more flags here... */
704
705 #define LT_DLIS_RESIDENT(handle)    LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
706
707
708 #define LT_DLSTRERROR(name)     lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
709
710 static  const char      objdir[]                = LTDL_OBJDIR;
711 static  const char      archive_ext[]           = LTDL_ARCHIVE_EXT;
712 #ifdef  LTDL_SHLIB_EXT
713 static  const char      shlib_ext[]             = LTDL_SHLIB_EXT;
714 #endif
715 #ifdef  LTDL_SYSSEARCHPATH
716 static  const char      sys_search_path[]       = LTDL_SYSSEARCHPATH;
717 #endif
718
719
720
721 \f
722 /* --- MUTEX LOCKING --- */
723
724
725 /* Macros to make it easier to run the lock functions only if they have
726    been registered.  The reason for the complicated lock macro is to
727    ensure that the stored error message from the last error is not
728    accidentally erased if the current function doesn't generate an
729    error of its own.  */
730 #define LT_DLMUTEX_LOCK()                       LT_STMT_START { \
731         if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)();    \
732                                                 } LT_STMT_END
733 #define LT_DLMUTEX_UNLOCK()                     LT_STMT_START { \
734         if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
735                                                 } LT_STMT_END
736 #define LT_DLMUTEX_SETERROR(errormsg)           LT_STMT_START { \
737         if (lt_dlmutex_seterror_func)                           \
738                 (*lt_dlmutex_seterror_func) (errormsg);         \
739         else    lt_dllast_error = (errormsg);   } LT_STMT_END
740 #define LT_DLMUTEX_GETERROR(errormsg)           LT_STMT_START { \
741         if (lt_dlmutex_seterror_func)                           \
742                 (errormsg) = (*lt_dlmutex_geterror_func) ();    \
743         else    (errormsg) = lt_dllast_error;   } LT_STMT_END
744
745 /* The mutex functions stored here are global, and are necessarily the
746    same for all threads that wish to share access to libltdl.  */
747 static  lt_dlmutex_lock     *lt_dlmutex_lock_func     = 0;
748 static  lt_dlmutex_unlock   *lt_dlmutex_unlock_func   = 0;
749 static  lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
750 static  lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
751 static  const char          *lt_dllast_error          = 0;
752
753
754 /* Either set or reset the mutex functions.  Either all the arguments must
755    be valid functions, or else all can be NULL to turn off locking entirely.
756    The registered functions should be manipulating a static global lock
757    from the lock() and unlock() callbacks, which needs to be reentrant.  */
758 int
759 lt_dlmutex_register (lock, unlock, seterror, geterror)
760      lt_dlmutex_lock *lock;
761      lt_dlmutex_unlock *unlock;
762      lt_dlmutex_seterror *seterror;
763      lt_dlmutex_geterror *geterror;
764 {
765   lt_dlmutex_unlock *old_unlock = unlock;
766   int                errors     = 0;
767
768   /* Lock using the old lock() callback, if any.  */
769   LT_DLMUTEX_LOCK ();
770
771   if ((lock && unlock && seterror && geterror)
772       || !(lock || unlock || seterror || geterror))
773     {
774       lt_dlmutex_lock_func     = lock;
775       lt_dlmutex_unlock_func   = unlock;
776       lt_dlmutex_geterror_func = geterror;
777     }
778   else
779     {
780       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
781       ++errors;
782     }
783
784   /* Use the old unlock() callback we saved earlier, if any.  Otherwise
785      record any errors using internal storage.  */
786   if (old_unlock)
787     (*old_unlock) ();
788
789   /* Return the number of errors encountered during the execution of
790      this function.  */
791   return errors;
792 }
793
794
795
796 \f
797 /* --- ERROR HANDLING --- */
798
799
800 static  const char    **user_error_strings      = 0;
801 static  int             errorcount              = LT_ERROR_MAX;
802
803 int
804 lt_dladderror (diagnostic)
805      const char *diagnostic;
806 {
807   int           errindex = 0;
808   int           result   = -1;
809   const char  **temp     = (const char **) 0;
810
811   assert (diagnostic);
812
813   LT_DLMUTEX_LOCK ();
814
815   errindex = errorcount - LT_ERROR_MAX;
816   temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
817   if (temp)
818     {
819       user_error_strings                = temp;
820       user_error_strings[errindex]      = diagnostic;
821       result                            = errorcount++;
822     }
823
824   LT_DLMUTEX_UNLOCK ();
825
826   return result;
827 }
828
829 int
830 lt_dlseterror (errindex)
831      int errindex;
832 {
833   int           errors   = 0;
834
835   LT_DLMUTEX_LOCK ();
836
837   if (errindex >= errorcount || errindex < 0)
838     {
839       /* Ack!  Error setting the error message! */
840       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
841       ++errors;
842     }
843   else if (errindex < LT_ERROR_MAX)
844     {
845       /* No error setting the error message! */
846       LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
847     }
848   else
849     {
850       /* No error setting the error message! */
851       LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
852     }
853
854   LT_DLMUTEX_UNLOCK ();
855
856   return errors;
857 }
858
859 lt_ptr
860 lt_emalloc (size)
861      size_t size;
862 {
863   lt_ptr mem = lt_dlmalloc (size);
864   if (size && !mem)
865     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
866   return mem;
867 }
868
869 lt_ptr
870 lt_erealloc (addr, size)
871      lt_ptr addr;
872      size_t size;
873 {
874   lt_ptr mem = realloc (addr, size);
875   if (size && !mem)
876     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
877   return mem;
878 }
879
880 char *
881 lt_estrdup (str)
882      const char *str;
883 {
884   char *dup = strdup (str);
885   if (LT_STRLEN (str) && !dup)
886     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
887   return dup;
888 }
889
890
891
892 \f
893 /* --- DLOPEN() INTERFACE LOADER --- */
894
895
896 /* The Cygwin dlopen implementation prints a spurious error message to
897    stderr if its call to LoadLibrary() fails for any reason.  We can
898    mitigate this by not using the Cygwin implementation, and falling
899    back to our own LoadLibrary() wrapper. */
900 #if HAVE_LIBDL && !defined(__CYGWIN__)
901
902 /* dynamic linking with dlopen/dlsym */
903
904 #if HAVE_DLFCN_H
905 #  include <dlfcn.h>
906 #endif
907
908 #if HAVE_SYS_DL_H
909 #  include <sys/dl.h>
910 #endif
911
912 #ifdef RTLD_GLOBAL
913 #  define LT_GLOBAL             RTLD_GLOBAL
914 #else
915 #  ifdef DL_GLOBAL
916 #    define LT_GLOBAL           DL_GLOBAL
917 #  endif
918 #endif /* !RTLD_GLOBAL */
919 #ifndef LT_GLOBAL
920 #  define LT_GLOBAL             0
921 #endif /* !LT_GLOBAL */
922
923 /* We may have to define LT_LAZY_OR_NOW in the command line if we
924    find out it does not work in some platform. */
925 #ifndef LT_LAZY_OR_NOW
926 #  ifdef RTLD_LAZY
927 #    define LT_LAZY_OR_NOW      RTLD_LAZY
928 #  else
929 #    ifdef DL_LAZY
930 #      define LT_LAZY_OR_NOW    DL_LAZY
931 #    endif
932 #  endif /* !RTLD_LAZY */
933 #endif
934 #ifndef LT_LAZY_OR_NOW
935 #  ifdef RTLD_NOW
936 #    define LT_LAZY_OR_NOW      RTLD_NOW
937 #  else
938 #    ifdef DL_NOW
939 #      define LT_LAZY_OR_NOW    DL_NOW
940 #    endif
941 #  endif /* !RTLD_NOW */
942 #endif
943 #ifndef LT_LAZY_OR_NOW
944 #  define LT_LAZY_OR_NOW        0
945 #endif /* !LT_LAZY_OR_NOW */
946
947 #if HAVE_DLERROR
948 #  define DLERROR(arg)  dlerror ()
949 #else
950 #  define DLERROR(arg)  LT_DLSTRERROR (arg)
951 #endif
952
953 static lt_module
954 sys_dl_open (loader_data, filename)
955      lt_user_data loader_data;
956      const char *filename;
957 {
958   lt_module   module   = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
959
960   if (!module)
961     {
962       LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
963     }
964
965   return module;
966 }
967
968 static int
969 sys_dl_close (loader_data, module)
970      lt_user_data loader_data;
971      lt_module module;
972 {
973   int errors = 0;
974
975   if (dlclose (module) != 0)
976     {
977       LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
978       ++errors;
979     }
980
981   return errors;
982 }
983
984 static lt_ptr
985 sys_dl_sym (loader_data, module, symbol)
986      lt_user_data loader_data;
987      lt_module module;
988      const char *symbol;
989 {
990   lt_ptr address = dlsym (module, symbol);
991
992   if (!address)
993     {
994       LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
995     }
996
997   return address;
998 }
999
1000 static struct lt_user_dlloader sys_dl =
1001   {
1002 #  ifdef NEED_USCORE
1003     "_",
1004 #  else
1005     0,
1006 #  endif
1007     sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1008
1009
1010 #endif /* HAVE_LIBDL */
1011
1012
1013 \f
1014 /* --- SHL_LOAD() INTERFACE LOADER --- */
1015
1016 #if HAVE_SHL_LOAD
1017
1018 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1019
1020 #ifdef HAVE_DL_H
1021 #  include <dl.h>
1022 #endif
1023
1024 /* some flags are missing on some systems, so we provide
1025  * harmless defaults.
1026  *
1027  * Mandatory:
1028  * BIND_IMMEDIATE  - Resolve symbol references when the library is loaded.
1029  * BIND_DEFERRED   - Delay code symbol resolution until actual reference.
1030  *
1031  * Optionally:
1032  * BIND_FIRST      - Place the library at the head of the symbol search
1033  *                   order.
1034  * BIND_NONFATAL   - The default BIND_IMMEDIATE behavior is to treat all
1035  *                   unsatisfied symbols as fatal.  This flag allows
1036  *                   binding of unsatisfied code symbols to be deferred
1037  *                   until use.
1038  *                   [Perl: For certain libraries, like DCE, deferred
1039  *                   binding often causes run time problems. Adding
1040  *                   BIND_NONFATAL to BIND_IMMEDIATE still allows
1041  *                   unresolved references in situations like this.]
1042  * BIND_NOSTART    - Do not call the initializer for the shared library
1043  *                   when the library is loaded, nor on a future call to
1044  *                   shl_unload().
1045  * BIND_VERBOSE    - Print verbose messages concerning possible
1046  *                   unsatisfied symbols.
1047  *
1048  * hp9000s700/hp9000s800:
1049  * BIND_RESTRICTED - Restrict symbols visible by the library to those
1050  *                   present at library load time.
1051  * DYNAMIC_PATH    - Allow the loader to dynamically search for the
1052  *                   library specified by the path argument.
1053  */
1054
1055 #ifndef DYNAMIC_PATH
1056 #  define DYNAMIC_PATH          0
1057 #endif
1058 #ifndef BIND_RESTRICTED
1059 #  define BIND_RESTRICTED       0
1060 #endif
1061
1062 #define LT_BIND_FLAGS   (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1063
1064 static lt_module
1065 sys_shl_open (loader_data, filename)
1066      lt_user_data loader_data;
1067      const char *filename;
1068 {
1069   static shl_t self = (shl_t) 0;
1070   lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1071
1072   /* Since searching for a symbol against a NULL module handle will also
1073      look in everything else that was already loaded and exported with
1074      the -E compiler flag, we always cache a handle saved before any
1075      modules are loaded.  */
1076   if (!self)
1077     {
1078       lt_ptr address;
1079       shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1080     }
1081
1082   if (!filename)
1083     {
1084       module = self;
1085     }
1086   else
1087     {
1088       module = shl_load (filename, LT_BIND_FLAGS, 0L);
1089
1090       if (!module)
1091         {
1092           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1093         }
1094     }
1095
1096   return module;
1097 }
1098
1099 static int
1100 sys_shl_close (loader_data, module)
1101      lt_user_data loader_data;
1102      lt_module module;
1103 {
1104   int errors = 0;
1105
1106   if (module && (shl_unload ((shl_t) (module)) != 0))
1107     {
1108       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1109       ++errors;
1110     }
1111
1112   return errors;
1113 }
1114
1115 static lt_ptr
1116 sys_shl_sym (loader_data, module, symbol)
1117      lt_user_data loader_data;
1118      lt_module module;
1119      const char *symbol;
1120 {
1121   lt_ptr address = 0;
1122
1123   /* sys_shl_open should never return a NULL module handle */
1124   if (module == (lt_module) 0)
1125   {
1126     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1127   }
1128   else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1129     {
1130       if (!address)
1131         {
1132           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1133         }
1134     }
1135
1136   return address;
1137 }
1138
1139 static struct lt_user_dlloader sys_shl = {
1140   0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1141 };
1142
1143 #endif /* HAVE_SHL_LOAD */
1144
1145
1146
1147 \f
1148 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1149
1150 #ifdef __WINDOWS__
1151
1152 /* dynamic linking for Win32 */
1153
1154 #include <windows.h>
1155
1156 /* Forward declaration; required to implement handle search below. */
1157 static lt_dlhandle handles;
1158
1159 static lt_module
1160 sys_wll_open (loader_data, filename)
1161      lt_user_data loader_data;
1162      const char *filename;
1163 {
1164   lt_dlhandle   cur;
1165   lt_module     module     = 0;
1166   const char   *errormsg   = 0;
1167   char         *searchname = 0;
1168   char         *ext;
1169   char          self_name_buf[MAX_PATH];
1170
1171   if (!filename)
1172     {
1173       /* Get the name of main module */
1174       *self_name_buf = 0;
1175       GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1176       filename = ext = self_name_buf;
1177     }
1178   else
1179     {
1180       ext = strrchr (filename, '.');
1181     }
1182
1183   if (ext)
1184     {
1185       /* FILENAME already has an extension. */
1186       searchname = lt_estrdup (filename);
1187     }
1188   else
1189     {
1190       /* Append a `.' to stop Windows from adding an
1191          implicit `.dll' extension. */
1192       searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1193       if (searchname)
1194         sprintf (searchname, "%s.", filename);
1195     }
1196   if (!searchname)
1197     return 0;
1198
1199 #if __CYGWIN__
1200   {
1201     char wpath[MAX_PATH];
1202     cygwin_conv_to_full_win32_path(searchname, wpath);
1203     module = LoadLibrary(wpath);
1204   }
1205 #else
1206   module = LoadLibrary (searchname);
1207 #endif
1208   LT_DLFREE (searchname);
1209
1210   /* libltdl expects this function to fail if it is unable
1211      to physically load the library.  Sadly, LoadLibrary
1212      will search the loaded libraries for a match and return
1213      one of them if the path search load fails.
1214
1215      We check whether LoadLibrary is returning a handle to
1216      an already loaded module, and simulate failure if we
1217      find one. */
1218   LT_DLMUTEX_LOCK ();
1219   cur = handles;
1220   while (cur)
1221     {
1222       if (!cur->module)
1223         {
1224           cur = 0;
1225           break;
1226         }
1227
1228       if (cur->module == module)
1229         {
1230           break;
1231         }
1232
1233       cur = cur->next;
1234   }
1235   LT_DLMUTEX_UNLOCK ();
1236
1237   if (cur || !module)
1238     {
1239       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1240       module = 0;
1241     }
1242
1243   return module;
1244 }
1245
1246 static int
1247 sys_wll_close (loader_data, module)
1248      lt_user_data loader_data;
1249      lt_module module;
1250 {
1251   int         errors   = 0;
1252
1253   if (FreeLibrary(module) == 0)
1254     {
1255       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1256       ++errors;
1257     }
1258
1259   return errors;
1260 }
1261
1262 static lt_ptr
1263 sys_wll_sym (loader_data, module, symbol)
1264      lt_user_data loader_data;
1265      lt_module module;
1266      const char *symbol;
1267 {
1268   lt_ptr      address  = GetProcAddress (module, symbol);
1269
1270   if (!address)
1271     {
1272       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1273     }
1274
1275   return address;
1276 }
1277
1278 static struct lt_user_dlloader sys_wll = {
1279   0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1280 };
1281
1282 #endif /* __WINDOWS__ */
1283
1284
1285
1286 \f
1287 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1288
1289
1290 #ifdef __BEOS__
1291
1292 /* dynamic linking for BeOS */
1293
1294 #include <kernel/image.h>
1295
1296 static lt_module
1297 sys_bedl_open (loader_data, filename)
1298      lt_user_data loader_data;
1299      const char *filename;
1300 {
1301   image_id image = 0;
1302
1303   if (filename)
1304     {
1305       image = load_add_on (filename);
1306     }
1307   else
1308     {
1309       image_info info;
1310       int32 cookie = 0;
1311       if (get_next_image_info (0, &cookie, &info) == B_OK)
1312         image = load_add_on (info.name);
1313     }
1314
1315   if (image <= 0)
1316     {
1317       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1318       image = 0;
1319     }
1320
1321   return (lt_module) image;
1322 }
1323
1324 static int
1325 sys_bedl_close (loader_data, module)
1326      lt_user_data loader_data;
1327      lt_module module;
1328 {
1329   int errors = 0;
1330
1331   if (unload_add_on ((image_id) module) != B_OK)
1332     {
1333       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1334       ++errors;
1335     }
1336
1337   return errors;
1338 }
1339
1340 static lt_ptr
1341 sys_bedl_sym (loader_data, module, symbol)
1342      lt_user_data loader_data;
1343      lt_module module;
1344      const char *symbol;
1345 {
1346   lt_ptr address = 0;
1347   image_id image = (image_id) module;
1348
1349   if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1350     {
1351       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1352       address = 0;
1353     }
1354
1355   return address;
1356 }
1357
1358 static struct lt_user_dlloader sys_bedl = {
1359   0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1360 };
1361
1362 #endif /* __BEOS__ */
1363
1364
1365
1366 \f
1367 /* --- DLD_LINK() INTERFACE LOADER --- */
1368
1369
1370 #if HAVE_DLD
1371
1372 /* dynamic linking with dld */
1373
1374 #if HAVE_DLD_H
1375 #include <dld.h>
1376 #endif
1377
1378 static lt_module
1379 sys_dld_open (loader_data, filename)
1380      lt_user_data loader_data;
1381      const char *filename;
1382 {
1383   lt_module module = strdup (filename);
1384
1385   if (dld_link (filename) != 0)
1386     {
1387       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1388       LT_DLFREE (module);
1389       module = 0;
1390     }
1391
1392   return module;
1393 }
1394
1395 static int
1396 sys_dld_close (loader_data, module)
1397      lt_user_data loader_data;
1398      lt_module module;
1399 {
1400   int errors = 0;
1401
1402   if (dld_unlink_by_file ((char*)(module), 1) != 0)
1403     {
1404       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1405       ++errors;
1406     }
1407   else
1408     {
1409       LT_DLFREE (module);
1410     }
1411
1412   return errors;
1413 }
1414
1415 static lt_ptr
1416 sys_dld_sym (loader_data, module, symbol)
1417      lt_user_data loader_data;
1418      lt_module module;
1419      const char *symbol;
1420 {
1421   lt_ptr address = dld_get_func (symbol);
1422
1423   if (!address)
1424     {
1425       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1426     }
1427
1428   return address;
1429 }
1430
1431 static struct lt_user_dlloader sys_dld = {
1432   0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1433 };
1434
1435 #endif /* HAVE_DLD */
1436
1437
1438
1439 \f
1440 /* --- DLPREOPEN() INTERFACE LOADER --- */
1441
1442
1443 /* emulate dynamic linking using preloaded_symbols */
1444
1445 typedef struct lt_dlsymlists_t
1446 {
1447   struct lt_dlsymlists_t       *next;
1448   const lt_dlsymlist           *syms;
1449 } lt_dlsymlists_t;
1450
1451 static  const lt_dlsymlist     *default_preloaded_symbols       = 0;
1452 static  lt_dlsymlists_t        *preloaded_symbols               = 0;
1453
1454 static int
1455 presym_init (loader_data)
1456      lt_user_data loader_data;
1457 {
1458   int errors = 0;
1459
1460   LT_DLMUTEX_LOCK ();
1461
1462   preloaded_symbols = 0;
1463   if (default_preloaded_symbols)
1464     {
1465       errors = lt_dlpreload (default_preloaded_symbols);
1466     }
1467
1468   LT_DLMUTEX_UNLOCK ();
1469
1470   return errors;
1471 }
1472
1473 static int
1474 presym_free_symlists ()
1475 {
1476   lt_dlsymlists_t *lists;
1477
1478   LT_DLMUTEX_LOCK ();
1479
1480   lists = preloaded_symbols;
1481   while (lists)
1482     {
1483       lt_dlsymlists_t   *tmp = lists;
1484
1485       lists = lists->next;
1486       LT_DLFREE (tmp);
1487     }
1488   preloaded_symbols = 0;
1489
1490   LT_DLMUTEX_UNLOCK ();
1491
1492   return 0;
1493 }
1494
1495 static int
1496 presym_exit (loader_data)
1497      lt_user_data loader_data;
1498 {
1499   presym_free_symlists ();
1500   return 0;
1501 }
1502
1503 static int
1504 presym_add_symlist (preloaded)
1505      const lt_dlsymlist *preloaded;
1506 {
1507   lt_dlsymlists_t *tmp;
1508   lt_dlsymlists_t *lists;
1509   int              errors   = 0;
1510
1511   LT_DLMUTEX_LOCK ();
1512
1513   lists = preloaded_symbols;
1514   while (lists)
1515     {
1516       if (lists->syms == preloaded)
1517         {
1518           goto done;
1519         }
1520       lists = lists->next;
1521     }
1522
1523   tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
1524   if (tmp)
1525     {
1526       memset (tmp, 0, sizeof(lt_dlsymlists_t));
1527       tmp->syms = preloaded;
1528       tmp->next = preloaded_symbols;
1529       preloaded_symbols = tmp;
1530     }
1531   else
1532     {
1533       ++errors;
1534     }
1535
1536  done:
1537   LT_DLMUTEX_UNLOCK ();
1538   return errors;
1539 }
1540
1541 static lt_module
1542 presym_open (loader_data, filename)
1543      lt_user_data loader_data;
1544      const char *filename;
1545 {
1546   lt_dlsymlists_t *lists;
1547   lt_module        module = (lt_module) 0;
1548
1549   LT_DLMUTEX_LOCK ();
1550   lists = preloaded_symbols;
1551
1552   if (!lists)
1553     {
1554       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
1555       goto done;
1556     }
1557
1558   /* Can't use NULL as the reflective symbol header, as NULL is
1559      used to mark the end of the entire symbol list.  Self-dlpreopened
1560      symbols follow this magic number, chosen to be an unlikely
1561      clash with a real module name.  */
1562   if (!filename)
1563     {
1564       filename = "@PROGRAM@";
1565     }
1566
1567   while (lists)
1568     {
1569       const lt_dlsymlist *syms = lists->syms;
1570
1571       while (syms->name)
1572         {
1573           if (!syms->address && strcmp(syms->name, filename) == 0)
1574             {
1575               module = (lt_module) syms;
1576               goto done;
1577             }
1578           ++syms;
1579         }
1580
1581       lists = lists->next;
1582     }
1583
1584   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
1585
1586  done:
1587   LT_DLMUTEX_UNLOCK ();
1588   return module;
1589 }
1590
1591 static int
1592 presym_close (loader_data, module)
1593      lt_user_data loader_data;
1594      lt_module module;
1595 {
1596   /* Just to silence gcc -Wall */
1597   module = 0;
1598   return 0;
1599 }
1600
1601 static lt_ptr
1602 presym_sym (loader_data, module, symbol)
1603      lt_user_data loader_data;
1604      lt_module module;
1605      const char *symbol;
1606 {
1607   lt_dlsymlist *syms = (lt_dlsymlist*) module;
1608
1609   ++syms;
1610   while (syms->address)
1611     {
1612       if (strcmp(syms->name, symbol) == 0)
1613         {
1614           return syms->address;
1615         }
1616
1617     ++syms;
1618   }
1619
1620   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1621
1622   return 0;
1623 }
1624
1625 static struct lt_user_dlloader presym = {
1626   0, presym_open, presym_close, presym_sym, presym_exit, 0
1627 };
1628
1629
1630
1631
1632 \f
1633 /* --- DYNAMIC MODULE LOADING --- */
1634
1635
1636 /* The type of a function used at each iteration of  foreach_dirinpath().  */
1637 typedef int     foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
1638                                                  lt_ptr data2));
1639
1640 static  int     foreach_dirinpath     LT_PARAMS((const char *search_path,
1641                                                  const char *base_name,
1642                                                  foreach_callback_func *func,
1643                                                  lt_ptr data1, lt_ptr data2));
1644
1645 static  int     find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
1646                                                  lt_ptr ignored));
1647 static  int     find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
1648                                                  lt_ptr ignored));
1649 static  int     foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
1650                                                  lt_ptr data2));
1651
1652
1653 static  int     canonicalize_path     LT_PARAMS((const char *path,
1654                                                  char **pcanonical));
1655 static  int     argzize_path          LT_PARAMS((const char *path,
1656                                                  char **pargz,
1657                                                  size_t *pargz_len));
1658 static  FILE   *find_file             LT_PARAMS((const char *search_path,
1659                                                  const char *base_name,
1660                                                  char **pdir));
1661 static  lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
1662                                                  const char *base_name,
1663                                                  lt_dlhandle *handle));
1664 static  int     find_module           LT_PARAMS((lt_dlhandle *handle,
1665                                                  const char *dir,
1666                                                  const char *libdir,
1667                                                  const char *dlname,
1668                                                  const char *old_name,
1669                                                  int installed));
1670 static  int     free_vars             LT_PARAMS((char *dlname, char *oldname,
1671                                                  char *libdir, char *deplibs));
1672 static  int     load_deplibs          LT_PARAMS((lt_dlhandle handle,
1673                                                  char *deplibs));
1674 static  int     trim                  LT_PARAMS((char **dest,
1675                                                  const char *str));
1676 static  int     try_dlopen            LT_PARAMS((lt_dlhandle *handle,
1677                                                  const char *filename));
1678 static  int     tryall_dlopen         LT_PARAMS((lt_dlhandle *handle,
1679                                                  const char *filename));
1680 static  int     unload_deplibs        LT_PARAMS((lt_dlhandle handle));
1681 static  int     lt_argz_insert        LT_PARAMS((char **pargz,
1682                                                  size_t *pargz_len,
1683                                                  char *before,
1684                                                  const char *entry));
1685 static  int     lt_argz_insertinorder LT_PARAMS((char **pargz,
1686                                                  size_t *pargz_len,
1687                                                  const char *entry));
1688 static  int     lt_dlpath_insertdir   LT_PARAMS((char **ppath,
1689                                                  char *before,
1690                                                  const char *dir));
1691
1692 static  char           *user_search_path= 0;
1693 static  lt_dlloader    *loaders         = 0;
1694 static  lt_dlhandle     handles         = 0;
1695 static  int             initialized     = 0;
1696
1697 /* Initialize libltdl. */
1698 int
1699 lt_dlinit ()
1700 {
1701   int         errors   = 0;
1702
1703   LT_DLMUTEX_LOCK ();
1704
1705   /* Initialize only at first call. */
1706   if (++initialized == 1)
1707     {
1708       handles = 0;
1709       user_search_path = 0; /* empty search path */
1710
1711 #if HAVE_LIBDL && !defined(__CYGWIN__)
1712       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
1713 #endif
1714 #if HAVE_SHL_LOAD
1715       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
1716 #endif
1717 #ifdef __WINDOWS__
1718       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
1719 #endif
1720 #ifdef __BEOS__
1721       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
1722 #endif
1723 #if HAVE_DLD
1724       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
1725 #endif
1726       errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
1727
1728       if (presym_init (presym.dlloader_data))
1729         {
1730           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
1731           ++errors;
1732         }
1733       else if (errors != 0)
1734         {
1735           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
1736           ++errors;
1737         }
1738     }
1739
1740   LT_DLMUTEX_UNLOCK ();
1741
1742   return errors;
1743 }
1744
1745 int
1746 lt_dlpreload (preloaded)
1747      const lt_dlsymlist *preloaded;
1748 {
1749   int errors = 0;
1750
1751   if (preloaded)
1752     {
1753       errors = presym_add_symlist (preloaded);
1754     }
1755   else
1756     {
1757       presym_free_symlists();
1758
1759       LT_DLMUTEX_LOCK ();
1760       if (default_preloaded_symbols)
1761         {
1762           errors = lt_dlpreload (default_preloaded_symbols);
1763         }
1764       LT_DLMUTEX_UNLOCK ();
1765     }
1766
1767   return errors;
1768 }
1769
1770 int
1771 lt_dlpreload_default (preloaded)
1772      const lt_dlsymlist *preloaded;
1773 {
1774   LT_DLMUTEX_LOCK ();
1775   default_preloaded_symbols = preloaded;
1776   LT_DLMUTEX_UNLOCK ();
1777   return 0;
1778 }
1779
1780 int
1781 lt_dlexit ()
1782 {
1783   /* shut down libltdl */
1784   lt_dlloader *loader;
1785   int          errors   = 0;
1786
1787   LT_DLMUTEX_LOCK ();
1788   loader = loaders;
1789
1790   if (!initialized)
1791     {
1792       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
1793       ++errors;
1794       goto done;
1795     }
1796
1797   /* shut down only at last call. */
1798   if (--initialized == 0)
1799     {
1800       int       level;
1801
1802       while (handles && LT_DLIS_RESIDENT (handles))
1803         {
1804           handles = handles->next;
1805         }
1806
1807       /* close all modules */
1808       for (level = 1; handles; ++level)
1809         {
1810           lt_dlhandle cur = handles;
1811           int saw_nonresident = 0;
1812
1813           while (cur)
1814             {
1815               lt_dlhandle tmp = cur;
1816               cur = cur->next;
1817               if (!LT_DLIS_RESIDENT (tmp))
1818                 saw_nonresident = 1;
1819               if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
1820                 {
1821                   if (lt_dlclose (tmp))
1822                     {
1823                       ++errors;
1824                     }
1825                 }
1826             }
1827           /* done if only resident modules are left */
1828           if (!saw_nonresident)
1829             break;
1830         }
1831
1832       /* close all loaders */
1833       while (loader)
1834         {
1835           lt_dlloader *next = loader->next;
1836           lt_user_data data = loader->dlloader_data;
1837           if (loader->dlloader_exit && loader->dlloader_exit (data))
1838             {
1839               ++errors;
1840             }
1841
1842           LT_DLMEM_REASSIGN (loader, next);
1843         }
1844       loaders = 0;
1845     }
1846
1847  done:
1848   LT_DLMUTEX_UNLOCK ();
1849   return errors;
1850 }
1851
1852 static int
1853 tryall_dlopen (handle, filename)
1854      lt_dlhandle *handle;
1855      const char *filename;
1856 {
1857   lt_dlhandle    cur;
1858   lt_dlloader   *loader;
1859   const char    *saved_error;
1860   int            errors         = 0;
1861
1862   LT_DLMUTEX_GETERROR (saved_error);
1863   LT_DLMUTEX_LOCK ();
1864
1865   cur    = handles;
1866   loader = loaders;
1867
1868   /* check whether the module was already opened */
1869   while (cur)
1870     {
1871       /* try to dlopen the program itself? */
1872       if (!cur->info.filename && !filename)
1873         {
1874           break;
1875         }
1876
1877       if (cur->info.filename && filename
1878           && strcmp (cur->info.filename, filename) == 0)
1879         {
1880           break;
1881         }
1882
1883       cur = cur->next;
1884     }
1885
1886   if (cur)
1887     {
1888       ++cur->info.ref_count;
1889       *handle = cur;
1890       goto done;
1891     }
1892
1893   cur = *handle;
1894   if (filename)
1895     {
1896       cur->info.filename = lt_estrdup (filename);
1897       if (!cur->info.filename)
1898         {
1899           ++errors;
1900           goto done;
1901         }
1902     }
1903   else
1904     {
1905       cur->info.filename = 0;
1906     }
1907
1908   while (loader)
1909     {
1910       lt_user_data data = loader->dlloader_data;
1911
1912       cur->module = loader->module_open (data, filename);
1913
1914       if (cur->module != 0)
1915         {
1916           break;
1917         }
1918       loader = loader->next;
1919     }
1920
1921   if (!loader)
1922     {
1923       LT_DLFREE (cur->info.filename);
1924       ++errors;
1925       goto done;
1926     }
1927
1928   cur->loader   = loader;
1929   LT_DLMUTEX_SETERROR (saved_error);
1930
1931  done:
1932   LT_DLMUTEX_UNLOCK ();
1933
1934   return errors;
1935 }
1936
1937 static int
1938 tryall_dlopen_module (handle, prefix, dirname, dlname)
1939      lt_dlhandle *handle;
1940      const char *prefix;
1941      const char *dirname;
1942      const char *dlname;
1943 {
1944   int      error        = 0;
1945   char     *filename    = 0;
1946   size_t   filename_len = 0;
1947   size_t   dirname_len  = LT_STRLEN (dirname);
1948
1949   assert (handle);
1950   assert (dirname);
1951   assert (dlname);
1952 #ifdef LT_DIRSEP_CHAR
1953   /* Only canonicalized names (i.e. with DIRSEP chars already converted)
1954      should make it into this function:  */
1955   assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
1956 #endif
1957
1958   if (dirname[dirname_len -1] == '/')
1959     --dirname_len;
1960   filename_len = dirname_len + 1 + LT_STRLEN (dlname);
1961
1962   /* Allocate memory, and combine DIRNAME and MODULENAME into it.
1963      The PREFIX (if any) is handled below.  */
1964   filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
1965   if (!filename)
1966     return 1;
1967
1968   sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
1969
1970   /* Now that we have combined DIRNAME and MODULENAME, if there is
1971      also a PREFIX to contend with, simply recurse with the arguments
1972      shuffled.  Otherwise, attempt to open FILENAME as a module.  */
1973   if (prefix)
1974     {
1975       error += tryall_dlopen_module (handle,
1976                                      (const char *) 0, prefix, filename);
1977     }
1978   else if (tryall_dlopen (handle, filename) != 0)
1979     {
1980       ++error;
1981     }
1982
1983   LT_DLFREE (filename);
1984   return error;
1985 }
1986
1987 static int
1988 find_module (handle, dir, libdir, dlname, old_name, installed)
1989      lt_dlhandle *handle;
1990      const char *dir;
1991      const char *libdir;
1992      const char *dlname;
1993      const char *old_name;
1994      int installed;
1995 {
1996   /* Try to open the old library first; if it was dlpreopened,
1997      we want the preopened version of it, even if a dlopenable
1998      module is available.  */
1999   if (old_name && tryall_dlopen (handle, old_name) == 0)
2000     {
2001       return 0;
2002     }
2003
2004   /* Try to open the dynamic library.  */
2005   if (dlname)
2006     {
2007       /* try to open the installed module */
2008       if (installed && libdir)
2009         {
2010           if (tryall_dlopen_module (handle,
2011                                     (const char *) 0, libdir, dlname) == 0)
2012             return 0;
2013         }
2014
2015       /* try to open the not-installed module */
2016       if (!installed)
2017         {
2018           if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2019             return 0;
2020         }
2021
2022       /* maybe it was moved to another directory */
2023       {
2024           if (tryall_dlopen_module (handle,
2025                                     (const char *) 0, dir, dlname) == 0)
2026             return 0;
2027       }
2028     }
2029
2030   return 1;
2031 }
2032
2033
2034 static int
2035 canonicalize_path (path, pcanonical)
2036      const char *path;
2037      char **pcanonical;
2038 {
2039   char *canonical = 0;
2040
2041   assert (path && *path);
2042   assert (pcanonical);
2043
2044   canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2045   if (!canonical)
2046     return 1;
2047
2048   {
2049     size_t dest = 0;
2050     size_t src;
2051     for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2052       {
2053         /* Path separators are not copied to the beginning or end of
2054            the destination, or if another separator would follow
2055            immediately.  */
2056         if (path[src] == LT_PATHSEP_CHAR)
2057           {
2058             if ((dest == 0)
2059                 || (path[1+ src] == LT_PATHSEP_CHAR)
2060                 || (path[1+ src] == LT_EOS_CHAR))
2061               continue;
2062           }
2063
2064         /* Anything other than a directory separator is copied verbatim.  */
2065         if ((path[src] != '/')
2066 #ifdef LT_DIRSEP_CHAR
2067             && (path[src] != LT_DIRSEP_CHAR)
2068 #endif
2069             )
2070           {
2071             canonical[dest++] = path[src];
2072           }
2073         /* Directory separators are converted and copied only if they are
2074            not at the end of a path -- i.e. before a path separator or
2075            NULL terminator.  */
2076         else if ((path[1+ src] != LT_PATHSEP_CHAR)
2077                  && (path[1+ src] != LT_EOS_CHAR)
2078 #ifdef LT_DIRSEP_CHAR
2079                  && (path[1+ src] != LT_DIRSEP_CHAR)
2080 #endif
2081                  && (path[1+ src] != '/'))
2082           {
2083             canonical[dest++] = '/';
2084           }
2085       }
2086
2087     /* Add an end-of-string marker at the end.  */
2088     canonical[dest] = LT_EOS_CHAR;
2089   }
2090
2091   /* Assign new value.  */
2092   *pcanonical = canonical;
2093
2094   return 0;
2095 }
2096
2097 static int
2098 argzize_path (path, pargz, pargz_len)
2099      const char *path;
2100      char **pargz;
2101      size_t *pargz_len;
2102 {
2103   error_t error;
2104
2105   assert (path);
2106   assert (pargz);
2107   assert (pargz_len);
2108
2109   if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2110     {
2111       switch (error)
2112         {
2113         case ENOMEM:
2114           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2115           break;
2116         default:
2117           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2118           break;
2119         }
2120
2121       return 1;
2122     }
2123
2124   return 0;
2125 }
2126
2127 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2128    of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2129    non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
2130    it is appended to each SEARCH_PATH element before FUNC is called.  */
2131 static int
2132 foreach_dirinpath (search_path, base_name, func, data1, data2)
2133      const char *search_path;
2134      const char *base_name;
2135      foreach_callback_func *func;
2136      lt_ptr data1;
2137      lt_ptr data2;
2138 {
2139   int    result         = 0;
2140   int    filenamesize   = 0;
2141   int    lenbase        = LT_STRLEN (base_name);
2142   size_t argz_len       = 0;
2143   char * argz           = 0;
2144   char * filename       = 0;
2145   char * canonical      = 0;
2146
2147   LT_DLMUTEX_LOCK ();
2148
2149   if (!search_path || !*search_path)
2150     {
2151       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2152       goto cleanup;
2153     }
2154
2155   if (canonicalize_path (search_path, &canonical) != 0)
2156     goto cleanup;
2157
2158   if (argzize_path (canonical, &argz, &argz_len) != 0)
2159     goto cleanup;
2160
2161   {
2162     char *dir_name = 0;
2163     while ((dir_name = argz_next (argz, argz_len, dir_name)))
2164       {
2165         int lendir = LT_STRLEN (dir_name);
2166
2167         if (lendir +1 +lenbase >= filenamesize)
2168         {
2169           LT_DLFREE (filename);
2170           filenamesize  = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2171           filename      = LT_EMALLOC (char, filenamesize);
2172           if (!filename)
2173             goto cleanup;
2174         }
2175
2176         strncpy (filename, dir_name, lendir);
2177         if (base_name && *base_name)
2178           {
2179             if (filename[lendir -1] != '/')
2180               filename[lendir++] = '/';
2181             strcpy (filename +lendir, base_name);
2182           }
2183
2184         if ((result = (*func) (filename, data1, data2)))
2185           {
2186             break;
2187           }
2188       }
2189   }
2190
2191  cleanup:
2192   LT_DLFREE (argz);
2193   LT_DLFREE (canonical);
2194   LT_DLFREE (filename);
2195
2196   LT_DLMUTEX_UNLOCK ();
2197
2198   return result;
2199 }
2200
2201 /* If FILEPATH can be opened, store the name of the directory component
2202    in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
2203    DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
2204 static int
2205 find_file_callback (filename, data1, data2)
2206      char *filename;
2207      lt_ptr data1;
2208      lt_ptr data2;
2209 {
2210   char       **pdir     = (char **) data1;
2211   FILE       **pfile    = (FILE **) data2;
2212   int        is_done    = 0;
2213
2214   assert (filename && *filename);
2215   assert (pdir);
2216   assert (pfile);
2217
2218   if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2219     {
2220       char *dirend = strrchr (filename, '/');
2221
2222       if (dirend > filename)
2223         *dirend   = LT_EOS_CHAR;
2224
2225       LT_DLFREE (*pdir);
2226       *pdir   = lt_estrdup (filename);
2227       is_done = (*pdir == 0) ? -1 : 1;
2228     }
2229
2230   return is_done;
2231 }
2232
2233 static FILE *
2234 find_file (search_path, base_name, pdir)
2235      const char *search_path;
2236      const char *base_name;
2237      char **pdir;
2238 {
2239   FILE *file = 0;
2240
2241   foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2242
2243   return file;
2244 }
2245
2246 static int
2247 find_handle_callback (filename, data, ignored)
2248      char *filename;
2249      lt_ptr data;
2250      lt_ptr ignored;
2251 {
2252   lt_dlhandle  *handle  = (lt_dlhandle *) data;
2253   int           got_access_error        = access (filename, R_OK);
2254
2255   /* Bail out if file cannot be read...  */
2256   if (got_access_error)
2257     return 0;
2258
2259   /* Try to dlopen the file, but do not continue searching in any
2260      case.  */
2261   if (tryall_dlopen (handle, filename) != 0)
2262     *handle = 0;
2263
2264   return 1;
2265 }
2266
2267 /* If HANDLE was found return it, otherwise return 0.  If HANDLE was
2268    found but could not be opened, *HANDLE will be set to 0.  */
2269 static lt_dlhandle *
2270 find_handle (search_path, base_name, handle)
2271      const char *search_path;
2272      const char *base_name;
2273      lt_dlhandle *handle;
2274 {
2275   if (!search_path)
2276     return 0;
2277
2278   if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2279                           handle, 0))
2280     return 0;
2281
2282   return handle;
2283 }
2284
2285 static int
2286 load_deplibs (handle, deplibs)
2287      lt_dlhandle handle;
2288      char *deplibs;
2289 {
2290 #if LTDL_DLOPEN_DEPLIBS
2291   char  *p, *save_search_path = 0;
2292   int   depcount = 0;
2293   int   i;
2294   char  **names = 0;
2295 #endif
2296   int   errors = 0;
2297
2298   handle->depcount = 0;
2299
2300 #if LTDL_DLOPEN_DEPLIBS
2301   if (!deplibs)
2302     {
2303       return errors;
2304     }
2305   ++errors;
2306
2307   LT_DLMUTEX_LOCK ();
2308   if (user_search_path)
2309     {
2310       save_search_path = lt_estrdup (user_search_path);
2311       if (!save_search_path)
2312         goto cleanup;
2313     }
2314
2315   /* extract search paths and count deplibs */
2316   p = deplibs;
2317   while (*p)
2318     {
2319       if (!isspace ((int) *p))
2320         {
2321           char *end = p+1;
2322           while (*end && !isspace((int) *end))
2323             {
2324               ++end;
2325             }
2326
2327           if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2328             {
2329               char save = *end;
2330               *end = 0; /* set a temporary string terminator */
2331               if (lt_dladdsearchdir(p+2))
2332                 {
2333                   goto cleanup;
2334                 }
2335               *end = save;
2336             }
2337           else
2338             {
2339               ++depcount;
2340             }
2341
2342           p = end;
2343         }
2344       else
2345         {
2346           ++p;
2347         }
2348     }
2349
2350   /* restore the old search path */
2351   LT_DLFREE (user_search_path);
2352   user_search_path = save_search_path;
2353
2354   LT_DLMUTEX_UNLOCK ();
2355
2356   if (!depcount)
2357     {
2358       errors = 0;
2359       goto cleanup;
2360     }
2361
2362   names = LT_EMALLOC (char *, depcount * sizeof (char*));
2363   if (!names)
2364     goto cleanup;
2365
2366   /* now only extract the actual deplibs */
2367   depcount = 0;
2368   p = deplibs;
2369   while (*p)
2370     {
2371       if (isspace ((int) *p))
2372         {
2373           ++p;
2374         }
2375       else
2376         {
2377           char *end = p+1;
2378           while (*end && !isspace ((int) *end))
2379             {
2380               ++end;
2381             }
2382
2383           if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2384             {
2385               char *name;
2386               char save = *end;
2387               *end = 0; /* set a temporary string terminator */
2388               if (strncmp(p, "-l", 2) == 0)
2389                 {
2390                   size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2391                   name = LT_EMALLOC (char, 1+ name_len);
2392                   if (name)
2393                     sprintf (name, "lib%s", p+2);
2394                 }
2395               else
2396                 name = lt_estrdup(p);
2397
2398               if (!name)
2399                 goto cleanup_names;
2400
2401               names[depcount++] = name;
2402               *end = save;
2403             }
2404           p = end;
2405         }
2406     }
2407
2408   /* load the deplibs (in reverse order)
2409      At this stage, don't worry if the deplibs do not load correctly,
2410      they may already be statically linked into the loading application
2411      for instance.  There will be a more enlightening error message
2412      later on if the loaded module cannot resolve all of its symbols.  */
2413   if (depcount)
2414     {
2415       int       j = 0;
2416
2417       handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2418       if (!handle->deplibs)
2419         goto cleanup;
2420
2421       for (i = 0; i < depcount; ++i)
2422         {
2423           handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2424           if (handle->deplibs[j])
2425             {
2426               ++j;
2427             }
2428         }
2429
2430       handle->depcount  = j;    /* Number of successfully loaded deplibs */
2431       errors            = 0;
2432     }
2433
2434  cleanup_names:
2435   for (i = 0; i < depcount; ++i)
2436     {
2437       LT_DLFREE (names[i]);
2438     }
2439
2440  cleanup:
2441   LT_DLFREE (names);
2442 #endif
2443
2444   return errors;
2445 }
2446
2447 static int
2448 unload_deplibs (handle)
2449      lt_dlhandle handle;
2450 {
2451   int i;
2452   int errors = 0;
2453
2454   if (handle->depcount)
2455     {
2456       for (i = 0; i < handle->depcount; ++i)
2457         {
2458           if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
2459             {
2460               errors += lt_dlclose (handle->deplibs[i]);
2461             }
2462         }
2463     }
2464
2465   return errors;
2466 }
2467
2468 static int
2469 trim (dest, str)
2470      char **dest;
2471      const char *str;
2472 {
2473   /* remove the leading and trailing "'" from str
2474      and store the result in dest */
2475   const char *end   = strrchr (str, '\'');
2476   int   len         = LT_STRLEN (str);
2477   char *tmp;
2478
2479   LT_DLFREE (*dest);
2480
2481   if (len > 3 && str[0] == '\'')
2482     {
2483       tmp = LT_EMALLOC (char, end - str);
2484       if (!tmp)
2485         return 1;
2486
2487       strncpy(tmp, &str[1], (end - str) - 1);
2488       tmp[len-3] = LT_EOS_CHAR;
2489       *dest = tmp;
2490     }
2491   else
2492     {
2493       *dest = 0;
2494     }
2495
2496   return 0;
2497 }
2498
2499 static int
2500 free_vars (dlname, oldname, libdir, deplibs)
2501      char *dlname;
2502      char *oldname;
2503      char *libdir;
2504      char *deplibs;
2505 {
2506   LT_DLFREE (dlname);
2507   LT_DLFREE (oldname);
2508   LT_DLFREE (libdir);
2509   LT_DLFREE (deplibs);
2510
2511   return 0;
2512 }
2513
2514 int
2515 try_dlopen (phandle, filename)
2516      lt_dlhandle *phandle;
2517      const char *filename;
2518 {
2519   const char *  ext             = 0;
2520   const char *  saved_error     = 0;
2521   char *        canonical       = 0;
2522   char *        base_name       = 0;
2523   char *        dir             = 0;
2524   char *        name            = 0;
2525   int           errors          = 0;
2526   lt_dlhandle   newhandle;
2527
2528   assert (phandle);
2529   assert (*phandle == 0);
2530
2531   LT_DLMUTEX_GETERROR (saved_error);
2532
2533   /* dlopen self? */
2534   if (!filename)
2535     {
2536       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2537       if (*phandle == 0)
2538         return 1;
2539
2540       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
2541       newhandle = *phandle;
2542
2543       /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
2544       LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
2545
2546       if (tryall_dlopen (&newhandle, 0) != 0)
2547         {
2548           LT_DLFREE (*phandle);
2549           return 1;
2550         }
2551
2552       goto register_handle;
2553     }
2554
2555   assert (filename && *filename);
2556
2557   /* Doing this immediately allows internal functions to safely
2558      assume only canonicalized paths are passed.  */
2559   if (canonicalize_path (filename, &canonical) != 0)
2560     {
2561       ++errors;
2562       goto cleanup;
2563     }
2564
2565   /* If the canonical module name is a path (relative or absolute)
2566      then split it into a directory part and a name part.  */
2567   base_name = strrchr (canonical, '/');
2568   if (base_name)
2569     {
2570       size_t dirlen = (1+ base_name) - canonical;
2571
2572       dir = LT_EMALLOC (char, 1+ dirlen);
2573       if (!dir)
2574         {
2575           ++errors;
2576           goto cleanup;
2577         }
2578
2579       strncpy (dir, canonical, dirlen);
2580       dir[dirlen] = LT_EOS_CHAR;
2581
2582       ++base_name;
2583     }
2584   else
2585     LT_DLMEM_REASSIGN (base_name, canonical);
2586
2587   assert (base_name && *base_name);
2588
2589   /* Check whether we are opening a libtool module (.la extension).  */
2590   ext = strrchr (base_name, '.');
2591   if (ext && strcmp (ext, archive_ext) == 0)
2592     {
2593       /* this seems to be a libtool module */
2594       FILE *    file     = 0;
2595       char *    dlname   = 0;
2596       char *    old_name = 0;
2597       char *    libdir   = 0;
2598       char *    deplibs  = 0;
2599       char *    line     = 0;
2600       size_t    line_len;
2601       int       i;
2602
2603       /* if we can't find the installed flag, it is probably an
2604          installed libtool archive, produced with an old version
2605          of libtool */
2606       int       installed = 1;
2607
2608       /* extract the module name from the file name */
2609       name = LT_EMALLOC (char, ext - base_name + 1);
2610       if (!name)
2611         {
2612           ++errors;
2613           goto cleanup;
2614         }
2615
2616       /* canonicalize the module name */
2617       for (i = 0; i < ext - base_name; ++i)
2618         {
2619           if (isalnum ((int)(base_name[i])))
2620             {
2621               name[i] = base_name[i];
2622             }
2623           else
2624             {
2625               name[i] = '_';
2626             }
2627         }
2628       name[ext - base_name] = LT_EOS_CHAR;
2629
2630     /* Now try to open the .la file.  If there is no directory name
2631        component, try to find it first in user_search_path and then other
2632        prescribed paths.  Otherwise (or in any case if the module was not
2633        yet found) try opening just the module name as passed.  */
2634       if (!dir)
2635         {
2636           const char *search_path;
2637
2638           LT_DLMUTEX_LOCK ();
2639           search_path = user_search_path;
2640           if (search_path)
2641             file = find_file (user_search_path, base_name, &dir);
2642           LT_DLMUTEX_UNLOCK ();
2643
2644           if (!file)
2645             {
2646               search_path = getenv (LTDL_SEARCHPATH_VAR);
2647               if (search_path)
2648                 file = find_file (search_path, base_name, &dir);
2649             }
2650
2651 #ifdef LTDL_SHLIBPATH_VAR
2652           if (!file)
2653             {
2654               search_path = getenv (LTDL_SHLIBPATH_VAR);
2655               if (search_path)
2656                 file = find_file (search_path, base_name, &dir);
2657             }
2658 #endif
2659 #ifdef LTDL_SYSSEARCHPATH
2660           if (!file && sys_search_path)
2661             {
2662               file = find_file (sys_search_path, base_name, &dir);
2663             }
2664 #endif
2665         }
2666       if (!file)
2667         {
2668           file = fopen (filename, LT_READTEXT_MODE);
2669         }
2670
2671       /* If we didn't find the file by now, it really isn't there.  Set
2672          the status flag, and bail out.  */
2673       if (!file)
2674         {
2675           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2676           ++errors;
2677           goto cleanup;
2678         }
2679
2680       line_len = LT_FILENAME_MAX;
2681       line = LT_EMALLOC (char, line_len);
2682       if (!line)
2683         {
2684           fclose (file);
2685           ++errors;
2686           goto cleanup;
2687         }
2688
2689       /* read the .la file */
2690       while (!feof (file))
2691         {
2692           if (!fgets (line, line_len, file))
2693             {
2694               break;
2695             }
2696
2697           /* Handle the case where we occasionally need to read a line
2698              that is longer than the initial buffer size.  */
2699           while (line[LT_STRLEN(line) -1] != '\n')
2700             {
2701               line = LT_DLREALLOC (char, line, line_len *2);
2702               if (!fgets (&line[line_len -1], line_len +1, file))
2703                 {
2704                   break;
2705                 }
2706               line_len *= 2;
2707             }
2708
2709           if (line[0] == '\n' || line[0] == '#')
2710             {
2711               continue;
2712             }
2713
2714 #undef  STR_DLNAME
2715 #define STR_DLNAME      "dlname="
2716           if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
2717             {
2718               errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
2719             }
2720
2721 #undef  STR_OLD_LIBRARY
2722 #define STR_OLD_LIBRARY "old_library="
2723           else if (strncmp (line, STR_OLD_LIBRARY,
2724                             sizeof (STR_OLD_LIBRARY) - 1) == 0)
2725             {
2726               errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
2727             }
2728 #undef  STR_LIBDIR
2729 #define STR_LIBDIR      "libdir="
2730           else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
2731             {
2732               errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
2733             }
2734
2735 #undef  STR_DL_DEPLIBS
2736 #define STR_DL_DEPLIBS  "dependency_libs="
2737           else if (strncmp (line, STR_DL_DEPLIBS,
2738                             sizeof (STR_DL_DEPLIBS) - 1) == 0)
2739             {
2740               errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
2741             }
2742           else if (strcmp (line, "installed=yes\n") == 0)
2743             {
2744               installed = 1;
2745             }
2746           else if (strcmp (line, "installed=no\n") == 0)
2747             {
2748               installed = 0;
2749             }
2750
2751 #undef  STR_LIBRARY_NAMES
2752 #define STR_LIBRARY_NAMES "library_names="
2753           else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
2754                                         sizeof (STR_LIBRARY_NAMES) - 1) == 0)
2755             {
2756               char *last_libname;
2757               errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
2758               if (!errors
2759                   && dlname
2760                   && (last_libname = strrchr (dlname, ' ')) != 0)
2761                 {
2762                   last_libname = lt_estrdup (last_libname + 1);
2763                   if (!last_libname)
2764                     {
2765                       ++errors;
2766                       goto cleanup;
2767                     }
2768                   LT_DLMEM_REASSIGN (dlname, last_libname);
2769                 }
2770             }
2771
2772           if (errors)
2773             break;
2774         }
2775
2776       fclose (file);
2777       LT_DLFREE (line);
2778
2779       /* allocate the handle */
2780       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2781       if (*phandle == 0)
2782         ++errors;
2783
2784       if (errors)
2785         {
2786           free_vars (dlname, old_name, libdir, deplibs);
2787           LT_DLFREE (*phandle);
2788           goto cleanup;
2789         }
2790
2791       assert (*phandle);
2792
2793       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
2794       if (load_deplibs (*phandle, deplibs) == 0)
2795         {
2796           newhandle = *phandle;
2797           /* find_module may replace newhandle */
2798           if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
2799             {
2800               unload_deplibs (*phandle);
2801               ++errors;
2802             }
2803         }
2804       else
2805         {
2806           ++errors;
2807         }
2808
2809       free_vars (dlname, old_name, libdir, deplibs);
2810       if (errors)
2811         {
2812           LT_DLFREE (*phandle);
2813           goto cleanup;
2814         }
2815
2816       if (*phandle != newhandle)
2817         {
2818           unload_deplibs (*phandle);
2819         }
2820     }
2821   else
2822     {
2823       /* not a libtool module */
2824       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2825       if (*phandle == 0)
2826         {
2827           ++errors;
2828           goto cleanup;
2829         }
2830
2831       memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
2832       newhandle = *phandle;
2833
2834       /* If the module has no directory name component, try to find it
2835          first in user_search_path and then other prescribed paths.
2836          Otherwise (or in any case if the module was not yet found) try
2837          opening just the module name as passed.  */
2838       if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
2839                    && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
2840                                     &newhandle)
2841 #ifdef LTDL_SHLIBPATH_VAR
2842                    && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
2843                                     &newhandle)
2844 #endif
2845 #ifdef LTDL_SYSSEARCHPATH
2846                    && !find_handle (sys_search_path, base_name, &newhandle)
2847 #endif
2848                    )))
2849         {
2850           tryall_dlopen (&newhandle, filename);
2851         }
2852
2853       if (!newhandle)
2854         {
2855           LT_DLFREE (*phandle);
2856           ++errors;
2857           goto cleanup;
2858         }
2859     }
2860
2861  register_handle:
2862   LT_DLMEM_REASSIGN (*phandle, newhandle);
2863
2864   if ((*phandle)->info.ref_count == 0)
2865     {
2866       (*phandle)->info.ref_count        = 1;
2867       LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
2868
2869       LT_DLMUTEX_LOCK ();
2870       (*phandle)->next          = handles;
2871       handles                   = *phandle;
2872       LT_DLMUTEX_UNLOCK ();
2873     }
2874
2875   LT_DLMUTEX_SETERROR (saved_error);
2876
2877  cleanup:
2878   LT_DLFREE (dir);
2879   LT_DLFREE (name);
2880   LT_DLFREE (canonical);
2881
2882   return errors;
2883 }
2884
2885 lt_dlhandle
2886 lt_dlopen (filename)
2887      const char *filename;
2888 {
2889   lt_dlhandle handle = 0;
2890
2891   /* Just incase we missed a code path in try_dlopen() that reports
2892      an error, but forgets to reset handle... */
2893   if (try_dlopen (&handle, filename) != 0)
2894     return 0;
2895
2896   return handle;
2897 }
2898
2899 /* If the last error messge store was `FILE_NOT_FOUND', then return
2900    non-zero.  */
2901 int
2902 file_not_found ()
2903 {
2904   const char *error = 0;
2905
2906   LT_DLMUTEX_GETERROR (error);
2907   if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
2908     return 1;
2909
2910   return 0;
2911 }
2912
2913 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
2914    open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
2915    and if a file is still not found try again with SHLIB_EXT appended
2916    instead.  */
2917 lt_dlhandle
2918 lt_dlopenext (filename)
2919      const char *filename;
2920 {
2921   lt_dlhandle   handle          = 0;
2922   char *        tmp             = 0;
2923   char *        ext             = 0;
2924   int           len;
2925   int           errors          = 0;
2926   int           file_found      = 1; /* until proven otherwise */
2927
2928   if (!filename)
2929     {
2930       return lt_dlopen (filename);
2931     }
2932
2933   assert (filename);
2934
2935   len = LT_STRLEN (filename);
2936   ext = strrchr (filename, '.');
2937
2938   /* If FILENAME already bears a suitable extension, there is no need
2939      to try appending additional extensions.  */
2940   if (ext && ((strcmp (ext, archive_ext) == 0)
2941 #ifdef LTDL_SHLIB_EXT
2942               || (strcmp (ext, shlib_ext) == 0)
2943 #endif
2944       ))
2945     {
2946       return lt_dlopen (filename);
2947     }
2948
2949   /* First try appending ARCHIVE_EXT.  */
2950   tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
2951   if (!tmp)
2952     return 0;
2953
2954   strcpy (tmp, filename);
2955   strcat (tmp, archive_ext);
2956   errors = try_dlopen (&handle, tmp);
2957
2958   /* If we found FILENAME, stop searching -- whether we were able to
2959      load the file as a module or not.  If the file exists but loading
2960      failed, it is better to return an error message here than to
2961      report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
2962      in the module search path.  */
2963   if (handle || ((errors > 0) && !file_not_found ()))
2964     {
2965       LT_DLFREE (tmp);
2966       return handle;
2967     }
2968
2969 #ifdef LTDL_SHLIB_EXT
2970   /* Try appending SHLIB_EXT.   */
2971   if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
2972     {
2973       LT_DLFREE (tmp);
2974       tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
2975       if (!tmp)
2976         return 0;
2977
2978       strcpy (tmp, filename);
2979     }
2980   else
2981     {
2982       tmp[len] = LT_EOS_CHAR;
2983     }
2984
2985   strcat(tmp, shlib_ext);
2986   errors = try_dlopen (&handle, tmp);
2987
2988   /* As before, if the file was found but loading failed, return now
2989      with the current error message.  */
2990   if (handle || ((errors > 0) && file_not_found ()))
2991     {
2992       LT_DLFREE (tmp);
2993       return handle;
2994     }
2995 #endif
2996
2997   /* Still here?  Then we really did fail to locate any of the file
2998      names we tried.  */
2999   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3000   LT_DLFREE (tmp);
3001   return 0;
3002 }
3003
3004
3005 int
3006 lt_argz_insert (pargz, pargz_len, before, entry)
3007      char **pargz;
3008      size_t *pargz_len;
3009      char *before;
3010      const char *entry;
3011 {
3012   error_t error;
3013
3014   if ((error = argz_insert (pargz, pargz_len, before, entry)))
3015     {
3016       switch (error)
3017         {
3018         case ENOMEM:
3019           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3020           break;
3021         default:
3022           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3023           break;
3024         }
3025       return 1;
3026     }
3027
3028   return 0;
3029 }
3030
3031 int
3032 lt_argz_insertinorder (pargz, pargz_len, entry)
3033      char **pargz;
3034      size_t *pargz_len;
3035      const char *entry;
3036 {
3037   char *before = 0;
3038
3039   assert (pargz);
3040   assert (pargz_len);
3041   assert (entry && *entry);
3042
3043   if (*pargz)
3044     while ((before = argz_next (*pargz, *pargz_len, before)))
3045       {
3046         int cmp = strcmp (entry, before);
3047
3048         if (cmp < 0)  break;
3049         if (cmp == 0) return 0; /* No duplicates! */
3050       }
3051
3052   return lt_argz_insert (pargz, pargz_len, before, entry);
3053 }
3054
3055 int
3056 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3057      char **pargz;
3058      size_t *pargz_len;
3059      const char *dirnam;
3060      struct dirent *dp;
3061 {
3062   char   *buf       = 0;
3063   size_t buf_len    = 0;
3064   char   *end       = 0;
3065   size_t end_offset = 0;
3066   size_t dir_len    = 0;
3067   int    errors     = 0;
3068
3069   assert (pargz);
3070   assert (pargz_len);
3071   assert (dp);
3072
3073   dir_len = LT_STRLEN (dirnam);
3074   end     = dp->d_name + LT_D_NAMLEN(dp);
3075
3076   /* Ignore version numbers.  */
3077   {
3078     char *p;
3079     for (p = end; p -1 > dp->d_name; --p)
3080       if (strchr (".0123456789", p[-1]) == 0)
3081         break;
3082
3083     if (*p == '.')
3084       end = p;
3085   }
3086
3087   /* Ignore filename extension.  */
3088   {
3089     char *p;
3090     for (p = end -1; p > dp->d_name; --p)
3091       if (*p == '.')
3092         {
3093           end = p;
3094           break;
3095         }
3096   }
3097
3098   /* Prepend the directory name.  */
3099   end_offset    = end - dp->d_name;
3100   buf_len       = dir_len + 1+ end_offset;
3101   buf           = LT_EMALLOC (char, 1+ buf_len);
3102   if (!buf)
3103     return ++errors;
3104
3105   assert (buf);
3106
3107   strcpy  (buf, dirnam);
3108   strcat  (buf, "/");
3109   strncat (buf, dp->d_name, end_offset);
3110   buf[buf_len] = LT_EOS_CHAR;
3111
3112   /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
3113   if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3114     ++errors;
3115
3116   LT_DLFREE (buf);
3117
3118   return errors;
3119 }
3120
3121 int
3122 list_files_by_dir (dirnam, pargz, pargz_len)
3123      const char *dirnam;
3124      char **pargz;
3125      size_t *pargz_len;
3126 {
3127   DIR   *dirp     = 0;
3128   int    errors   = 0;
3129
3130   assert (dirnam && *dirnam);
3131   assert (pargz);
3132   assert (pargz_len);
3133   assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3134
3135   dirp = opendir (dirnam);
3136   if (dirp)
3137     {
3138       struct dirent *dp = 0;
3139
3140       while ((dp = readdir (dirp)))
3141         if (dp->d_name[0] != '.')
3142           if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3143             {
3144               ++errors;
3145               break;
3146             }
3147
3148       closedir (dirp);
3149     }
3150   else
3151     ++errors;
3152
3153   return errors;
3154 }
3155
3156
3157 /* If there are any files in DIRNAME, call the function passed in
3158    DATA1 (with the name of each file and DATA2 as arguments).  */
3159 static int
3160 foreachfile_callback (dirname, data1, data2)
3161      char *dirname;
3162      lt_ptr data1;
3163      lt_ptr data2;
3164 {
3165   int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3166         = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3167
3168   int     is_done  = 0;
3169   char   *argz     = 0;
3170   size_t  argz_len = 0;
3171
3172   if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3173     goto cleanup;
3174   if (!argz)
3175     goto cleanup;
3176
3177   {
3178     char *filename = 0;
3179     while ((filename = argz_next (argz, argz_len, filename)))
3180       if ((is_done = (*func) (filename, data2)))
3181         break;
3182   }
3183
3184  cleanup:
3185   LT_DLFREE (argz);
3186
3187   return is_done;
3188 }
3189
3190
3191 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3192    with DATA.  The filenames passed to FUNC would be suitable for
3193    passing to lt_dlopenext.  The extensions are stripped so that
3194    individual modules do not generate several entries (e.g. libfoo.la,
3195    libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
3196    then the same directories that lt_dlopen would search are examined.  */
3197 int
3198 lt_dlforeachfile (search_path, func, data)
3199      const char *search_path;
3200      int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3201      lt_ptr data;
3202 {
3203   int is_done = 0;
3204
3205   if (search_path)
3206     {
3207       /* If a specific path was passed, search only the directories
3208          listed in it.  */
3209       is_done = foreach_dirinpath (search_path, 0,
3210                                    foreachfile_callback, func, data);
3211     }
3212   else
3213     {
3214       /* Otherwise search the default paths.  */
3215       is_done = foreach_dirinpath (user_search_path, 0,
3216                                    foreachfile_callback, func, data);
3217       if (!is_done)
3218         {
3219           is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3220                                        foreachfile_callback, func, data);
3221         }
3222
3223 #ifdef LTDL_SHLIBPATH_VAR
3224       if (!is_done)
3225         {
3226           is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3227                                        foreachfile_callback, func, data);
3228         }
3229 #endif
3230 #ifdef LTDL_SYSSEARCHPATH
3231       if (!is_done)
3232         {
3233           is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3234                                        foreachfile_callback, func, data);
3235         }
3236 #endif
3237     }
3238
3239   return is_done;
3240 }
3241
3242 int
3243 lt_dlclose (handle)
3244      lt_dlhandle handle;
3245 {
3246   lt_dlhandle cur, last;
3247   int errors = 0;
3248
3249   LT_DLMUTEX_LOCK ();
3250
3251   /* check whether the handle is valid */
3252   last = cur = handles;
3253   while (cur && handle != cur)
3254     {
3255       last = cur;
3256       cur = cur->next;
3257     }
3258
3259   if (!cur)
3260     {
3261       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3262       ++errors;
3263       goto done;
3264     }
3265
3266   handle->info.ref_count--;
3267
3268   /* Note that even with resident modules, we must track the ref_count
3269      correctly incase the user decides to reset the residency flag
3270      later (even though the API makes no provision for that at the
3271      moment).  */
3272   if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3273     {
3274       lt_user_data data = handle->loader->dlloader_data;
3275
3276       if (handle != handles)
3277         {
3278           last->next = handle->next;
3279         }
3280       else
3281         {
3282           handles = handle->next;
3283         }
3284
3285       errors += handle->loader->module_close (data, handle->module);
3286       errors += unload_deplibs(handle);
3287
3288       LT_DLFREE (handle->info.filename);
3289       LT_DLFREE (handle->info.name);
3290       LT_DLFREE (handle);
3291
3292       goto done;
3293     }
3294
3295   if (LT_DLIS_RESIDENT (handle))
3296     {
3297       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3298       ++errors;
3299     }
3300
3301  done:
3302   LT_DLMUTEX_UNLOCK ();
3303
3304   return errors;
3305 }
3306
3307 lt_ptr
3308 lt_dlsym (handle, symbol)
3309      lt_dlhandle handle;
3310      const char *symbol;
3311 {
3312   int   lensym;
3313   char  lsym[LT_SYMBOL_LENGTH];
3314   char  *sym;
3315   lt_ptr address;
3316   lt_user_data data;
3317
3318   if (!handle)
3319     {
3320       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3321       return 0;
3322     }
3323
3324   if (!symbol)
3325     {
3326       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3327       return 0;
3328     }
3329
3330   lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3331                                         + LT_STRLEN (handle->info.name);
3332
3333   if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3334     {
3335       sym = lsym;
3336     }
3337   else
3338     {
3339       sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3340       if (!sym)
3341         {
3342           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3343           return 0;
3344         }
3345     }
3346
3347   data = handle->loader->dlloader_data;
3348   if (handle->info.name)
3349     {
3350       const char *saved_error;
3351
3352       LT_DLMUTEX_GETERROR (saved_error);
3353
3354       /* this is a libtool module */
3355       if (handle->loader->sym_prefix)
3356         {
3357           strcpy(sym, handle->loader->sym_prefix);
3358           strcat(sym, handle->info.name);
3359         }
3360       else
3361         {
3362           strcpy(sym, handle->info.name);
3363         }
3364
3365       strcat(sym, "_LTX_");
3366       strcat(sym, symbol);
3367
3368       /* try "modulename_LTX_symbol" */
3369       address = handle->loader->find_sym (data, handle->module, sym);
3370       if (address)
3371         {
3372           if (sym != lsym)
3373             {
3374               LT_DLFREE (sym);
3375             }
3376           return address;
3377         }
3378       LT_DLMUTEX_SETERROR (saved_error);
3379     }
3380
3381   /* otherwise try "symbol" */
3382   if (handle->loader->sym_prefix)
3383     {
3384       strcpy(sym, handle->loader->sym_prefix);
3385       strcat(sym, symbol);
3386     }
3387   else
3388     {
3389       strcpy(sym, symbol);
3390     }
3391
3392   address = handle->loader->find_sym (data, handle->module, sym);
3393   if (sym != lsym)
3394     {
3395       LT_DLFREE (sym);
3396     }
3397
3398   return address;
3399 }
3400
3401 const char *
3402 lt_dlerror ()
3403 {
3404   const char *error;
3405
3406   LT_DLMUTEX_GETERROR (error);
3407   LT_DLMUTEX_SETERROR (0);
3408
3409   return error ? error : LT_DLSTRERROR (UNKNOWN);
3410 }
3411
3412 int
3413 lt_dlpath_insertdir (ppath, before, dir)
3414      char **ppath;
3415      char *before;
3416      const char *dir;
3417 {
3418   int    errors         = 0;
3419   char  *canonical      = 0;
3420   char  *argz           = 0;
3421   size_t argz_len       = 0;
3422
3423   assert (ppath);
3424   assert (dir && *dir);
3425
3426   if (canonicalize_path (dir, &canonical) != 0)
3427     {
3428       ++errors;
3429       goto cleanup;
3430     }
3431
3432   assert (canonical && *canonical);
3433
3434   /* If *PPATH is empty, set it to DIR.  */
3435   if (*ppath == 0)
3436     {
3437       assert (!before);         /* BEFORE cannot be set without PPATH.  */
3438       assert (dir);             /* Without DIR, don't call this function!  */
3439
3440       *ppath = lt_estrdup (dir);
3441       if (*ppath == 0)
3442         ++errors;
3443
3444       return errors;
3445     }
3446
3447   assert (ppath && *ppath);
3448
3449   if (argzize_path (*ppath, &argz, &argz_len) != 0)
3450     {
3451       ++errors;
3452       goto cleanup;
3453     }
3454
3455   /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
3456      if *PPATH is already canonicalized, and hence does not change length
3457      with respect to ARGZ.  We canonicalize each entry as it is added to
3458      the search path, and don't call this function with (uncanonicalized)
3459      user paths, so this is a fair assumption.  */
3460   if (before)
3461     {
3462       assert (*ppath <= before);
3463       assert (before - *ppath <= strlen (*ppath));
3464
3465       before = before - *ppath + argz;
3466     }
3467
3468   if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
3469     {
3470       ++errors;
3471       goto cleanup;
3472     }
3473
3474   argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
3475   LT_DLMEM_REASSIGN (*ppath,  argz);
3476
3477  cleanup:
3478   LT_DLFREE (canonical);
3479   LT_DLFREE (argz);
3480
3481   return errors;
3482 }
3483
3484 int
3485 lt_dladdsearchdir (search_dir)
3486      const char *search_dir;
3487 {
3488   int errors = 0;
3489
3490   if (search_dir && *search_dir)
3491     {
3492       LT_DLMUTEX_LOCK ();
3493       if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
3494         ++errors;
3495       LT_DLMUTEX_UNLOCK ();
3496     }
3497
3498   return errors;
3499 }
3500
3501 int
3502 lt_dlinsertsearchdir (before, search_dir)
3503      const char *before;
3504      const char *search_dir;
3505 {
3506   int errors = 0;
3507
3508   if (before)
3509     {
3510       LT_DLMUTEX_LOCK ();
3511       if ((before < user_search_path)
3512           || (before >= user_search_path + LT_STRLEN (user_search_path)))
3513         {
3514           LT_DLMUTEX_UNLOCK ();
3515           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
3516           return 1;
3517         }
3518       LT_DLMUTEX_UNLOCK ();
3519     }
3520
3521   if (search_dir && *search_dir)
3522     {
3523       LT_DLMUTEX_LOCK ();
3524       if (lt_dlpath_insertdir (&user_search_path,
3525                                (char *) before, search_dir) != 0)
3526         {
3527           ++errors;
3528         }
3529       LT_DLMUTEX_UNLOCK ();
3530     }
3531
3532   return errors;
3533 }
3534
3535 int
3536 lt_dlsetsearchpath (search_path)
3537      const char *search_path;
3538 {
3539   int   errors      = 0;
3540
3541   LT_DLMUTEX_LOCK ();
3542   LT_DLFREE (user_search_path);
3543   LT_DLMUTEX_UNLOCK ();
3544
3545   if (!search_path || !LT_STRLEN (search_path))
3546     {
3547       return errors;
3548     }
3549
3550   LT_DLMUTEX_LOCK ();
3551   if (canonicalize_path (search_path, &user_search_path) != 0)
3552     ++errors;
3553   LT_DLMUTEX_UNLOCK ();
3554
3555   return errors;
3556 }
3557
3558 const char *
3559 lt_dlgetsearchpath ()
3560 {
3561   const char *saved_path;
3562
3563   LT_DLMUTEX_LOCK ();
3564   saved_path = user_search_path;
3565   LT_DLMUTEX_UNLOCK ();
3566
3567   return saved_path;
3568 }
3569
3570 int
3571 lt_dlmakeresident (handle)
3572      lt_dlhandle handle;
3573 {
3574   int errors = 0;
3575
3576   if (!handle)
3577     {
3578       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3579       ++errors;
3580     }
3581   else
3582     {
3583       LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
3584     }
3585
3586   return errors;
3587 }
3588
3589 int
3590 lt_dlisresident (handle)
3591      lt_dlhandle handle;
3592 {
3593   if (!handle)
3594     {
3595       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3596       return -1;
3597     }
3598
3599   return LT_DLIS_RESIDENT (handle);
3600 }
3601
3602
3603
3604 \f
3605 /* --- MODULE INFORMATION --- */
3606
3607 const lt_dlinfo *
3608 lt_dlgetinfo (handle)
3609      lt_dlhandle handle;
3610 {
3611   if (!handle)
3612     {
3613       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3614       return 0;
3615     }
3616
3617   return &(handle->info);
3618 }
3619
3620 lt_dlhandle
3621 lt_dlhandle_next (place)
3622      lt_dlhandle place;
3623 {
3624   return place ? place->next : handles;
3625 }
3626
3627 int
3628 lt_dlforeach (func, data)
3629      int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
3630      lt_ptr data;
3631 {
3632   int errors = 0;
3633   lt_dlhandle cur;
3634
3635   LT_DLMUTEX_LOCK ();
3636
3637   cur = handles;
3638   while (cur)
3639     {
3640       lt_dlhandle tmp = cur;
3641
3642       cur = cur->next;
3643       if ((*func) (tmp, data))
3644         {
3645           ++errors;
3646           break;
3647         }
3648     }
3649
3650   LT_DLMUTEX_UNLOCK ();
3651
3652   return errors;
3653 }
3654
3655 lt_dlcaller_id
3656 lt_dlcaller_register ()
3657 {
3658   static lt_dlcaller_id last_caller_id = 0;
3659   int result;
3660
3661   LT_DLMUTEX_LOCK ();
3662   result = ++last_caller_id;
3663   LT_DLMUTEX_UNLOCK ();
3664
3665   return result;
3666 }
3667
3668 lt_ptr
3669 lt_dlcaller_set_data (key, handle, data)
3670      lt_dlcaller_id key;
3671      lt_dlhandle handle;
3672      lt_ptr data;
3673 {
3674   int n_elements = 0;
3675   lt_ptr stale = (lt_ptr) 0;
3676   int i;
3677
3678   /* This needs to be locked so that the caller data can be updated
3679      simultaneously by different threads.  */
3680   LT_DLMUTEX_LOCK ();
3681
3682   if (handle->caller_data)
3683     while (handle->caller_data[n_elements].key)
3684       ++n_elements;
3685
3686   for (i = 0; i < n_elements; ++i)
3687     {
3688       if (handle->caller_data[i].key == key)
3689         {
3690           stale = handle->caller_data[i].data;
3691           break;
3692         }
3693     }
3694
3695   /* Ensure that there is enough room in this handle's caller_data
3696      array to accept a new element (and an empty end marker).  */
3697   if (i == n_elements)
3698     {
3699       lt_caller_data *temp
3700         = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
3701
3702       if (!temp)
3703         {
3704           stale = 0;
3705           goto done;
3706         }
3707
3708       handle->caller_data = temp;
3709
3710       /* We only need this if we needed to allocate a new caller_data.  */
3711       handle->caller_data[i].key  = key;
3712       handle->caller_data[1+ i].key = 0;
3713     }
3714
3715   handle->caller_data[i].data = data;
3716
3717  done:
3718   LT_DLMUTEX_UNLOCK ();
3719
3720   return stale;
3721 }
3722
3723 lt_ptr
3724 lt_dlcaller_get_data  (key, handle)
3725      lt_dlcaller_id key;
3726      lt_dlhandle handle;
3727 {
3728   lt_ptr result = (lt_ptr) 0;
3729
3730   /* This needs to be locked so that the caller data isn't updated by
3731      another thread part way through this function.  */
3732   LT_DLMUTEX_LOCK ();
3733
3734   /* Locate the index of the element with a matching KEY.  */
3735   {
3736     int i;
3737     for (i = 0; handle->caller_data[i].key; ++i)
3738       {
3739         if (handle->caller_data[i].key == key)
3740           {
3741             result = handle->caller_data[i].data;
3742             break;
3743           }
3744       }
3745   }
3746
3747   LT_DLMUTEX_UNLOCK ();
3748
3749   return result;
3750 }
3751
3752
3753 \f
3754 /* --- USER MODULE LOADER API --- */
3755
3756
3757 int
3758 lt_dlloader_add (place, dlloader, loader_name)
3759      lt_dlloader *place;
3760      const struct lt_user_dlloader *dlloader;
3761      const char *loader_name;
3762 {
3763   int errors = 0;
3764   lt_dlloader *node = 0, *ptr = 0;
3765
3766   if ((dlloader == 0)   /* diagnose null parameters */
3767       || (dlloader->module_open == 0)
3768       || (dlloader->module_close == 0)
3769       || (dlloader->find_sym == 0))
3770     {
3771       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3772       return 1;
3773     }
3774
3775   /* Create a new dlloader node with copies of the user callbacks.  */
3776   node = LT_EMALLOC (lt_dlloader, 1);
3777   if (!node)
3778     return 1;
3779
3780   node->next            = 0;
3781   node->loader_name     = loader_name;
3782   node->sym_prefix      = dlloader->sym_prefix;
3783   node->dlloader_exit   = dlloader->dlloader_exit;
3784   node->module_open     = dlloader->module_open;
3785   node->module_close    = dlloader->module_close;
3786   node->find_sym        = dlloader->find_sym;
3787   node->dlloader_data   = dlloader->dlloader_data;
3788
3789   LT_DLMUTEX_LOCK ();
3790   if (!loaders)
3791     {
3792       /* If there are no loaders, NODE becomes the list! */
3793       loaders = node;
3794     }
3795   else if (!place)
3796     {
3797       /* If PLACE is not set, add NODE to the end of the
3798          LOADERS list. */
3799       for (ptr = loaders; ptr->next; ptr = ptr->next)
3800         {
3801           /*NOWORK*/;
3802         }
3803
3804       ptr->next = node;
3805     }
3806   else if (loaders == place)
3807     {
3808       /* If PLACE is the first loader, NODE goes first. */
3809       node->next = place;
3810       loaders = node;
3811     }
3812   else
3813     {
3814       /* Find the node immediately preceding PLACE. */
3815       for (ptr = loaders; ptr->next != place; ptr = ptr->next)
3816         {
3817           /*NOWORK*/;
3818         }
3819
3820       if (ptr->next != place)
3821         {
3822           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3823           ++errors;
3824         }
3825       else
3826         {
3827           /* Insert NODE between PTR and PLACE. */
3828           node->next = place;
3829           ptr->next  = node;
3830         }
3831     }
3832
3833   LT_DLMUTEX_UNLOCK ();
3834
3835   return errors;
3836 }
3837
3838 int
3839 lt_dlloader_remove (loader_name)
3840      const char *loader_name;
3841 {
3842   lt_dlloader *place = lt_dlloader_find (loader_name);
3843   lt_dlhandle handle;
3844   int errors = 0;
3845
3846   if (!place)
3847     {
3848       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3849       return 1;
3850     }
3851
3852   LT_DLMUTEX_LOCK ();
3853
3854   /* Fail if there are any open modules which use this loader. */
3855   for  (handle = handles; handle; handle = handle->next)
3856     {
3857       if (handle->loader == place)
3858         {
3859           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
3860           ++errors;
3861           goto done;
3862         }
3863     }
3864
3865   if (place == loaders)
3866     {
3867       /* PLACE is the first loader in the list. */
3868       loaders = loaders->next;
3869     }
3870   else
3871     {
3872       /* Find the loader before the one being removed. */
3873       lt_dlloader *prev;
3874       for (prev = loaders; prev->next; prev = prev->next)
3875         {
3876           if (!strcmp (prev->next->loader_name, loader_name))
3877             {
3878               break;
3879             }
3880         }
3881
3882       place = prev->next;
3883       prev->next = prev->next->next;
3884     }
3885
3886   if (place->dlloader_exit)
3887     {
3888       errors = place->dlloader_exit (place->dlloader_data);
3889     }
3890
3891   LT_DLFREE (place);
3892
3893  done:
3894   LT_DLMUTEX_UNLOCK ();
3895
3896   return errors;
3897 }
3898
3899 lt_dlloader *
3900 lt_dlloader_next (place)
3901      lt_dlloader *place;
3902 {
3903   lt_dlloader *next;
3904
3905   LT_DLMUTEX_LOCK ();
3906   next = place ? place->next : loaders;
3907   LT_DLMUTEX_UNLOCK ();
3908
3909   return next;
3910 }
3911
3912 const char *
3913 lt_dlloader_name (place)
3914      lt_dlloader *place;
3915 {
3916   const char *name = 0;
3917
3918   if (place)
3919     {
3920       LT_DLMUTEX_LOCK ();
3921       name = place ? place->loader_name : 0;
3922       LT_DLMUTEX_UNLOCK ();
3923     }
3924   else
3925     {
3926       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3927     }
3928
3929   return name;
3930 }
3931
3932 lt_user_data *
3933 lt_dlloader_data (place)
3934      lt_dlloader *place;
3935 {
3936   lt_user_data *data = 0;
3937
3938   if (place)
3939     {
3940       LT_DLMUTEX_LOCK ();
3941       data = place ? &(place->dlloader_data) : 0;
3942       LT_DLMUTEX_UNLOCK ();
3943     }
3944   else
3945     {
3946       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3947     }
3948
3949   return data;
3950 }
3951
3952 lt_dlloader *
3953 lt_dlloader_find (loader_name)
3954      const char *loader_name;
3955 {
3956   lt_dlloader *place = 0;
3957
3958   LT_DLMUTEX_LOCK ();
3959   for (place = loaders; place; place = place->next)
3960     {
3961       if (strcmp (place->loader_name, loader_name) == 0)
3962         {
3963           break;
3964         }
3965     }
3966   LT_DLMUTEX_UNLOCK ();
3967
3968   return place;
3969 }