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