OSDN Git Service

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