New build path variable
[freeradius.git] / libltdl / ltdl.c
1 /* ltdl.c -- system independent dlopen wrapper
2    Copyright (C) 1998, 1999, 2000, 2004, 2005  Free Software Foundation, Inc.
3    Originally by Thomas Tanner <tanner@ffii.org>
4    This file is part of GNU Libtool.
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 As a special exception to the GNU Lesser General Public License,
12 if you distribute this file as part of a program or library that
13 is built using GNU libtool, you may include it under the same
14 distribution terms that you use for the rest of that program.
15
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 Lesser General Public License for more details.
20
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 02110-1301  USA
25
26 */
27
28 #if HAVE_CONFIG_H
29 #  include <config.h>
30 #endif
31
32 #if HAVE_UNISTD_H
33 #  include <unistd.h>
34 #endif
35
36 #if HAVE_STDIO_H
37 #  include <stdio.h>
38 #endif
39
40 /* Include the header defining malloc.  On K&R C compilers,
41    that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>.  */
42 #if HAVE_STDLIB_H
43 #  include <stdlib.h>
44 #else
45 #  if HAVE_MALLOC_H
46 #    include <malloc.h>
47 #  endif
48 #endif
49
50 #if HAVE_STRING_H
51 #  include <string.h>
52 #else
53 #  if HAVE_STRINGS_H
54 #    include <strings.h>
55 #  endif
56 #endif
57
58 #if HAVE_CTYPE_H
59 #  include <ctype.h>
60 #endif
61
62 #if HAVE_MEMORY_H
63 #  include <memory.h>
64 #endif
65
66 #if HAVE_ERRNO_H
67 #  include <errno.h>
68 #endif
69
70
71 #ifndef __WINDOWS__
72 #  ifdef __WIN32__
73 #    define __WINDOWS__
74 #  endif
75 #endif
76
77
78 #undef LT_USE_POSIX_DIRENT
79 #ifdef HAVE_CLOSEDIR
80 #  ifdef HAVE_OPENDIR
81 #    ifdef HAVE_READDIR
82 #      ifdef HAVE_DIRENT_H
83 #        define LT_USE_POSIX_DIRENT
84 #      endif /* HAVE_DIRENT_H */
85 #    endif /* HAVE_READDIR */
86 #  endif /* HAVE_OPENDIR */
87 #endif /* HAVE_CLOSEDIR */
88
89
90 #undef LT_USE_WINDOWS_DIRENT_EMULATION
91 #ifndef LT_USE_POSIX_DIRENT
92 #  ifdef __WINDOWS__
93 #    define LT_USE_WINDOWS_DIRENT_EMULATION
94 #  endif /* __WINDOWS__ */
95 #endif /* LT_USE_POSIX_DIRENT */
96
97
98 #ifdef LT_USE_POSIX_DIRENT
99 #  include <dirent.h>
100 #  define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
101 #else
102 #  ifdef LT_USE_WINDOWS_DIRENT_EMULATION
103 #    define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
104 #  else
105 #    define dirent direct
106 #    define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
107 #    if HAVE_SYS_NDIR_H
108 #      include <sys/ndir.h>
109 #    endif
110 #    if HAVE_SYS_DIR_H
111 #      include <sys/dir.h>
112 #    endif
113 #    if HAVE_NDIR_H
114 #      include <ndir.h>
115 #    endif
116 #  endif
117 #endif
118
119 #if HAVE_ARGZ_H
120 #  include <argz.h>
121 #endif
122
123 #if HAVE_ASSERT_H
124 #  include <assert.h>
125 #else
126 #  define assert(arg)   ((void) 0)
127 #endif
128
129 #include "ltdl.h"
130
131 #if WITH_DMALLOC
132 #  include <dmalloc.h>
133 #endif
134
135
136
137 \f
138 /* --- WINDOWS SUPPORT --- */
139
140
141 #ifdef DLL_EXPORT
142 #  define LT_GLOBAL_DATA        __declspec(dllexport)
143 #else
144 #  define LT_GLOBAL_DATA
145 #endif
146
147 /* fopen() mode flags for reading a text file */
148 #undef  LT_READTEXT_MODE
149 #ifdef __WINDOWS__
150 #  define LT_READTEXT_MODE "rt"
151 #else
152 #  define LT_READTEXT_MODE "r"
153 #endif
154
155 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
156
157 #include <windows.h>
158
159 #define dirent lt_dirent
160 #define DIR lt_DIR
161
162 struct dirent
163 {
164   char d_name[2048];
165   int  d_namlen;
166 };
167
168 typedef struct _DIR
169 {
170   HANDLE hSearch;
171   WIN32_FIND_DATA Win32FindData;
172   BOOL firsttime;
173   struct dirent file_info;
174 } DIR;
175
176 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
177
178 \f
179 /* --- MANIFEST CONSTANTS --- */
180
181
182 /* Standard libltdl search path environment variable name  */
183 #undef  LTDL_SEARCHPATH_VAR
184 #define LTDL_SEARCHPATH_VAR     "LTDL_LIBRARY_PATH"
185
186 /* Standard libtool archive file extension.  */
187 #undef  LTDL_ARCHIVE_EXT
188 #define LTDL_ARCHIVE_EXT        ".la"
189
190 /* max. filename length */
191 #ifndef LT_FILENAME_MAX
192 #  define LT_FILENAME_MAX       1024
193 #endif
194
195 /* This is the maximum symbol size that won't require malloc/free */
196 #undef  LT_SYMBOL_LENGTH
197 #define LT_SYMBOL_LENGTH        128
198
199 /* This accounts for the _LTX_ separator */
200 #undef  LT_SYMBOL_OVERHEAD
201 #define LT_SYMBOL_OVERHEAD      5
202
203
204
205 \f
206 /* --- MEMORY HANDLING --- */
207
208
209 /* These are the functions used internally.  In addition to making
210    use of the associated function pointers above, they also perform
211    error handling.  */
212 static char   *lt_estrdup       LT_PARAMS((const char *str));
213 static lt_ptr lt_emalloc        LT_PARAMS((size_t size));
214 static lt_ptr lt_erealloc       LT_PARAMS((lt_ptr addr, size_t size));
215
216 /* static lt_ptr rpl_realloc    LT_PARAMS((lt_ptr ptr, size_t size)); */
217 #define rpl_realloc realloc
218
219 /* These are the pointers that can be changed by the caller:  */
220 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)    LT_PARAMS((size_t size))
221                         = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
222 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc)   LT_PARAMS((lt_ptr ptr, size_t size))
223                         = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
224 LT_GLOBAL_DATA void   (*lt_dlfree)      LT_PARAMS((lt_ptr ptr))
225                         = (void (*) LT_PARAMS((lt_ptr))) free;
226
227 /* The following macros reduce the amount of typing needed to cast
228    assigned memory.  */
229 #if WITH_DMALLOC
230
231 #define LT_DLMALLOC(tp, n)      ((tp *) xmalloc ((n) * sizeof(tp)))
232 #define LT_DLREALLOC(tp, p, n)  ((tp *) xrealloc ((p), (n) * sizeof(tp)))
233 #define LT_DLFREE(p)                                            \
234         LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
235
236 #define LT_EMALLOC(tp, n)       ((tp *) xmalloc ((n) * sizeof(tp)))
237 #define LT_EREALLOC(tp, p, n)   ((tp *) xrealloc ((p), (n) * sizeof(tp)))
238
239 #else
240
241 #define LT_DLMALLOC(tp, n)      ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
242 #define LT_DLREALLOC(tp, p, n)  ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
243 #define LT_DLFREE(p)                                            \
244         LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
245
246 #define LT_EMALLOC(tp, n)       ((tp *) lt_emalloc ((n) * sizeof(tp)))
247 #define LT_EREALLOC(tp, p, n)   ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
248
249 #endif
250
251 #define LT_DLMEM_REASSIGN(p, q)                 LT_STMT_START { \
252         if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; }   \
253                                                 } LT_STMT_END
254
255 \f
256 /* --- REPLACEMENT FUNCTIONS --- */
257
258
259 #undef strdup
260 #define strdup rpl_strdup
261
262 static char *strdup LT_PARAMS((const char *str));
263
264 static char *
265 strdup(str)
266      const char *str;
267 {
268   char *tmp = 0;
269
270   if (str)
271     {
272       tmp = LT_DLMALLOC (char, 1+ strlen (str));
273       if (tmp)
274         {
275           strcpy(tmp, str);
276         }
277     }
278
279   return tmp;
280 }
281
282
283 #if ! HAVE_STRCMP
284
285 #undef strcmp
286 #define strcmp rpl_strcmp
287
288 static int strcmp LT_PARAMS((const char *str1, const char *str2));
289
290 static int
291 strcmp (str1, str2)
292      const char *str1;
293      const char *str2;
294 {
295   if (str1 == str2)
296     return 0;
297   if (str1 == 0)
298     return -1;
299   if (str2 == 0)
300     return 1;
301
302   for (;*str1 && *str2; ++str1, ++str2)
303     {
304       if (*str1 != *str2)
305         break;
306     }
307
308   return (int)(*str1 - *str2);
309 }
310 #endif
311
312
313 #if ! HAVE_STRCHR
314
315 #  if HAVE_INDEX
316 #    define strchr index
317 #  else
318 #    define strchr rpl_strchr
319
320 static const char *strchr LT_PARAMS((const char *str, int ch));
321
322 static const char*
323 strchr(str, ch)
324      const char *str;
325      int ch;
326 {
327   const char *p;
328
329   for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
330     /*NOWORK*/;
331
332   return (*p == (char)ch) ? p : 0;
333 }
334
335 #  endif
336 #endif /* !HAVE_STRCHR */
337
338
339 #if ! HAVE_STRRCHR
340
341 #  if HAVE_RINDEX
342 #    define strrchr rindex
343 #  else
344 #    define strrchr rpl_strrchr
345
346 static const char *strrchr LT_PARAMS((const char *str, int ch));
347
348 static const char*
349 strrchr(str, ch)
350      const char *str;
351      int ch;
352 {
353   const char *p, *q = 0;
354
355   for (p = str; *p != LT_EOS_CHAR; ++p)
356     {
357       if (*p == (char) ch)
358         {
359           q = p;
360         }
361     }
362
363   return q;
364 }
365
366 # endif
367 #endif
368
369 /* NOTE:  Neither bcopy nor the memcpy implementation below can
370           reliably handle copying in overlapping areas of memory.  Use
371           memmove (for which there is a fallback implmentation below)
372           if you need that behaviour.  */
373 #if ! HAVE_MEMCPY
374
375 #  if HAVE_BCOPY
376 #    define memcpy(dest, src, size)     bcopy (src, dest, size)
377 #  else
378 #    define memcpy rpl_memcpy
379
380 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
381
382 static lt_ptr
383 memcpy (dest, src, size)
384      lt_ptr dest;
385      const lt_ptr src;
386      size_t size;
387 {
388   const char *  s = src;
389   char *        d = dest;
390   size_t        i = 0;
391
392   for (i = 0; i < size; ++i)
393     {
394       d[i] = s[i];
395     }
396
397   return dest;
398 }
399
400 #  endif /* !HAVE_BCOPY */
401 #endif   /* !HAVE_MEMCPY */
402
403 #if ! HAVE_MEMMOVE
404 #  define memmove rpl_memmove
405
406 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
407
408 static lt_ptr
409 memmove (dest, src, size)
410      lt_ptr dest;
411      const lt_ptr src;
412      size_t size;
413 {
414   const char *  s = src;
415   char *        d = dest;
416   size_t        i;
417
418   if (d < s)
419     for (i = 0; i < size; ++i)
420       {
421         d[i] = s[i];
422       }
423   else if (d > s && size > 0)
424     for (i = size -1; ; --i)
425       {
426         d[i] = s[i];
427         if (i == 0)
428           break;
429       }
430
431   return dest;
432 }
433
434 #endif /* !HAVE_MEMMOVE */
435
436 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
437
438 static void closedir LT_PARAMS((DIR *entry));
439
440 static void
441 closedir(entry)
442   DIR *entry;
443 {
444   assert(entry != (DIR *) NULL);
445   FindClose(entry->hSearch);
446   lt_dlfree((lt_ptr)entry);
447 }
448
449
450 static DIR * opendir LT_PARAMS((const char *path));
451
452 static DIR*
453 opendir (path)
454   const char *path;
455 {
456   char file_specification[LT_FILENAME_MAX];
457   DIR *entry;
458
459   assert(path != (char *) NULL);
460   /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
461   (void) strncpy (file_specification, path, LT_FILENAME_MAX-6);
462   file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR;
463   (void) strcat(file_specification,"\\");
464   entry = LT_DLMALLOC (DIR,sizeof(DIR));
465   if (entry != (DIR *) 0)
466     {
467       entry->firsttime = TRUE;
468       entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
469     }
470   if (entry->hSearch == INVALID_HANDLE_VALUE)
471     {
472       (void) strcat(file_specification,"\\*.*");
473       entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
474       if (entry->hSearch == INVALID_HANDLE_VALUE)
475         {
476           LT_DLFREE (entry);
477           return (DIR *) 0;
478         }
479     }
480   return(entry);
481 }
482
483
484 static struct dirent *readdir LT_PARAMS((DIR *entry));
485
486 static struct dirent *readdir(entry)
487   DIR *entry;
488 {
489   int
490     status;
491
492   if (entry == (DIR *) 0)
493     return((struct dirent *) 0);
494   if (!entry->firsttime)
495     {
496       status = FindNextFile(entry->hSearch,&entry->Win32FindData);
497       if (status == 0)
498         return((struct dirent *) 0);
499     }
500   entry->firsttime = FALSE;
501   (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
502     LT_FILENAME_MAX-1);
503   entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
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 occurrence 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
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   {
1352     /* Silence dialog from LoadLibrary on some failures.
1353        No way to get the error mode, but to set it,
1354        so set it twice to preserve any previous flags. */
1355     UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
1356     SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
1357
1358 #if defined(__CYGWIN__)
1359     {
1360       char wpath[MAX_PATH];
1361       cygwin_conv_to_full_win32_path (searchname, wpath);
1362       module = LoadLibrary (wpath);
1363     }
1364 #else
1365     module = LoadLibrary (searchname);
1366 #endif
1367
1368     /* Restore the error mode. */
1369     SetErrorMode(errormode);
1370   }
1371
1372   LT_DLFREE (searchname);
1373
1374   /* libltdl expects this function to fail if it is unable
1375      to physically load the library.  Sadly, LoadLibrary
1376      will search the loaded libraries for a match and return
1377      one of them if the path search load fails.
1378
1379      We check whether LoadLibrary is returning a handle to
1380      an already loaded module, and simulate failure if we
1381      find one. */
1382   LT_DLMUTEX_LOCK ();
1383   cur = handles;
1384   while (cur)
1385     {
1386       if (!cur->module)
1387         {
1388           cur = 0;
1389           break;
1390         }
1391
1392       if (cur->module == module)
1393         {
1394           break;
1395         }
1396
1397       cur = cur->next;
1398   }
1399   LT_DLMUTEX_UNLOCK ();
1400
1401   if (cur || !module)
1402     {
1403       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1404       module = 0;
1405     }
1406
1407   return module;
1408 }
1409
1410 static int
1411 sys_wll_close (loader_data, module)
1412      lt_user_data loader_data;
1413      lt_module module;
1414 {
1415   int         errors   = 0;
1416
1417   if (FreeLibrary(module) == 0)
1418     {
1419       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1420       ++errors;
1421     }
1422
1423   return errors;
1424 }
1425
1426 static lt_ptr
1427 sys_wll_sym (loader_data, module, symbol)
1428      lt_user_data loader_data;
1429      lt_module module;
1430      const char *symbol;
1431 {
1432   lt_ptr      address  = GetProcAddress (module, symbol);
1433
1434   if (!address)
1435     {
1436       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1437     }
1438
1439   return address;
1440 }
1441
1442 static struct lt_user_dlloader sys_wll = {
1443   0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1444 };
1445
1446 #endif /* __WINDOWS__ */
1447
1448
1449
1450 \f
1451 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1452
1453
1454 #ifdef __BEOS__
1455
1456 /* dynamic linking for BeOS */
1457
1458 #include <kernel/image.h>
1459
1460 static lt_module
1461 sys_bedl_open (loader_data, filename)
1462      lt_user_data loader_data;
1463      const char *filename;
1464 {
1465   image_id image = 0;
1466
1467   if (filename)
1468     {
1469       image = load_add_on (filename);
1470     }
1471   else
1472     {
1473       image_info info;
1474       int32 cookie = 0;
1475       if (get_next_image_info (0, &cookie, &info) == B_OK)
1476         image = load_add_on (info.name);
1477     }
1478
1479   if (image <= 0)
1480     {
1481       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1482       image = 0;
1483     }
1484
1485   return (lt_module) image;
1486 }
1487
1488 static int
1489 sys_bedl_close (loader_data, module)
1490      lt_user_data loader_data;
1491      lt_module module;
1492 {
1493   int errors = 0;
1494
1495   if (unload_add_on ((image_id) module) != B_OK)
1496     {
1497       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1498       ++errors;
1499     }
1500
1501   return errors;
1502 }
1503
1504 static lt_ptr
1505 sys_bedl_sym (loader_data, module, symbol)
1506      lt_user_data loader_data;
1507      lt_module module;
1508      const char *symbol;
1509 {
1510   lt_ptr address = 0;
1511   image_id image = (image_id) module;
1512
1513   if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1514     {
1515       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1516       address = 0;
1517     }
1518
1519   return address;
1520 }
1521
1522 static struct lt_user_dlloader sys_bedl = {
1523   0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1524 };
1525
1526 #endif /* __BEOS__ */
1527
1528
1529
1530 \f
1531 /* --- DLD_LINK() INTERFACE LOADER --- */
1532
1533
1534 #if HAVE_DLD
1535
1536 /* dynamic linking with dld */
1537
1538 #if HAVE_DLD_H
1539 #include <dld.h>
1540 #endif
1541
1542 static lt_module
1543 sys_dld_open (loader_data, filename)
1544      lt_user_data loader_data;
1545      const char *filename;
1546 {
1547   lt_module module = strdup (filename);
1548
1549   if (dld_link (filename) != 0)
1550     {
1551       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1552       LT_DLFREE (module);
1553       module = 0;
1554     }
1555
1556   return module;
1557 }
1558
1559 static int
1560 sys_dld_close (loader_data, module)
1561      lt_user_data loader_data;
1562      lt_module module;
1563 {
1564   int errors = 0;
1565
1566   if (dld_unlink_by_file ((char*)(module), 1) != 0)
1567     {
1568       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1569       ++errors;
1570     }
1571   else
1572     {
1573       LT_DLFREE (module);
1574     }
1575
1576   return errors;
1577 }
1578
1579 static lt_ptr
1580 sys_dld_sym (loader_data, module, symbol)
1581      lt_user_data loader_data;
1582      lt_module module;
1583      const char *symbol;
1584 {
1585   lt_ptr address = dld_get_func (symbol);
1586
1587   if (!address)
1588     {
1589       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1590     }
1591
1592   return address;
1593 }
1594
1595 static struct lt_user_dlloader sys_dld = {
1596   0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1597 };
1598
1599 #endif /* HAVE_DLD */
1600
1601 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
1602 #if HAVE_DYLD
1603
1604
1605 #if HAVE_MACH_O_DYLD_H
1606 #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
1607 /* Is this correct? Does it still function properly? */
1608 #define __private_extern__ extern
1609 #endif
1610 # include <mach-o/dyld.h>
1611 #endif
1612 #include <mach-o/getsect.h>
1613
1614 /* We have to put some stuff here that isn't in older dyld.h files */
1615 #ifndef ENUM_DYLD_BOOL
1616 # define ENUM_DYLD_BOOL
1617 # undef FALSE
1618 # undef TRUE
1619  enum DYLD_BOOL {
1620     FALSE,
1621     TRUE
1622  };
1623 #endif
1624 #ifndef LC_REQ_DYLD
1625 # define LC_REQ_DYLD 0x80000000
1626 #endif
1627 #ifndef LC_LOAD_WEAK_DYLIB
1628 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1629 #endif
1630 static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
1631 static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
1632 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
1633 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
1634
1635 #ifndef NSADDIMAGE_OPTION_NONE
1636 #define NSADDIMAGE_OPTION_NONE                          0x0
1637 #endif
1638 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1639 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR               0x1
1640 #endif
1641 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
1642 #define NSADDIMAGE_OPTION_WITH_SEARCHING                0x2
1643 #endif
1644 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1645 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED         0x4
1646 #endif
1647 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1648 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
1649 #endif
1650 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1651 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND            0x0
1652 #endif
1653 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1654 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW        0x1
1655 #endif
1656 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1657 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY      0x2
1658 #endif
1659 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1660 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1661 #endif
1662
1663
1664 static const char *
1665 lt_int_dyld_error(othererror)
1666         char* othererror;
1667 {
1668 /* return the dyld error string, or the passed in error string if none */
1669         NSLinkEditErrors ler;
1670         int lerno;
1671         const char *errstr;
1672         const char *file;
1673         NSLinkEditError(&ler,&lerno,&file,&errstr);
1674         if (!errstr || !strlen(errstr)) errstr = othererror;
1675         return errstr;
1676 }
1677
1678 static const struct mach_header *
1679 lt_int_dyld_get_mach_header_from_nsmodule(module)
1680         NSModule module;
1681 {
1682 /* There should probably be an apple dyld api for this */
1683         int i=_dyld_image_count();
1684         int j;
1685         const char *modname=NSNameOfModule(module);
1686         const struct mach_header *mh=NULL;
1687         if (!modname) return NULL;
1688         for (j = 0; j < i; j++)
1689         {
1690                 if (!strcmp(_dyld_get_image_name(j),modname))
1691                 {
1692                         mh=_dyld_get_image_header(j);
1693                         break;
1694                 }
1695         }
1696         return mh;
1697 }
1698
1699 static const char* lt_int_dyld_lib_install_name(mh)
1700         const struct mach_header *mh;
1701 {
1702 /* NSAddImage is also used to get the loaded image, but it only works if the lib
1703    is installed, for uninstalled libs we need to check the install_names against
1704    each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
1705    different lib was loaded as a result
1706 */
1707         int j;
1708         struct load_command *lc;
1709         unsigned long offset = sizeof(struct mach_header);
1710         const char* retStr=NULL;
1711         for (j = 0; j < mh->ncmds; j++)
1712         {
1713                 lc = (struct load_command*)(((unsigned long)mh) + offset);
1714                 if (LC_ID_DYLIB == lc->cmd)
1715                 {
1716                         retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
1717                                                                         (unsigned long)lc);
1718                 }
1719                 offset += lc->cmdsize;
1720         }
1721         return retStr;
1722 }
1723
1724 static const struct mach_header *
1725 lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
1726 {
1727         int i=_dyld_image_count();
1728         int j;
1729         const struct mach_header *mh=NULL;
1730         const char *id=NULL;
1731         for (j = 0; j < i; j++)
1732         {
1733                 id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
1734                 if ((id) && (!strcmp(id,name)))
1735                 {
1736                         mh=_dyld_get_image_header(j);
1737                         break;
1738                 }
1739         }
1740         return mh;
1741 }
1742
1743 static NSSymbol
1744 lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
1745         const char *symbol;
1746         const struct mach_header *mh;
1747 {
1748         /* Safe to assume our mh is good */
1749         int j;
1750         struct load_command *lc;
1751         unsigned long offset = sizeof(struct mach_header);
1752         NSSymbol retSym = 0;
1753         const struct mach_header *mh1;
1754         if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
1755         {
1756                 for (j = 0; j < mh->ncmds; j++)
1757                 {
1758                         lc = (struct load_command*)(((unsigned long)mh) + offset);
1759                         if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
1760                         {
1761                                 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1762                                                                                 (unsigned long)lc));
1763                                 if (!mh1)
1764                                 {
1765                                         /* Maybe NSAddImage can find it */
1766                                         mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1767                                                                                 (unsigned long)lc),
1768                                                                                 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
1769                                                                                 NSADDIMAGE_OPTION_WITH_SEARCHING +
1770                                                                                 NSADDIMAGE_OPTION_RETURN_ON_ERROR );
1771                                 }
1772                                 if (mh1)
1773                                 {
1774                                         retSym = ltdl_NSLookupSymbolInImage(mh1,
1775                                                                                         symbol,
1776                                                                                         NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1777                                                                                         | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1778                                                                                         );
1779                                         if (retSym) break;
1780                                 }
1781                         }
1782                         offset += lc->cmdsize;
1783                 }
1784         }
1785         return retSym;
1786 }
1787
1788 static int
1789 sys_dyld_init()
1790 {
1791         int retCode = 0;
1792         int err = 0;
1793         if (!_dyld_present()) {
1794                 retCode=1;
1795         }
1796         else {
1797       err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
1798       err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
1799       err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
1800       err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
1801     }
1802  return retCode;
1803 }
1804
1805 static lt_module
1806 sys_dyld_open (loader_data, filename)
1807      lt_user_data loader_data;
1808      const char *filename;
1809 {
1810         lt_module   module   = 0;
1811         NSObjectFileImage ofi = 0;
1812         NSObjectFileImageReturnCode ofirc;
1813
1814         if (!filename)
1815                 return (lt_module)-1;
1816         ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
1817         switch (ofirc)
1818         {
1819                 case NSObjectFileImageSuccess:
1820                         module = NSLinkModule(ofi, filename,
1821                                                 NSLINKMODULE_OPTION_RETURN_ON_ERROR
1822                                                  | NSLINKMODULE_OPTION_PRIVATE
1823                                                  | NSLINKMODULE_OPTION_BINDNOW);
1824                         NSDestroyObjectFileImage(ofi);
1825                         if (module)
1826                                 ltdl_NSMakePrivateModulePublic(module);
1827                         break;
1828                 case NSObjectFileImageInappropriateFile:
1829                     if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1830                     {
1831                                 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
1832                                 break;
1833                         }
1834                 default:
1835                         LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1836                         return 0;
1837         }
1838         if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1839   return module;
1840 }
1841
1842 static int
1843 sys_dyld_close (loader_data, module)
1844      lt_user_data loader_data;
1845      lt_module module;
1846 {
1847         int retCode = 0;
1848         int flags = 0;
1849         if (module == (lt_module)-1) return 0;
1850 #ifdef __BIG_ENDIAN__
1851         if (((struct mach_header *)module)->magic == MH_MAGIC)
1852 #else
1853     if (((struct mach_header *)module)->magic == MH_CIGAM)
1854 #endif
1855         {
1856           LT_DLMUTEX_SETERROR("Can not close a dylib");
1857           retCode = 1;
1858         }
1859         else
1860         {
1861 #if 1
1862 /* Currently, if a module contains c++ static destructors and it is unloaded, we
1863    get a segfault in atexit(), due to compiler and dynamic loader differences of
1864    opinion, this works around that.
1865 */
1866                 if ((const struct section *)NULL !=
1867                    getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
1868                    "__DATA","__mod_term_func"))
1869                 {
1870                         flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1871                 }
1872 #endif
1873 #ifdef __ppc__
1874                         flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
1875 #endif
1876                 if (!NSUnLinkModule(module,flags))
1877                 {
1878                         retCode=1;
1879                         LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
1880                 }
1881         }
1882
1883  return retCode;
1884 }
1885
1886 static lt_ptr
1887 sys_dyld_sym (loader_data, module, symbol)
1888      lt_user_data loader_data;
1889      lt_module module;
1890      const char *symbol;
1891 {
1892         lt_ptr address = 0;
1893         NSSymbol *nssym = 0;
1894         void *unused;
1895         const struct mach_header *mh=NULL;
1896         char saveError[256] = "Symbol not found";
1897         if (module == (lt_module)-1)
1898         {
1899                 _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
1900                 return address;
1901         }
1902 #ifdef __BIG_ENDIAN__
1903         if (((struct mach_header *)module)->magic == MH_MAGIC)
1904 #else
1905     if (((struct mach_header *)module)->magic == MH_CIGAM)
1906 #endif
1907         {
1908             if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1909             {
1910                 mh=module;
1911                         if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
1912                         {
1913                                 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
1914                                                                                         symbol,
1915                                                                                         NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1916                                                                                         | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1917                                                                                         );
1918                         }
1919             }
1920
1921         }
1922   else {
1923         nssym = NSLookupSymbolInModule(module, symbol);
1924         }
1925         if (!nssym)
1926         {
1927                 strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
1928                 saveError[255] = 0;
1929                 if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
1930                 nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
1931         }
1932         if (!nssym)
1933         {
1934                 LT_DLMUTEX_SETERROR (saveError);
1935                 return NULL;
1936         }
1937         return NSAddressOfSymbol(nssym);
1938 }
1939
1940 static struct lt_user_dlloader sys_dyld =
1941   { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
1942
1943
1944 #endif /* HAVE_DYLD */
1945
1946 \f
1947 /* --- DLPREOPEN() INTERFACE LOADER --- */
1948
1949
1950 /* emulate dynamic linking using preloaded_symbols */
1951
1952 typedef struct lt_dlsymlists_t
1953 {
1954   struct lt_dlsymlists_t       *next;
1955   const lt_dlsymlist           *syms;
1956 } lt_dlsymlists_t;
1957
1958 static  const lt_dlsymlist     *default_preloaded_symbols       = 0;
1959 static  lt_dlsymlists_t        *preloaded_symbols               = 0;
1960
1961 static int
1962 presym_init (loader_data)
1963      lt_user_data loader_data;
1964 {
1965   int errors = 0;
1966
1967   LT_DLMUTEX_LOCK ();
1968
1969   preloaded_symbols = 0;
1970   if (default_preloaded_symbols)
1971     {
1972       errors = lt_dlpreload (default_preloaded_symbols);
1973     }
1974
1975   LT_DLMUTEX_UNLOCK ();
1976
1977   return errors;
1978 }
1979
1980 static int
1981 presym_free_symlists ()
1982 {
1983   lt_dlsymlists_t *lists;
1984
1985   LT_DLMUTEX_LOCK ();
1986
1987   lists = preloaded_symbols;
1988   while (lists)
1989     {
1990       lt_dlsymlists_t   *tmp = lists;
1991
1992       lists = lists->next;
1993       LT_DLFREE (tmp);
1994     }
1995   preloaded_symbols = 0;
1996
1997   LT_DLMUTEX_UNLOCK ();
1998
1999   return 0;
2000 }
2001
2002 static int
2003 presym_exit (loader_data)
2004      lt_user_data loader_data;
2005 {
2006   presym_free_symlists ();
2007   return 0;
2008 }
2009
2010 static int
2011 presym_add_symlist (preloaded)
2012      const lt_dlsymlist *preloaded;
2013 {
2014   lt_dlsymlists_t *tmp;
2015   lt_dlsymlists_t *lists;
2016   int              errors   = 0;
2017
2018   LT_DLMUTEX_LOCK ();
2019
2020   lists = preloaded_symbols;
2021   while (lists)
2022     {
2023       if (lists->syms == preloaded)
2024         {
2025           goto done;
2026         }
2027       lists = lists->next;
2028     }
2029
2030   tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
2031   if (tmp)
2032     {
2033       memset (tmp, 0, sizeof(lt_dlsymlists_t));
2034       tmp->syms = preloaded;
2035       tmp->next = preloaded_symbols;
2036       preloaded_symbols = tmp;
2037     }
2038   else
2039     {
2040       ++errors;
2041     }
2042
2043  done:
2044   LT_DLMUTEX_UNLOCK ();
2045   return errors;
2046 }
2047
2048 static lt_module
2049 presym_open (loader_data, filename)
2050      lt_user_data loader_data;
2051      const char *filename;
2052 {
2053   lt_dlsymlists_t *lists;
2054   lt_module        module = (lt_module) 0;
2055
2056   LT_DLMUTEX_LOCK ();
2057   lists = preloaded_symbols;
2058
2059   if (!lists)
2060     {
2061       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
2062       goto done;
2063     }
2064
2065   /* Can't use NULL as the reflective symbol header, as NULL is
2066      used to mark the end of the entire symbol list.  Self-dlpreopened
2067      symbols follow this magic number, chosen to be an unlikely
2068      clash with a real module name.  */
2069   if (!filename)
2070     {
2071       filename = "@PROGRAM@";
2072     }
2073
2074   while (lists)
2075     {
2076       const lt_dlsymlist *syms = lists->syms;
2077
2078       while (syms->name)
2079         {
2080           if (!syms->address && strcmp(syms->name, filename) == 0)
2081             {
2082               module = (lt_module) syms;
2083               goto done;
2084             }
2085           ++syms;
2086         }
2087
2088       lists = lists->next;
2089     }
2090
2091   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2092
2093  done:
2094   LT_DLMUTEX_UNLOCK ();
2095   return module;
2096 }
2097
2098 static int
2099 presym_close (loader_data, module)
2100      lt_user_data loader_data;
2101      lt_module module;
2102 {
2103   /* Just to silence gcc -Wall */
2104   module = 0;
2105   return 0;
2106 }
2107
2108 static lt_ptr
2109 presym_sym (loader_data, module, symbol)
2110      lt_user_data loader_data;
2111      lt_module module;
2112      const char *symbol;
2113 {
2114   lt_dlsymlist *syms = (lt_dlsymlist*) module;
2115
2116   ++syms;
2117   while (syms->address)
2118     {
2119       if (strcmp(syms->name, symbol) == 0)
2120         {
2121           return syms->address;
2122         }
2123
2124     ++syms;
2125   }
2126
2127   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
2128
2129   return 0;
2130 }
2131
2132 static struct lt_user_dlloader presym = {
2133   0, presym_open, presym_close, presym_sym, presym_exit, 0
2134 };
2135
2136
2137
2138
2139 \f
2140 /* --- DYNAMIC MODULE LOADING --- */
2141
2142
2143 /* The type of a function used at each iteration of  foreach_dirinpath().  */
2144 typedef int     foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
2145                                                  lt_ptr data2));
2146
2147 static  int     foreach_dirinpath     LT_PARAMS((const char *search_path,
2148                                                  const char *base_name,
2149                                                  foreach_callback_func *func,
2150                                                  lt_ptr data1, lt_ptr data2));
2151
2152 static  int     find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
2153                                                  lt_ptr ignored));
2154 static  int     find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
2155                                                  lt_ptr ignored));
2156 static  int     foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
2157                                                  lt_ptr data2));
2158
2159
2160 static  int     canonicalize_path     LT_PARAMS((const char *path,
2161                                                  char **pcanonical));
2162 static  int     argzize_path          LT_PARAMS((const char *path,
2163                                                  char **pargz,
2164                                                  size_t *pargz_len));
2165 static  FILE   *find_file             LT_PARAMS((const char *search_path,
2166                                                  const char *base_name,
2167                                                  char **pdir));
2168 static  lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
2169                                                  const char *base_name,
2170                                                  lt_dlhandle *handle));
2171 static  int     find_module           LT_PARAMS((lt_dlhandle *handle,
2172                                                  const char *dir,
2173                                                  const char *libdir,
2174                                                  const char *dlname,
2175                                                  const char *old_name,
2176                                                  int installed));
2177 static  int     free_vars             LT_PARAMS((char *dlname, char *oldname,
2178                                                  char *libdir, char *deplibs));
2179 static  int     load_deplibs          LT_PARAMS((lt_dlhandle handle,
2180                                                  char *deplibs));
2181 static  int     trim                  LT_PARAMS((char **dest,
2182                                                  const char *str));
2183 static  int     try_dlopen            LT_PARAMS((lt_dlhandle *handle,
2184                                                  const char *filename));
2185 static  int     tryall_dlopen         LT_PARAMS((lt_dlhandle *handle,
2186                                                  const char *filename,
2187                                                  const char * useloader));
2188 static  int     unload_deplibs        LT_PARAMS((lt_dlhandle handle));
2189 static  int     lt_argz_insert        LT_PARAMS((char **pargz,
2190                                                  size_t *pargz_len,
2191                                                  char *before,
2192                                                  const char *entry));
2193 static  int     lt_argz_insertinorder LT_PARAMS((char **pargz,
2194                                                  size_t *pargz_len,
2195                                                  const char *entry));
2196 static  int     lt_argz_insertdir     LT_PARAMS((char **pargz,
2197                                                  size_t *pargz_len,
2198                                                  const char *dirnam,
2199                                                  struct dirent *dp));
2200 static  int     lt_dlpath_insertdir   LT_PARAMS((char **ppath,
2201                                                  char *before,
2202                                                  const char *dir));
2203 static  int     list_files_by_dir     LT_PARAMS((const char *dirnam,
2204                                                  char **pargz,
2205                                                  size_t *pargz_len));
2206 static  int     file_not_found        LT_PARAMS((void));
2207
2208 static  char           *user_search_path= 0;
2209 static  lt_dlloader    *loaders         = 0;
2210 static  lt_dlhandle     handles         = 0;
2211 static  int             initialized     = 0;
2212
2213 /* Initialize libltdl. */
2214 int
2215 lt_dlinit ()
2216 {
2217   int         errors   = 0;
2218
2219   LT_DLMUTEX_LOCK ();
2220
2221   /* Initialize only at first call. */
2222   if (++initialized == 1)
2223     {
2224       handles = 0;
2225       user_search_path = 0; /* empty search path */
2226
2227 #if HAVE_LIBDL
2228       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
2229 #endif
2230 #if HAVE_SHL_LOAD
2231       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
2232 #endif
2233 #ifdef __WINDOWS__
2234       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
2235 #endif
2236 #ifdef __BEOS__
2237       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
2238 #endif
2239 #if HAVE_DLD
2240       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
2241 #endif
2242 #if HAVE_DYLD
2243        errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
2244        errors += sys_dyld_init();
2245 #endif
2246       errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
2247
2248       if (presym_init (presym.dlloader_data))
2249         {
2250           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
2251           ++errors;
2252         }
2253       else if (errors != 0)
2254         {
2255           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
2256           ++errors;
2257         }
2258     }
2259
2260   LT_DLMUTEX_UNLOCK ();
2261
2262   return errors;
2263 }
2264
2265 int
2266 lt_dlpreload (preloaded)
2267      const lt_dlsymlist *preloaded;
2268 {
2269   int errors = 0;
2270
2271   if (preloaded)
2272     {
2273       errors = presym_add_symlist (preloaded);
2274     }
2275   else
2276     {
2277       presym_free_symlists();
2278
2279       LT_DLMUTEX_LOCK ();
2280       if (default_preloaded_symbols)
2281         {
2282           errors = lt_dlpreload (default_preloaded_symbols);
2283         }
2284       LT_DLMUTEX_UNLOCK ();
2285     }
2286
2287   return errors;
2288 }
2289
2290 int
2291 lt_dlpreload_default (preloaded)
2292      const lt_dlsymlist *preloaded;
2293 {
2294   LT_DLMUTEX_LOCK ();
2295   default_preloaded_symbols = preloaded;
2296   LT_DLMUTEX_UNLOCK ();
2297   return 0;
2298 }
2299
2300 int
2301 lt_dlexit ()
2302 {
2303   /* shut down libltdl */
2304   lt_dlloader *loader;
2305   int          errors   = 0;
2306
2307   LT_DLMUTEX_LOCK ();
2308   loader = loaders;
2309
2310   if (!initialized)
2311     {
2312       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
2313       ++errors;
2314       goto done;
2315     }
2316
2317   /* shut down only at last call. */
2318   if (--initialized == 0)
2319     {
2320       int       level;
2321
2322       while (handles && LT_DLIS_RESIDENT (handles))
2323         {
2324           handles = handles->next;
2325         }
2326
2327       /* close all modules */
2328       for (level = 1; handles; ++level)
2329         {
2330           lt_dlhandle cur = handles;
2331           int saw_nonresident = 0;
2332
2333           while (cur)
2334             {
2335               lt_dlhandle tmp = cur;
2336               cur = cur->next;
2337               if (!LT_DLIS_RESIDENT (tmp))
2338                 saw_nonresident = 1;
2339               if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
2340                 {
2341                   if (lt_dlclose (tmp))
2342                     {
2343                       ++errors;
2344                     }
2345                 }
2346             }
2347           /* done if only resident modules are left */
2348           if (!saw_nonresident)
2349             break;
2350         }
2351
2352       /* close all loaders */
2353       while (loader)
2354         {
2355           lt_dlloader *next = loader->next;
2356           lt_user_data data = loader->dlloader_data;
2357           if (loader->dlloader_exit && loader->dlloader_exit (data))
2358             {
2359               ++errors;
2360             }
2361
2362           LT_DLMEM_REASSIGN (loader, next);
2363         }
2364       loaders = 0;
2365
2366       LT_DLFREE (user_search_path);
2367     }
2368
2369  done:
2370   LT_DLMUTEX_UNLOCK ();
2371   return errors;
2372 }
2373
2374 static int
2375 tryall_dlopen (handle, filename, useloader)
2376      lt_dlhandle *handle;
2377      const char *filename;
2378      const char *useloader;
2379 {
2380   lt_dlhandle    cur;
2381   lt_dlloader   *loader;
2382   const char    *saved_error;
2383   int            errors         = 0;
2384
2385   LT_DLMUTEX_GETERROR (saved_error);
2386   LT_DLMUTEX_LOCK ();
2387
2388   cur    = handles;
2389   loader = loaders;
2390
2391   /* check whether the module was already opened */
2392   while (cur)
2393     {
2394       /* try to dlopen the program itself? */
2395       if (!cur->info.filename && !filename)
2396         {
2397           break;
2398         }
2399
2400       if (cur->info.filename && filename
2401           && strcmp (cur->info.filename, filename) == 0)
2402         {
2403           break;
2404         }
2405
2406       cur = cur->next;
2407     }
2408
2409   if (cur)
2410     {
2411       ++cur->info.ref_count;
2412       *handle = cur;
2413       goto done;
2414     }
2415
2416   cur = *handle;
2417   if (filename)
2418     {
2419       /* Comment out the check of file permissions using access.
2420          This call seems to always return -1 with error EACCES.
2421       */
2422       /* We need to catch missing file errors early so that
2423          file_not_found() can detect what happened.
2424       if (access (filename, R_OK) != 0)
2425         {
2426           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2427           ++errors;
2428           goto done;
2429         } */
2430
2431       cur->info.filename = lt_estrdup (filename);
2432       if (!cur->info.filename)
2433         {
2434           ++errors;
2435           goto done;
2436         }
2437     }
2438   else
2439     {
2440       cur->info.filename = 0;
2441     }
2442
2443   while (loader)
2444     {
2445       if (useloader && strcmp(loader->loader_name, useloader))
2446         {
2447           loader = loader->next;
2448           continue;
2449         }
2450       lt_user_data data = loader->dlloader_data;
2451
2452       cur->module = loader->module_open (data, filename);
2453
2454       if (cur->module != 0)
2455         {
2456           break;
2457         }
2458       loader = loader->next;
2459     }
2460
2461   if (!loader)
2462     {
2463       LT_DLFREE (cur->info.filename);
2464       ++errors;
2465       goto done;
2466     }
2467
2468   cur->loader   = loader;
2469   LT_DLMUTEX_SETERROR (saved_error);
2470
2471  done:
2472   LT_DLMUTEX_UNLOCK ();
2473
2474   return errors;
2475 }
2476
2477 static int
2478 tryall_dlopen_module (handle, prefix, dirname, dlname)
2479      lt_dlhandle *handle;
2480      const char *prefix;
2481      const char *dirname;
2482      const char *dlname;
2483 {
2484   int      error        = 0;
2485   char     *filename    = 0;
2486   size_t   filename_len = 0;
2487   size_t   dirname_len  = LT_STRLEN (dirname);
2488
2489   assert (handle);
2490   assert (dirname);
2491   assert (dlname);
2492 #ifdef LT_DIRSEP_CHAR
2493   /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2494      should make it into this function:  */
2495   assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
2496 #endif
2497
2498   if (dirname_len > 0)
2499     if (dirname[dirname_len -1] == '/')
2500       --dirname_len;
2501   filename_len = dirname_len + 1 + LT_STRLEN (dlname);
2502
2503   /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2504      The PREFIX (if any) is handled below.  */
2505   filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
2506   if (!filename)
2507     return 1;
2508
2509   sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
2510
2511   /* Now that we have combined DIRNAME and MODULENAME, if there is
2512      also a PREFIX to contend with, simply recurse with the arguments
2513      shuffled.  Otherwise, attempt to open FILENAME as a module.  */
2514   if (prefix)
2515     {
2516       error += tryall_dlopen_module (handle,
2517                                      (const char *) 0, prefix, filename);
2518     }
2519   else if (tryall_dlopen (handle, filename, NULL) != 0)
2520     {
2521       ++error;
2522     }
2523
2524   LT_DLFREE (filename);
2525   return error;
2526 }
2527
2528 static int
2529 find_module (handle, dir, libdir, dlname, old_name, installed)
2530      lt_dlhandle *handle;
2531      const char *dir;
2532      const char *libdir;
2533      const char *dlname;
2534      const char *old_name;
2535      int installed;
2536 {
2537   /* Try to open the old library first; if it was dlpreopened,
2538      we want the preopened version of it, even if a dlopenable
2539      module is available.  */
2540   if (old_name && tryall_dlopen (handle, old_name, "dlpreload") == 0)
2541     {
2542       return 0;
2543     }
2544
2545   /* Try to open the dynamic library.  */
2546   if (dlname)
2547     {
2548       /* try to open the installed module */
2549       if (installed && libdir)
2550         {
2551           if (tryall_dlopen_module (handle,
2552                                     (const char *) 0, libdir, dlname) == 0)
2553             return 0;
2554         }
2555
2556       /* try to open the not-installed module */
2557       if (!installed)
2558         {
2559           if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2560             return 0;
2561         }
2562
2563       /* maybe it was moved to another directory */
2564       {
2565           if (dir && (tryall_dlopen_module (handle,
2566                                     (const char *) 0, dir, dlname) == 0))
2567             return 0;
2568       }
2569     }
2570
2571   return 1;
2572 }
2573
2574
2575 static int
2576 canonicalize_path (path, pcanonical)
2577      const char *path;
2578      char **pcanonical;
2579 {
2580   char *canonical = 0;
2581
2582   assert (path && *path);
2583   assert (pcanonical);
2584
2585   canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2586   if (!canonical)
2587     return 1;
2588
2589   {
2590     size_t dest = 0;
2591     size_t src;
2592     for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2593       {
2594         /* Path separators are not copied to the beginning or end of
2595            the destination, or if another separator would follow
2596            immediately.  */
2597         if (path[src] == LT_PATHSEP_CHAR)
2598           {
2599             if ((dest == 0)
2600                 || (path[1+ src] == LT_PATHSEP_CHAR)
2601                 || (path[1+ src] == LT_EOS_CHAR))
2602               continue;
2603           }
2604
2605         /* Anything other than a directory separator is copied verbatim.  */
2606         if ((path[src] != '/')
2607 #ifdef LT_DIRSEP_CHAR
2608             && (path[src] != LT_DIRSEP_CHAR)
2609 #endif
2610             )
2611           {
2612             canonical[dest++] = path[src];
2613           }
2614         /* Directory separators are converted and copied only if they are
2615            not at the end of a path -- i.e. before a path separator or
2616            NULL terminator.  */
2617         else if ((path[1+ src] != LT_PATHSEP_CHAR)
2618                  && (path[1+ src] != LT_EOS_CHAR)
2619 #ifdef LT_DIRSEP_CHAR
2620                  && (path[1+ src] != LT_DIRSEP_CHAR)
2621 #endif
2622                  && (path[1+ src] != '/'))
2623           {
2624             canonical[dest++] = '/';
2625           }
2626       }
2627
2628     /* Add an end-of-string marker at the end.  */
2629     canonical[dest] = LT_EOS_CHAR;
2630   }
2631
2632   /* Assign new value.  */
2633   *pcanonical = canonical;
2634
2635   return 0;
2636 }
2637
2638 static int
2639 argzize_path (path, pargz, pargz_len)
2640      const char *path;
2641      char **pargz;
2642      size_t *pargz_len;
2643 {
2644   error_t error;
2645
2646   assert (path);
2647   assert (pargz);
2648   assert (pargz_len);
2649
2650   if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2651     {
2652       switch (error)
2653         {
2654         case ENOMEM:
2655           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2656           break;
2657         default:
2658           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2659           break;
2660         }
2661
2662       return 1;
2663     }
2664
2665   return 0;
2666 }
2667
2668 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2669    of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2670    non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
2671    it is appended to each SEARCH_PATH element before FUNC is called.  */
2672 static int
2673 foreach_dirinpath (search_path, base_name, func, data1, data2)
2674      const char *search_path;
2675      const char *base_name;
2676      foreach_callback_func *func;
2677      lt_ptr data1;
2678      lt_ptr data2;
2679 {
2680   int    result         = 0;
2681   int    filenamesize   = 0;
2682   size_t lenbase        = LT_STRLEN (base_name);
2683   size_t argz_len       = 0;
2684   char *argz            = 0;
2685   char *filename        = 0;
2686   char *canonical       = 0;
2687
2688   LT_DLMUTEX_LOCK ();
2689
2690   if (!search_path || !*search_path)
2691     {
2692       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2693       goto cleanup;
2694     }
2695
2696   if (canonicalize_path (search_path, &canonical) != 0)
2697     goto cleanup;
2698
2699   if (argzize_path (canonical, &argz, &argz_len) != 0)
2700     goto cleanup;
2701
2702   {
2703     char *dir_name = 0;
2704     while ((dir_name = argz_next (argz, argz_len, dir_name)))
2705       {
2706         size_t lendir = LT_STRLEN (dir_name);
2707
2708         if (lendir +1 +lenbase >= filenamesize)
2709         {
2710           LT_DLFREE (filename);
2711           filenamesize  = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2712           filename      = LT_EMALLOC (char, filenamesize);
2713           if (!filename)
2714             goto cleanup;
2715         }
2716
2717         assert (filenamesize > lendir);
2718         strcpy (filename, dir_name);
2719
2720         if (base_name && *base_name)
2721           {
2722             if (filename[lendir -1] != '/')
2723               filename[lendir++] = '/';
2724             strcpy (filename +lendir, base_name);
2725           }
2726
2727         if ((result = (*func) (filename, data1, data2)))
2728           {
2729             break;
2730           }
2731       }
2732   }
2733
2734  cleanup:
2735   LT_DLFREE (argz);
2736   LT_DLFREE (canonical);
2737   LT_DLFREE (filename);
2738
2739   LT_DLMUTEX_UNLOCK ();
2740
2741   return result;
2742 }
2743
2744 /* If FILEPATH can be opened, store the name of the directory component
2745    in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
2746    DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
2747 static int
2748 find_file_callback (filename, data1, data2)
2749      char *filename;
2750      lt_ptr data1;
2751      lt_ptr data2;
2752 {
2753   char       **pdir     = (char **) data1;
2754   FILE       **pfile    = (FILE **) data2;
2755   int        is_done    = 0;
2756
2757   assert (filename && *filename);
2758   assert (pdir);
2759   assert (pfile);
2760
2761   if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2762     {
2763       char *dirend = strrchr (filename, '/');
2764
2765       if (dirend > filename)
2766         *dirend   = LT_EOS_CHAR;
2767
2768       LT_DLFREE (*pdir);
2769       *pdir   = lt_estrdup (filename);
2770       is_done = (*pdir == 0) ? -1 : 1;
2771     }
2772
2773   return is_done;
2774 }
2775
2776 static FILE *
2777 find_file (search_path, base_name, pdir)
2778      const char *search_path;
2779      const char *base_name;
2780      char **pdir;
2781 {
2782   FILE *file = 0;
2783
2784   foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2785
2786   return file;
2787 }
2788
2789 static int
2790 find_handle_callback (filename, data, ignored)
2791      char *filename;
2792      lt_ptr data;
2793      lt_ptr ignored;
2794 {
2795   lt_dlhandle  *handle          = (lt_dlhandle *) data;
2796   int           notfound        = access (filename, R_OK);
2797
2798   /* Bail out if file cannot be read...  */
2799   if (notfound)
2800     return 0;
2801
2802   /* Try to dlopen the file, but do not continue searching in any
2803      case.  */
2804   if (tryall_dlopen (handle, filename,NULL) != 0)
2805     *handle = 0;
2806
2807   return 1;
2808 }
2809
2810 /* If HANDLE was found return it, otherwise return 0.  If HANDLE was
2811    found but could not be opened, *HANDLE will be set to 0.  */
2812 static lt_dlhandle *
2813 find_handle (search_path, base_name, handle)
2814      const char *search_path;
2815      const char *base_name;
2816      lt_dlhandle *handle;
2817 {
2818   if (!search_path)
2819     return 0;
2820
2821   if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2822                           handle, 0))
2823     return 0;
2824
2825   return handle;
2826 }
2827
2828 static int
2829 load_deplibs (handle, deplibs)
2830      lt_dlhandle handle;
2831      char *deplibs;
2832 {
2833 #if LTDL_DLOPEN_DEPLIBS
2834   char  *p, *save_search_path = 0;
2835   int   depcount = 0;
2836   int   i;
2837   char  **names = 0;
2838 #endif
2839   int   errors = 0;
2840
2841   handle->depcount = 0;
2842
2843 #if LTDL_DLOPEN_DEPLIBS
2844   if (!deplibs)
2845     {
2846       return errors;
2847     }
2848   ++errors;
2849
2850   LT_DLMUTEX_LOCK ();
2851   if (user_search_path)
2852     {
2853       save_search_path = lt_estrdup (user_search_path);
2854       if (!save_search_path)
2855         goto cleanup;
2856     }
2857
2858   /* extract search paths and count deplibs */
2859   p = deplibs;
2860   while (*p)
2861     {
2862       if (!isspace ((int) *p))
2863         {
2864           char *end = p+1;
2865           while (*end && !isspace((int) *end))
2866             {
2867               ++end;
2868             }
2869
2870           if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2871             {
2872               char save = *end;
2873               *end = 0; /* set a temporary string terminator */
2874               if (lt_dladdsearchdir(p+2))
2875                 {
2876                   goto cleanup;
2877                 }
2878               *end = save;
2879             }
2880           else
2881             {
2882               ++depcount;
2883             }
2884
2885           p = end;
2886         }
2887       else
2888         {
2889           ++p;
2890         }
2891     }
2892
2893   if (!depcount)
2894     {
2895       errors = 0;
2896       goto cleanup;
2897     }
2898
2899   names = LT_EMALLOC (char *, depcount * sizeof (char*));
2900   if (!names)
2901     goto cleanup;
2902
2903   /* now only extract the actual deplibs */
2904   depcount = 0;
2905   p = deplibs;
2906   while (*p)
2907     {
2908       if (isspace ((int) *p))
2909         {
2910           ++p;
2911         }
2912       else
2913         {
2914           char *end = p+1;
2915           while (*end && !isspace ((int) *end))
2916             {
2917               ++end;
2918             }
2919
2920           if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2921             {
2922               char *name;
2923               char save = *end;
2924               *end = 0; /* set a temporary string terminator */
2925               if (strncmp(p, "-l", 2) == 0)
2926                 {
2927                   size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2928                   name = LT_EMALLOC (char, 1+ name_len);
2929                   if (name)
2930                     sprintf (name, "lib%s", p+2);
2931                 }
2932               else
2933                 name = lt_estrdup(p);
2934
2935               if (!name)
2936                 goto cleanup_names;
2937
2938               names[depcount++] = name;
2939               *end = save;
2940             }
2941           p = end;
2942         }
2943     }
2944
2945   /* load the deplibs (in reverse order)
2946      At this stage, don't worry if the deplibs do not load correctly,
2947      they may already be statically linked into the loading application
2948      for instance.  There will be a more enlightening error message
2949      later on if the loaded module cannot resolve all of its symbols.  */
2950   if (depcount)
2951     {
2952       int       j = 0;
2953
2954       handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2955       if (!handle->deplibs)
2956         goto cleanup;
2957
2958       for (i = 0; i < depcount; ++i)
2959         {
2960           handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2961           if (handle->deplibs[j])
2962             {
2963               ++j;
2964             }
2965         }
2966
2967       handle->depcount  = j;    /* Number of successfully loaded deplibs */
2968       errors            = 0;
2969     }
2970
2971  cleanup_names:
2972   for (i = 0; i < depcount; ++i)
2973     {
2974       LT_DLFREE (names[i]);
2975     }
2976
2977  cleanup:
2978   LT_DLFREE (names);
2979   /* restore the old search path */
2980   if (user_search_path) {
2981     LT_DLFREE (user_search_path);
2982     user_search_path = save_search_path;
2983   }
2984   LT_DLMUTEX_UNLOCK ();
2985
2986 #endif
2987
2988   return errors;
2989 }
2990
2991 static int
2992 unload_deplibs (handle)
2993      lt_dlhandle handle;
2994 {
2995   int i;
2996   int errors = 0;
2997
2998   if (handle->depcount)
2999     {
3000       for (i = 0; i < handle->depcount; ++i)
3001         {
3002           if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
3003             {
3004               errors += lt_dlclose (handle->deplibs[i]);
3005             }
3006         }
3007     }
3008
3009   return errors;
3010 }
3011
3012 static int
3013 trim (dest, str)
3014      char **dest;
3015      const char *str;
3016 {
3017   /* remove the leading and trailing "'" from str
3018      and store the result in dest */
3019   const char *end   = strrchr (str, '\'');
3020   size_t len        = LT_STRLEN (str);
3021   char *tmp;
3022
3023   LT_DLFREE (*dest);
3024
3025   if (!end)
3026     return 1;
3027
3028   if (len > 3 && str[0] == '\'')
3029     {
3030       tmp = LT_EMALLOC (char, end - str);
3031       if (!tmp)
3032         return 1;
3033
3034       strncpy(tmp, &str[1], (end - str) - 1);
3035       tmp[len-3] = LT_EOS_CHAR;
3036       *dest = tmp;
3037     }
3038   else
3039     {
3040       *dest = 0;
3041     }
3042
3043   return 0;
3044 }
3045
3046 static int
3047 free_vars (dlname, oldname, libdir, deplibs)
3048      char *dlname;
3049      char *oldname;
3050      char *libdir;
3051      char *deplibs;
3052 {
3053   LT_DLFREE (dlname);
3054   LT_DLFREE (oldname);
3055   LT_DLFREE (libdir);
3056   LT_DLFREE (deplibs);
3057
3058   return 0;
3059 }
3060
3061 static int
3062 try_dlopen (phandle, filename)
3063      lt_dlhandle *phandle;
3064      const char *filename;
3065 {
3066   const char *  ext             = 0;
3067   const char *  saved_error     = 0;
3068   char *        canonical       = 0;
3069   char *        base_name       = 0;
3070   char *        dir             = 0;
3071   char *        name            = 0;
3072   int           errors          = 0;
3073   lt_dlhandle   newhandle;
3074
3075   assert (phandle);
3076   assert (*phandle == 0);
3077
3078   LT_DLMUTEX_GETERROR (saved_error);
3079
3080   /* dlopen self? */
3081   if (!filename)
3082     {
3083       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3084       if (*phandle == 0)
3085         return 1;
3086
3087       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3088       newhandle = *phandle;
3089
3090       /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
3091       LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
3092
3093       if (tryall_dlopen (&newhandle, 0, NULL) != 0)
3094         {
3095           LT_DLFREE (*phandle);
3096           return 1;
3097         }
3098
3099       goto register_handle;
3100     }
3101
3102   assert (filename && *filename);
3103
3104   /* Doing this immediately allows internal functions to safely
3105      assume only canonicalized paths are passed.  */
3106   if (canonicalize_path (filename, &canonical) != 0)
3107     {
3108       ++errors;
3109       goto cleanup;
3110     }
3111
3112   /* If the canonical module name is a path (relative or absolute)
3113      then split it into a directory part and a name part.  */
3114   base_name = strrchr (canonical, '/');
3115   if (base_name)
3116     {
3117       size_t dirlen = (1+ base_name) - canonical;
3118
3119       dir = LT_EMALLOC (char, 1+ dirlen);
3120       if (!dir)
3121         {
3122           ++errors;
3123           goto cleanup;
3124         }
3125
3126       strncpy (dir, canonical, dirlen);
3127       dir[dirlen] = LT_EOS_CHAR;
3128
3129       ++base_name;
3130     }
3131   else
3132     base_name = canonical;
3133
3134   assert (base_name && *base_name);
3135
3136   /* Check whether we are opening a libtool module (.la extension).  */
3137   ext = strrchr (base_name, '.');
3138   if (ext && strcmp (ext, archive_ext) == 0)
3139     {
3140       /* this seems to be a libtool module */
3141       FILE *    file     = 0;
3142       char *    dlname   = 0;
3143       char *    old_name = 0;
3144       char *    libdir   = 0;
3145       char *    deplibs  = 0;
3146       char *    line     = 0;
3147       size_t    line_len;
3148
3149       /* if we can't find the installed flag, it is probably an
3150          installed libtool archive, produced with an old version
3151          of libtool */
3152       int       installed = 1;
3153
3154       /* extract the module name from the file name */
3155       name = LT_EMALLOC (char, ext - base_name + 1);
3156       if (!name)
3157         {
3158           ++errors;
3159           goto cleanup;
3160         }
3161
3162       /* canonicalize the module name */
3163       {
3164         size_t i;
3165         for (i = 0; i < ext - base_name; ++i)
3166           {
3167             if (isalnum ((int)(base_name[i])))
3168               {
3169                 name[i] = base_name[i];
3170               }
3171             else
3172               {
3173                 name[i] = '_';
3174               }
3175           }
3176         name[ext - base_name] = LT_EOS_CHAR;
3177       }
3178
3179       /* Now try to open the .la file.  If there is no directory name
3180          component, try to find it first in user_search_path and then other
3181          prescribed paths.  Otherwise (or in any case if the module was not
3182          yet found) try opening just the module name as passed.  */
3183       if (!dir)
3184         {
3185           const char *search_path;
3186
3187           LT_DLMUTEX_LOCK ();
3188           search_path = user_search_path;
3189           if (search_path)
3190             file = find_file (user_search_path, base_name, &dir);
3191           LT_DLMUTEX_UNLOCK ();
3192
3193           if (!file)
3194             {
3195               search_path = getenv (LTDL_SEARCHPATH_VAR);
3196               if (search_path)
3197                 file = find_file (search_path, base_name, &dir);
3198             }
3199
3200 #ifdef LTDL_SHLIBPATH_VAR
3201           if (!file)
3202             {
3203               search_path = getenv (LTDL_SHLIBPATH_VAR);
3204               if (search_path)
3205                 file = find_file (search_path, base_name, &dir);
3206             }
3207 #endif
3208 #ifdef LTDL_SYSSEARCHPATH
3209           if (!file && sys_search_path)
3210             {
3211               file = find_file (sys_search_path, base_name, &dir);
3212             }
3213 #endif
3214         }
3215       else
3216         {
3217           file = fopen (filename, LT_READTEXT_MODE);
3218         }
3219
3220       /* If we didn't find the file by now, it really isn't there.  Set
3221          the status flag, and bail out.  */
3222       if (!file)
3223         {
3224           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3225           ++errors;
3226           goto cleanup;
3227         }
3228
3229       line_len = LT_FILENAME_MAX;
3230       line = LT_EMALLOC (char, line_len);
3231       if (!line)
3232         {
3233           fclose (file);
3234           ++errors;
3235           goto cleanup;
3236         }
3237
3238       /* read the .la file */
3239       while (!feof (file))
3240         {
3241           if (!fgets (line, (int) line_len, file))
3242             {
3243               break;
3244             }
3245
3246           /* Handle the case where we occasionally need to read a line
3247              that is longer than the initial buffer size.  */
3248           while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
3249             {
3250               line = LT_DLREALLOC (char, line, line_len *2);
3251               if (!fgets (&line[line_len -1], (int) line_len +1, file))
3252                 {
3253                   break;
3254                 }
3255               line_len *= 2;
3256             }
3257
3258           if (line[0] == '\n' || line[0] == '#')
3259             {
3260               continue;
3261             }
3262
3263 #undef  STR_DLNAME
3264 #define STR_DLNAME      "dlname="
3265           if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
3266             {
3267               errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
3268             }
3269
3270 #undef  STR_OLD_LIBRARY
3271 #define STR_OLD_LIBRARY "old_library="
3272           else if (strncmp (line, STR_OLD_LIBRARY,
3273                             sizeof (STR_OLD_LIBRARY) - 1) == 0)
3274             {
3275               errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
3276             }
3277 #undef  STR_LIBDIR
3278 #define STR_LIBDIR      "libdir="
3279           else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
3280             {
3281               errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
3282             }
3283
3284 #undef  STR_DL_DEPLIBS
3285 #define STR_DL_DEPLIBS  "dependency_libs="
3286           else if (strncmp (line, STR_DL_DEPLIBS,
3287                             sizeof (STR_DL_DEPLIBS) - 1) == 0)
3288             {
3289               errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
3290             }
3291           else if (strcmp (line, "installed=yes\n") == 0)
3292             {
3293               installed = 1;
3294             }
3295           else if (strcmp (line, "installed=no\n") == 0)
3296             {
3297               installed = 0;
3298             }
3299
3300 #undef  STR_LIBRARY_NAMES
3301 #define STR_LIBRARY_NAMES "library_names="
3302           else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
3303                                         sizeof (STR_LIBRARY_NAMES) - 1) == 0)
3304             {
3305               char *last_libname;
3306               errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
3307               if (!errors
3308                   && dlname
3309                   && (last_libname = strrchr (dlname, ' ')) != 0)
3310                 {
3311                   last_libname = lt_estrdup (last_libname + 1);
3312                   if (!last_libname)
3313                     {
3314                       ++errors;
3315                       goto cleanup;
3316                     }
3317                   LT_DLMEM_REASSIGN (dlname, last_libname);
3318                 }
3319             }
3320
3321           if (errors)
3322             break;
3323         }
3324
3325       fclose (file);
3326       LT_DLFREE (line);
3327
3328       /* allocate the handle */
3329       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3330       if (*phandle == 0)
3331         ++errors;
3332
3333       if (errors)
3334         {
3335           free_vars (dlname, old_name, libdir, deplibs);
3336           LT_DLFREE (*phandle);
3337           goto cleanup;
3338         }
3339
3340       assert (*phandle);
3341
3342       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3343       if (load_deplibs (*phandle, deplibs) == 0)
3344         {
3345           newhandle = *phandle;
3346           /* find_module may replace newhandle */
3347           if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
3348             {
3349               unload_deplibs (*phandle);
3350               ++errors;
3351             }
3352         }
3353       else
3354         {
3355           ++errors;
3356         }
3357
3358       free_vars (dlname, old_name, libdir, deplibs);
3359       if (errors)
3360         {
3361           LT_DLFREE (*phandle);
3362           goto cleanup;
3363         }
3364
3365       if (*phandle != newhandle)
3366         {
3367           unload_deplibs (*phandle);
3368         }
3369     }
3370   else
3371     {
3372       /* not a libtool module */
3373       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3374       if (*phandle == 0)
3375         {
3376           ++errors;
3377           goto cleanup;
3378         }
3379
3380       memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
3381       newhandle = *phandle;
3382
3383       /* If the module has no directory name component, try to find it
3384          first in user_search_path and then other prescribed paths.
3385          Otherwise (or in any case if the module was not yet found) try
3386          opening just the module name as passed.  */
3387       if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
3388                    && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
3389                                     &newhandle)
3390 #ifdef LTDL_SHLIBPATH_VAR
3391                    && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
3392                                     &newhandle)
3393 #endif
3394 #ifdef LTDL_SYSSEARCHPATH
3395                    && !find_handle (sys_search_path, base_name, &newhandle)
3396 #endif
3397                    )))
3398         {
3399           if (tryall_dlopen (&newhandle, filename, NULL) != 0)
3400             {
3401               newhandle = NULL;
3402             }
3403         }
3404
3405       if (!newhandle)
3406         {
3407           LT_DLFREE (*phandle);
3408           ++errors;
3409           goto cleanup;
3410         }
3411     }
3412
3413  register_handle:
3414   LT_DLMEM_REASSIGN (*phandle, newhandle);
3415
3416   if ((*phandle)->info.ref_count == 0)
3417     {
3418       (*phandle)->info.ref_count        = 1;
3419       LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
3420
3421       LT_DLMUTEX_LOCK ();
3422       (*phandle)->next          = handles;
3423       handles                   = *phandle;
3424       LT_DLMUTEX_UNLOCK ();
3425     }
3426
3427   LT_DLMUTEX_SETERROR (saved_error);
3428
3429  cleanup:
3430   LT_DLFREE (dir);
3431   LT_DLFREE (name);
3432   LT_DLFREE (canonical);
3433
3434   return errors;
3435 }
3436
3437 lt_dlhandle
3438 lt_dlopen (filename)
3439      const char *filename;
3440 {
3441   lt_dlhandle handle = 0;
3442
3443   /* Just incase we missed a code path in try_dlopen() that reports
3444      an error, but forgets to reset handle... */
3445   if (try_dlopen (&handle, filename) != 0)
3446     return 0;
3447
3448   return handle;
3449 }
3450
3451 /* If the last error messge store was `FILE_NOT_FOUND', then return
3452    non-zero.  */
3453 static int
3454 file_not_found ()
3455 {
3456   const char *error = 0;
3457
3458   LT_DLMUTEX_GETERROR (error);
3459   if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
3460     return 1;
3461
3462   return 0;
3463 }
3464
3465 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3466    open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
3467    and if a file is still not found try again with SHLIB_EXT appended
3468    instead.  */
3469 lt_dlhandle
3470 lt_dlopenext (filename)
3471      const char *filename;
3472 {
3473   lt_dlhandle   handle          = 0;
3474   char *        tmp             = 0;
3475   char *        ext             = 0;
3476   size_t        len;
3477   int           errors          = 0;
3478
3479   if (!filename)
3480     {
3481       return lt_dlopen (filename);
3482     }
3483
3484   assert (filename);
3485
3486   len = LT_STRLEN (filename);
3487   ext = strrchr (filename, '.');
3488
3489   /* If FILENAME already bears a suitable extension, there is no need
3490      to try appending additional extensions.  */
3491   if (ext && ((strcmp (ext, archive_ext) == 0)
3492 #ifdef LTDL_SHLIB_EXT
3493               || (strcmp (ext, shlib_ext) == 0)
3494 #endif
3495       ))
3496     {
3497       return lt_dlopen (filename);
3498     }
3499
3500   /* First try appending ARCHIVE_EXT.  */
3501   tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
3502   if (!tmp)
3503     return 0;
3504
3505   strcpy (tmp, filename);
3506   strcat (tmp, archive_ext);
3507   errors = try_dlopen (&handle, tmp);
3508   if (handle && errors) {
3509     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FR_DEPLIB));
3510     return 0;   /* leaks tmp and handle */
3511   }
3512   if (handle && errors) {
3513     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FR_DEPLIB));
3514     return 0;   /* leaks tmp and handle */
3515   }
3516
3517   /* If we found FILENAME, stop searching -- whether we were able to
3518      load the file as a module or not.  If the file exists but loading
3519      failed, it is better to return an error message here than to
3520      report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3521      in the module search path.  */
3522   if (handle || ((errors > 0) && !file_not_found ()))
3523     {
3524       LT_DLFREE (tmp);
3525       return handle;
3526     }
3527
3528 #ifdef LTDL_SHLIB_EXT
3529   /* Try appending SHLIB_EXT.   */
3530   if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
3531     {
3532       LT_DLFREE (tmp);
3533       tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3534       if (!tmp)
3535         return 0;
3536
3537       strcpy (tmp, filename);
3538     }
3539   else
3540     {
3541       tmp[len] = LT_EOS_CHAR;
3542   if (handle && errors) {
3543     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FR_DEPLIB));
3544     return 0;   /* leaks tmp and handle */
3545   }
3546     }
3547
3548   strcat(tmp, shlib_ext);
3549   errors = try_dlopen (&handle, tmp);
3550   if (handle && errors) {
3551     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FR_DEPLIB));
3552     return 0;   /* leaks tmp and handle */
3553   }
3554
3555   /* As before, if the file was found but loading failed, return now
3556      with the current error message.  */
3557   if (handle || ((errors > 0) && !file_not_found ()))
3558     {
3559       LT_DLFREE (tmp);
3560       return handle;
3561     }
3562 #endif
3563
3564   /* Still here?  Then we really did fail to locate any of the file
3565      names we tried.  */
3566   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3567   LT_DLFREE (tmp);
3568   return 0;
3569 }
3570
3571
3572 static int
3573 lt_argz_insert (pargz, pargz_len, before, entry)
3574      char **pargz;
3575      size_t *pargz_len;
3576      char *before;
3577      const char *entry;
3578 {
3579   error_t error;
3580
3581   /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
3582      pargz_len, NULL, entry) failed with EINVAL.  */
3583   if (before)
3584     error = argz_insert (pargz, pargz_len, before, entry);
3585   else
3586     error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
3587
3588   if (error)
3589     {
3590       switch (error)
3591         {
3592         case ENOMEM:
3593           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3594           break;
3595         default:
3596           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3597           break;
3598         }
3599       return 1;
3600     }
3601
3602   return 0;
3603 }
3604
3605 static int
3606 lt_argz_insertinorder (pargz, pargz_len, entry)
3607      char **pargz;
3608      size_t *pargz_len;
3609      const char *entry;
3610 {
3611   char *before = 0;
3612
3613   assert (pargz);
3614   assert (pargz_len);
3615   assert (entry && *entry);
3616
3617   if (*pargz)
3618     while ((before = argz_next (*pargz, *pargz_len, before)))
3619       {
3620         int cmp = strcmp (entry, before);
3621
3622         if (cmp < 0)  break;
3623         if (cmp == 0) return 0; /* No duplicates! */
3624       }
3625
3626   return lt_argz_insert (pargz, pargz_len, before, entry);
3627 }
3628
3629 static int
3630 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3631      char **pargz;
3632      size_t *pargz_len;
3633      const char *dirnam;
3634      struct dirent *dp;
3635 {
3636   char   *buf       = 0;
3637   size_t buf_len    = 0;
3638   char   *end       = 0;
3639   size_t end_offset = 0;
3640   size_t dir_len    = 0;
3641   int    errors     = 0;
3642
3643   assert (pargz);
3644   assert (pargz_len);
3645   assert (dp);
3646
3647   dir_len = LT_STRLEN (dirnam);
3648   end     = dp->d_name + LT_D_NAMLEN(dp);
3649
3650   /* Ignore version numbers.  */
3651   {
3652     char *p;
3653     for (p = end; p -1 > dp->d_name; --p)
3654       if (strchr (".0123456789", p[-1]) == 0)
3655         break;
3656
3657     if (*p == '.')
3658       end = p;
3659   }
3660
3661   /* Ignore filename extension.  */
3662   {
3663     char *p;
3664     for (p = end -1; p > dp->d_name; --p)
3665       if (*p == '.')
3666         {
3667           end = p;
3668           break;
3669         }
3670   }
3671
3672   /* Prepend the directory name.  */
3673   end_offset    = end - dp->d_name;
3674   buf_len       = dir_len + 1+ end_offset;
3675   buf           = LT_EMALLOC (char, 1+ buf_len);
3676   if (!buf)
3677     return ++errors;
3678
3679   assert (buf);
3680
3681   strcpy  (buf, dirnam);
3682   strcat  (buf, "/");
3683   strncat (buf, dp->d_name, end_offset);
3684   buf[buf_len] = LT_EOS_CHAR;
3685
3686   /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
3687   if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3688     ++errors;
3689
3690   LT_DLFREE (buf);
3691
3692   return errors;
3693 }
3694
3695 static int
3696 list_files_by_dir (dirnam, pargz, pargz_len)
3697      const char *dirnam;
3698      char **pargz;
3699      size_t *pargz_len;
3700 {
3701   DIR   *dirp     = 0;
3702   int    errors   = 0;
3703
3704   assert (dirnam && *dirnam);
3705   assert (pargz);
3706   assert (pargz_len);
3707   assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3708
3709   dirp = opendir (dirnam);
3710   if (dirp)
3711     {
3712       struct dirent *dp = 0;
3713
3714       while ((dp = readdir (dirp)))
3715         if (dp->d_name[0] != '.')
3716           if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3717             {
3718               ++errors;
3719               break;
3720             }
3721
3722       closedir (dirp);
3723     }
3724   else
3725     ++errors;
3726
3727   return errors;
3728 }
3729
3730
3731 /* If there are any files in DIRNAME, call the function passed in
3732    DATA1 (with the name of each file and DATA2 as arguments).  */
3733 static int
3734 foreachfile_callback (dirname, data1, data2)
3735      char *dirname;
3736      lt_ptr data1;
3737      lt_ptr data2;
3738 {
3739   int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3740         = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3741
3742   int     is_done  = 0;
3743   char   *argz     = 0;
3744   size_t  argz_len = 0;
3745
3746   if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3747     goto cleanup;
3748   if (!argz)
3749     goto cleanup;
3750
3751   {
3752     char *filename = 0;
3753     while ((filename = argz_next (argz, argz_len, filename)))
3754       if ((is_done = (*func) (filename, data2)))
3755         break;
3756   }
3757
3758  cleanup:
3759   LT_DLFREE (argz);
3760
3761   return is_done;
3762 }
3763
3764
3765 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3766    with DATA.  The filenames passed to FUNC would be suitable for
3767    passing to lt_dlopenext.  The extensions are stripped so that
3768    individual modules do not generate several entries (e.g. libfoo.la,
3769    libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
3770    then the same directories that lt_dlopen would search are examined.  */
3771 int
3772 lt_dlforeachfile (search_path, func, data)
3773      const char *search_path;
3774      int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3775      lt_ptr data;
3776 {
3777   int is_done = 0;
3778
3779   if (search_path)
3780     {
3781       /* If a specific path was passed, search only the directories
3782          listed in it.  */
3783       is_done = foreach_dirinpath (search_path, 0,
3784                                    foreachfile_callback, func, data);
3785     }
3786   else
3787     {
3788       /* Otherwise search the default paths.  */
3789       is_done = foreach_dirinpath (user_search_path, 0,
3790                                    foreachfile_callback, func, data);
3791       if (!is_done)
3792         {
3793           is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3794                                        foreachfile_callback, func, data);
3795         }
3796
3797 #ifdef LTDL_SHLIBPATH_VAR
3798       if (!is_done)
3799         {
3800           is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3801                                        foreachfile_callback, func, data);
3802         }
3803 #endif
3804 #ifdef LTDL_SYSSEARCHPATH
3805       if (!is_done)
3806         {
3807           is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3808                                        foreachfile_callback, func, data);
3809         }
3810 #endif
3811     }
3812
3813   return is_done;
3814 }
3815
3816 int
3817 lt_dlclose (handle)
3818      lt_dlhandle handle;
3819 {
3820   lt_dlhandle cur, last;
3821   int errors = 0;
3822
3823   LT_DLMUTEX_LOCK ();
3824
3825   /* check whether the handle is valid */
3826   last = cur = handles;
3827   while (cur && handle != cur)
3828     {
3829       last = cur;
3830       cur = cur->next;
3831     }
3832
3833   if (!cur)
3834     {
3835       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3836       ++errors;
3837       goto done;
3838     }
3839
3840   handle->info.ref_count--;
3841
3842   /* Note that even with resident modules, we must track the ref_count
3843      correctly incase the user decides to reset the residency flag
3844      later (even though the API makes no provision for that at the
3845      moment).  */
3846   if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3847     {
3848       lt_user_data data = handle->loader->dlloader_data;
3849
3850       if (handle != handles)
3851         {
3852           last->next = handle->next;
3853         }
3854       else
3855         {
3856           handles = handle->next;
3857         }
3858
3859       errors += handle->loader->module_close (data, handle->module);
3860       errors += unload_deplibs(handle);
3861
3862       /* It is up to the callers to free the data itself.  */
3863       LT_DLFREE (handle->caller_data);
3864
3865       LT_DLFREE (handle->info.filename);
3866       LT_DLFREE (handle->info.name);
3867       LT_DLFREE (handle);
3868
3869       goto done;
3870     }
3871
3872   if (LT_DLIS_RESIDENT (handle))
3873     {
3874       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3875       ++errors;
3876     }
3877
3878  done:
3879   LT_DLMUTEX_UNLOCK ();
3880
3881   return errors;
3882 }
3883
3884 lt_ptr
3885 lt_dlsym (handle, symbol)
3886      lt_dlhandle handle;
3887      const char *symbol;
3888 {
3889   size_t lensym;
3890   char  lsym[LT_SYMBOL_LENGTH];
3891   char  *sym;
3892   lt_ptr address;
3893   lt_user_data data;
3894
3895   if (!handle)
3896     {
3897       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3898       return 0;
3899     }
3900
3901   if (!symbol)
3902     {
3903       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3904       return 0;
3905     }
3906
3907   lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3908                                         + LT_STRLEN (handle->info.name);
3909
3910   if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3911     {
3912       sym = lsym;
3913     }
3914   else
3915     {
3916       sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3917       if (!sym)
3918         {
3919           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3920           return 0;
3921         }
3922     }
3923
3924   data = handle->loader->dlloader_data;
3925   if (handle->info.name)
3926     {
3927       const char *saved_error;
3928
3929       LT_DLMUTEX_GETERROR (saved_error);
3930
3931       /* this is a libtool module */
3932       if (handle->loader->sym_prefix)
3933         {
3934           strcpy(sym, handle->loader->sym_prefix);
3935           strcat(sym, handle->info.name);
3936         }
3937       else
3938         {
3939           strcpy(sym, handle->info.name);
3940         }
3941
3942       strcat(sym, "_LTX_");
3943       strcat(sym, symbol);
3944
3945       /* try "modulename_LTX_symbol" */
3946       address = handle->loader->find_sym (data, handle->module, sym);
3947       if (address)
3948         {
3949           if (sym != lsym)
3950             {
3951               LT_DLFREE (sym);
3952             }
3953           return address;
3954         }
3955       LT_DLMUTEX_SETERROR (saved_error);
3956     }
3957
3958   /* otherwise try "symbol" */
3959   if (handle->loader->sym_prefix)
3960     {
3961       strcpy(sym, handle->loader->sym_prefix);
3962       strcat(sym, symbol);
3963     }
3964   else
3965     {
3966       strcpy(sym, symbol);
3967     }
3968
3969   address = handle->loader->find_sym (data, handle->module, sym);
3970   if (sym != lsym)
3971     {
3972       LT_DLFREE (sym);
3973     }
3974
3975   return address;
3976 }
3977
3978 const char *
3979 lt_dlerror ()
3980 {
3981   const char *error;
3982
3983   LT_DLMUTEX_GETERROR (error);
3984   LT_DLMUTEX_SETERROR (0);
3985
3986   return error ? error : NULL;
3987 }
3988
3989 static int
3990 lt_dlpath_insertdir (ppath, before, dir)
3991      char **ppath;
3992      char *before;
3993      const char *dir;
3994 {
3995   int    errors         = 0;
3996   char  *canonical      = 0;
3997   char  *argz           = 0;
3998   size_t argz_len       = 0;
3999
4000   assert (ppath);
4001   assert (dir && *dir);
4002
4003   if (canonicalize_path (dir, &canonical) != 0)
4004     {
4005       ++errors;
4006       goto cleanup;
4007     }
4008
4009   assert (canonical && *canonical);
4010
4011   /* If *PPATH is empty, set it to DIR.  */
4012   if (*ppath == 0)
4013     {
4014       assert (!before);         /* BEFORE cannot be set without PPATH.  */
4015       assert (dir);             /* Without DIR, don't call this function!  */
4016
4017       *ppath = lt_estrdup (dir);
4018       if (*ppath == 0)
4019         ++errors;
4020
4021       return errors;
4022     }
4023
4024   assert (ppath && *ppath);
4025
4026   if (argzize_path (*ppath, &argz, &argz_len) != 0)
4027     {
4028       ++errors;
4029       goto cleanup;
4030     }
4031
4032   /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
4033      if *PPATH is already canonicalized, and hence does not change length
4034      with respect to ARGZ.  We canonicalize each entry as it is added to
4035      the search path, and don't call this function with (uncanonicalized)
4036      user paths, so this is a fair assumption.  */
4037   if (before)
4038     {
4039       assert (*ppath <= before);
4040       assert (before - *ppath <= strlen (*ppath));
4041
4042       before = before - *ppath + argz;
4043     }
4044
4045   if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
4046     {
4047       ++errors;
4048       goto cleanup;
4049     }
4050
4051   argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
4052   LT_DLMEM_REASSIGN (*ppath,  argz);
4053
4054  cleanup:
4055   LT_DLFREE (canonical);
4056   LT_DLFREE (argz);
4057
4058   return errors;
4059 }
4060
4061 int
4062 lt_dladdsearchdir (search_dir)
4063      const char *search_dir;
4064 {
4065   int errors = 0;
4066
4067   if (search_dir && *search_dir)
4068     {
4069       LT_DLMUTEX_LOCK ();
4070       if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
4071         ++errors;
4072       LT_DLMUTEX_UNLOCK ();
4073     }
4074
4075   return errors;
4076 }
4077
4078 int
4079 lt_dlinsertsearchdir (before, search_dir)
4080      const char *before;
4081      const char *search_dir;
4082 {
4083   int errors = 0;
4084
4085   if (before)
4086     {
4087       LT_DLMUTEX_LOCK ();
4088       if ((before < user_search_path)
4089           || (before >= user_search_path + LT_STRLEN (user_search_path)))
4090         {
4091           LT_DLMUTEX_UNLOCK ();
4092           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
4093           return 1;
4094         }
4095       LT_DLMUTEX_UNLOCK ();
4096     }
4097
4098   if (search_dir && *search_dir)
4099     {
4100       LT_DLMUTEX_LOCK ();
4101       if (lt_dlpath_insertdir (&user_search_path,
4102                                (char *) before, search_dir) != 0)
4103         {
4104           ++errors;
4105         }
4106       LT_DLMUTEX_UNLOCK ();
4107     }
4108
4109   return errors;
4110 }
4111
4112 int
4113 lt_dlsetsearchpath (search_path)
4114      const char *search_path;
4115 {
4116   int   errors      = 0;
4117
4118   LT_DLMUTEX_LOCK ();
4119   LT_DLFREE (user_search_path);
4120   LT_DLMUTEX_UNLOCK ();
4121
4122   if (!search_path || !LT_STRLEN (search_path))
4123     {
4124       return errors;
4125     }
4126
4127   LT_DLMUTEX_LOCK ();
4128   if (canonicalize_path (search_path, &user_search_path) != 0)
4129     ++errors;
4130   LT_DLMUTEX_UNLOCK ();
4131
4132   return errors;
4133 }
4134
4135 const char *
4136 lt_dlgetsearchpath ()
4137 {
4138   const char *saved_path;
4139
4140   LT_DLMUTEX_LOCK ();
4141   saved_path = user_search_path;
4142   LT_DLMUTEX_UNLOCK ();
4143
4144   return saved_path;
4145 }
4146
4147 int
4148 lt_dlmakeresident (handle)
4149      lt_dlhandle handle;
4150 {
4151   int errors = 0;
4152
4153   if (!handle)
4154     {
4155       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4156       ++errors;
4157     }
4158   else
4159     {
4160       LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
4161     }
4162
4163   return errors;
4164 }
4165
4166 int
4167 lt_dlisresident (handle)
4168      lt_dlhandle handle;
4169 {
4170   if (!handle)
4171     {
4172       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4173       return -1;
4174     }
4175
4176   return LT_DLIS_RESIDENT (handle);
4177 }
4178
4179
4180
4181 \f
4182 /* --- MODULE INFORMATION --- */
4183
4184 const lt_dlinfo *
4185 lt_dlgetinfo (handle)
4186      lt_dlhandle handle;
4187 {
4188   if (!handle)
4189     {
4190       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4191       return 0;
4192     }
4193
4194   return &(handle->info);
4195 }
4196
4197 lt_dlhandle
4198 lt_dlhandle_next (place)
4199      lt_dlhandle place;
4200 {
4201   return place ? place->next : handles;
4202 }
4203
4204 int
4205 lt_dlforeach (func, data)
4206      int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
4207      lt_ptr data;
4208 {
4209   int errors = 0;
4210   lt_dlhandle cur;
4211
4212   LT_DLMUTEX_LOCK ();
4213
4214   cur = handles;
4215   while (cur)
4216     {
4217       lt_dlhandle tmp = cur;
4218
4219       cur = cur->next;
4220       if ((*func) (tmp, data))
4221         {
4222           ++errors;
4223           break;
4224         }
4225     }
4226
4227   LT_DLMUTEX_UNLOCK ();
4228
4229   return errors;
4230 }
4231
4232 lt_dlcaller_id
4233 lt_dlcaller_register ()
4234 {
4235   static lt_dlcaller_id last_caller_id = 0;
4236   int result;
4237
4238   LT_DLMUTEX_LOCK ();
4239   result = ++last_caller_id;
4240   LT_DLMUTEX_UNLOCK ();
4241
4242   return result;
4243 }
4244
4245 lt_ptr
4246 lt_dlcaller_set_data (key, handle, data)
4247      lt_dlcaller_id key;
4248      lt_dlhandle handle;
4249      lt_ptr data;
4250 {
4251   int n_elements = 0;
4252   lt_ptr stale = (lt_ptr) 0;
4253   int i;
4254
4255   /* This needs to be locked so that the caller data can be updated
4256      simultaneously by different threads.  */
4257   LT_DLMUTEX_LOCK ();
4258
4259   if (handle->caller_data)
4260     while (handle->caller_data[n_elements].key)
4261       ++n_elements;
4262
4263   for (i = 0; i < n_elements; ++i)
4264     {
4265       if (handle->caller_data[i].key == key)
4266         {
4267           stale = handle->caller_data[i].data;
4268           break;
4269         }
4270     }
4271
4272   /* Ensure that there is enough room in this handle's caller_data
4273      array to accept a new element (and an empty end marker).  */
4274   if (i == n_elements)
4275     {
4276       lt_caller_data *temp
4277         = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
4278
4279       if (!temp)
4280         {
4281           stale = 0;
4282           goto done;
4283         }
4284
4285       handle->caller_data = temp;
4286
4287       /* We only need this if we needed to allocate a new caller_data.  */
4288       handle->caller_data[i].key  = key;
4289       handle->caller_data[1+ i].key = 0;
4290     }
4291
4292   handle->caller_data[i].data = data;
4293
4294  done:
4295   LT_DLMUTEX_UNLOCK ();
4296
4297   return stale;
4298 }
4299
4300 lt_ptr
4301 lt_dlcaller_get_data  (key, handle)
4302      lt_dlcaller_id key;
4303      lt_dlhandle handle;
4304 {
4305   lt_ptr result = (lt_ptr) 0;
4306
4307   /* This needs to be locked so that the caller data isn't updated by
4308      another thread part way through this function.  */
4309   LT_DLMUTEX_LOCK ();
4310
4311   /* Locate the index of the element with a matching KEY.  */
4312   {
4313     int i;
4314     for (i = 0; handle->caller_data[i].key; ++i)
4315       {
4316         if (handle->caller_data[i].key == key)
4317           {
4318             result = handle->caller_data[i].data;
4319             break;
4320           }
4321       }
4322   }
4323
4324   LT_DLMUTEX_UNLOCK ();
4325
4326   return result;
4327 }
4328
4329
4330 \f
4331 /* --- USER MODULE LOADER API --- */
4332
4333
4334 int
4335 lt_dlloader_add (place, dlloader, loader_name)
4336      lt_dlloader *place;
4337      const struct lt_user_dlloader *dlloader;
4338      const char *loader_name;
4339 {
4340   int errors = 0;
4341   lt_dlloader *node = 0, *ptr = 0;
4342
4343   if ((dlloader == 0)   /* diagnose null parameters */
4344       || (dlloader->module_open == 0)
4345       || (dlloader->module_close == 0)
4346       || (dlloader->find_sym == 0))
4347     {
4348       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4349       return 1;
4350     }
4351
4352   /* Create a new dlloader node with copies of the user callbacks.  */
4353   node = LT_EMALLOC (lt_dlloader, 1);
4354   if (!node)
4355     return 1;
4356
4357   node->next            = 0;
4358   node->loader_name     = loader_name;
4359   node->sym_prefix      = dlloader->sym_prefix;
4360   node->dlloader_exit   = dlloader->dlloader_exit;
4361   node->module_open     = dlloader->module_open;
4362   node->module_close    = dlloader->module_close;
4363   node->find_sym        = dlloader->find_sym;
4364   node->dlloader_data   = dlloader->dlloader_data;
4365
4366   LT_DLMUTEX_LOCK ();
4367   if (!loaders)
4368     {
4369       /* If there are no loaders, NODE becomes the list! */
4370       loaders = node;
4371     }
4372   else if (!place)
4373     {
4374       /* If PLACE is not set, add NODE to the end of the
4375          LOADERS list. */
4376       for (ptr = loaders; ptr->next; ptr = ptr->next)
4377         {
4378           /*NOWORK*/;
4379         }
4380
4381       ptr->next = node;
4382     }
4383   else if (loaders == place)
4384     {
4385       /* If PLACE is the first loader, NODE goes first. */
4386       node->next = place;
4387       loaders = node;
4388     }
4389   else
4390     {
4391       /* Find the node immediately preceding PLACE. */
4392       for (ptr = loaders; ptr->next != place; ptr = ptr->next)
4393         {
4394           /*NOWORK*/;
4395         }
4396
4397       if (ptr->next != place)
4398         {
4399           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4400           ++errors;
4401         }
4402       else
4403         {
4404           /* Insert NODE between PTR and PLACE. */
4405           node->next = place;
4406           ptr->next  = node;
4407         }
4408     }
4409
4410   LT_DLMUTEX_UNLOCK ();
4411
4412   return errors;
4413 }
4414
4415 int
4416 lt_dlloader_remove (loader_name)
4417      const char *loader_name;
4418 {
4419   lt_dlloader *place = lt_dlloader_find (loader_name);
4420   lt_dlhandle handle;
4421   int errors = 0;
4422
4423   if (!place)
4424     {
4425       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4426       return 1;
4427     }
4428
4429   LT_DLMUTEX_LOCK ();
4430
4431   /* Fail if there are any open modules which use this loader. */
4432   for  (handle = handles; handle; handle = handle->next)
4433     {
4434       if (handle->loader == place)
4435         {
4436           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
4437           ++errors;
4438           goto done;
4439         }
4440     }
4441
4442   if (place == loaders)
4443     {
4444       /* PLACE is the first loader in the list. */
4445       loaders = loaders->next;
4446     }
4447   else
4448     {
4449       /* Find the loader before the one being removed. */
4450       lt_dlloader *prev;
4451       for (prev = loaders; prev->next; prev = prev->next)
4452         {
4453           if (!strcmp (prev->next->loader_name, loader_name))
4454             {
4455               break;
4456             }
4457         }
4458
4459       place = prev->next;
4460       prev->next = prev->next->next;
4461     }
4462
4463   if (place->dlloader_exit)
4464     {
4465       errors = place->dlloader_exit (place->dlloader_data);
4466     }
4467
4468   LT_DLFREE (place);
4469
4470  done:
4471   LT_DLMUTEX_UNLOCK ();
4472
4473   return errors;
4474 }
4475
4476 lt_dlloader *
4477 lt_dlloader_next (place)
4478      lt_dlloader *place;
4479 {
4480   lt_dlloader *next;
4481
4482   LT_DLMUTEX_LOCK ();
4483   next = place ? place->next : loaders;
4484   LT_DLMUTEX_UNLOCK ();
4485
4486   return next;
4487 }
4488
4489 const char *
4490 lt_dlloader_name (place)
4491      lt_dlloader *place;
4492 {
4493   const char *name = 0;
4494
4495   if (place)
4496     {
4497       LT_DLMUTEX_LOCK ();
4498       name = place ? place->loader_name : 0;
4499       LT_DLMUTEX_UNLOCK ();
4500     }
4501   else
4502     {
4503       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4504     }
4505
4506   return name;
4507 }
4508
4509 lt_user_data *
4510 lt_dlloader_data (place)
4511      lt_dlloader *place;
4512 {
4513   lt_user_data *data = 0;
4514
4515   if (place)
4516     {
4517       LT_DLMUTEX_LOCK ();
4518       data = place ? &(place->dlloader_data) : 0;
4519       LT_DLMUTEX_UNLOCK ();
4520     }
4521   else
4522     {
4523       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4524     }
4525
4526   return data;
4527 }
4528
4529 lt_dlloader *
4530 lt_dlloader_find (loader_name)
4531      const char *loader_name;
4532 {
4533   lt_dlloader *place = 0;
4534
4535   LT_DLMUTEX_LOCK ();
4536   for (place = loaders; place; place = place->next)
4537     {
4538       if (strcmp (place->loader_name, loader_name) == 0)
4539         {
4540           break;
4541         }
4542     }
4543   LT_DLMUTEX_UNLOCK ();
4544
4545   return place;
4546 }