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