Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/shared_lib/libltdl/ltdl.c @ 7186

Last change on this file since 7186 was 7186, checked in by bensch, 19 years ago

better now

File size: 96.2 KB
Line 
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
6This library is free software; you can redistribute it and/or
7modify it under the terms of the GNU Lesser General Public
8License as published by the Free Software Foundation; either
9version 2 of the License, or (at your option) any later version.
10
11As a special exception to the GNU Lesser General Public License,
12if you distribute this file as part of a program or library that
13is built using GNU libtool, you may include it under the same
14distribution terms that you use for the rest of that program.
15
16This library is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19Lesser General Public License for more details.
20
21You should have received a copy of the GNU Lesser General Public
22License along with this library; if not, write to the Free Software
23Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2402110-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
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
162struct dirent
163{
164  char d_name[2048];
165  int  d_namlen;
166};
167
168typedef 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
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
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.  */
212static char   *lt_estrdup       LT_PARAMS((const char *str));
213static lt_ptr lt_emalloc        LT_PARAMS((size_t size));
214static 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:  */
220LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)    LT_PARAMS((size_t size))
221                        = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
222LT_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;
224LT_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
256/* --- REPLACEMENT FUNCTIONS --- */
257
258
259#undef strdup
260#define strdup rpl_strdup
261
262static char *strdup LT_PARAMS((const char *str));
263
264static char *
265strdup(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
288static int strcmp LT_PARAMS((const char *str1, const char *str2));
289
290static int
291strcmp (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
320static const char *strchr LT_PARAMS((const char *str, int ch));
321
322static const char*
323strchr(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
346static const char *strrchr LT_PARAMS((const char *str, int ch));
347
348static const char*
349strrchr(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
380static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
381
382static lt_ptr
383memcpy (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
406static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
407
408static lt_ptr
409memmove (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
438static void closedir LT_PARAMS((DIR *entry));
439
440static void
441closedir(entry)
442  DIR *entry;
443{
444  assert(entry != (DIR *) NULL);
445  FindClose(entry->hSearch);
446  lt_dlfree((lt_ptr)entry);
447}
448
449
450static DIR * opendir LT_PARAMS((const char *path));
451
452static DIR*
453opendir (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
484static struct dirent *readdir LT_PARAMS((DIR *entry));
485
486static 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
527static lt_ptr
528realloc (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
569static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
570                                        const char *buf, size_t buf_len));
571
572static error_t
573argz_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
611static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
612                                            char **pargz, size_t *pargz_len));
613
614static error_t
615argz_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
674static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
675                                        char *before, const char *entry));
676
677static error_t
678argz_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
731static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
732                                    const char *entry));
733
734static char *
735argz_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
776static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
777                                       int sep));
778
779static void
780argz_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
802/* --- TYPE DEFINITIONS -- */
803
804
805/* This type is used for the array of caller data sets in each handler. */
806typedef struct {
807  lt_dlcaller_id        key;
808  lt_ptr                data;
809} lt_caller_data;
810
811
812
813
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
820static 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. */
830struct 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
841struct 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
866static  const char      objdir[]                = LTDL_OBJDIR;
867static  const char      archive_ext[]           = LTDL_ARCHIVE_EXT;
868#ifdef  LTDL_SHLIB_EXT
869static  const char      shlib_ext[]             = LTDL_SHLIB_EXT;
870#endif
871#ifdef  LTDL_SYSSEARCHPATH
872static  const char      sys_search_path[]       = LTDL_SYSSEARCHPATH;
873#endif
874
875
876
877
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.  */
903static  lt_dlmutex_lock     *lt_dlmutex_lock_func     = 0;
904static  lt_dlmutex_unlock   *lt_dlmutex_unlock_func   = 0;
905static  lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
906static  lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
907static  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.  */
914int
915lt_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
953/* --- ERROR HANDLING --- */
954
955
956static  const char    **user_error_strings      = 0;
957static  int             errorcount              = LT_ERROR_MAX;
958
959int
960lt_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
985int
986lt_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
1015static lt_ptr
1016lt_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
1025static lt_ptr
1026lt_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
1036static char *
1037lt_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
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
1105static lt_module
1106sys_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
1120static int
1121sys_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
1136static lt_ptr
1137sys_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
1152static 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
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
1216static lt_module
1217sys_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
1251static int
1252sys_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
1267static lt_ptr
1268sys_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
1291static 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
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. */
1309static lt_dlhandle handles;
1310
1311static lt_module
1312sys_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
1410static int
1411sys_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
1426static lt_ptr
1427sys_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
1442static 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
1451/* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1452
1453
1454#ifdef __BEOS__
1455
1456/* dynamic linking for BeOS */
1457
1458#include <kernel/image.h>
1459
1460static lt_module
1461sys_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
1488static int
1489sys_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
1504static lt_ptr
1505sys_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
1522static 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
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
1542static lt_module
1543sys_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
1559static int
1560sys_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
1579static lt_ptr
1580sys_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
1595static 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
1630static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
1631static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
1632static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
1633static 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
1664static const char *
1665lt_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
1678static const struct mach_header *
1679lt_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
1699static 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
1724static const struct mach_header *
1725lt_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
1743static NSSymbol
1744lt_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
1788static int
1789sys_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
1805static lt_module
1806sys_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
1842static int
1843sys_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
1886static lt_ptr
1887sys_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
1940static 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
1947/* --- DLPREOPEN() INTERFACE LOADER --- */
1948
1949
1950/* emulate dynamic linking using preloaded_symbols */
1951
1952typedef struct lt_dlsymlists_t
1953{
1954  struct lt_dlsymlists_t       *next;
1955  const lt_dlsymlist           *syms;
1956} lt_dlsymlists_t;
1957
1958static  const lt_dlsymlist     *default_preloaded_symbols       = 0;
1959static  lt_dlsymlists_t        *preloaded_symbols               = 0;
1960
1961static int
1962presym_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
1980static int
1981presym_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
2002static int
2003presym_exit (loader_data)
2004     lt_user_data loader_data;
2005{
2006  presym_free_symlists ();
2007  return 0;
2008}
2009
2010static int
2011presym_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
2048static lt_module
2049presym_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
2098static int
2099presym_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
2108static lt_ptr
2109presym_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
2132static struct lt_user_dlloader presym = {
2133  0, presym_open, presym_close, presym_sym, presym_exit, 0
2134};
2135
2136
2137
2138
2139
2140/* --- DYNAMIC MODULE LOADING --- */
2141
2142
2143/* The type of a function used at each iteration of  foreach_dirinpath().  */
2144typedef int     foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
2145                                                 lt_ptr data2));
2146
2147static  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
2152static  int     find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
2153                                                 lt_ptr ignored));
2154static  int     find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
2155                                                 lt_ptr ignored));
2156static  int     foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
2157                                                 lt_ptr data2));
2158
2159
2160static  int     canonicalize_path     LT_PARAMS((const char *path,
2161                                                 char **pcanonical));
2162static  int     argzize_path          LT_PARAMS((const char *path,
2163                                                 char **pargz,
2164                                                 size_t *pargz_len));
2165static  FILE   *find_file             LT_PARAMS((const char *search_path,
2166                                                 const char *base_name,
2167                                                 char **pdir));
2168static  lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
2169                                                 const char *base_name,
2170                                                 lt_dlhandle *handle));
2171static  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));
2177static  int     free_vars             LT_PARAMS((char *dlname, char *oldname,
2178                                                 char *libdir, char *deplibs));
2179static  int     load_deplibs          LT_PARAMS((lt_dlhandle handle,
2180                                                 char *deplibs));
2181static  int     trim                  LT_PARAMS((char **dest,
2182                                                 const char *str));
2183static  int     try_dlopen            LT_PARAMS((lt_dlhandle *handle,
2184                                                 const char *filename));
2185static  int     tryall_dlopen         LT_PARAMS((lt_dlhandle *handle,
2186                                                 const char *filename));
2187static  int     unload_deplibs        LT_PARAMS((lt_dlhandle handle));
2188static  int     lt_argz_insert        LT_PARAMS((char **pargz,
2189                                                 size_t *pargz_len,
2190                                                 char *before,
2191                                                 const char *entry));
2192static  int     lt_argz_insertinorder LT_PARAMS((char **pargz,
2193                                                 size_t *pargz_len,
2194                                                 const char *entry));
2195static  int     lt_argz_insertdir     LT_PARAMS((char **pargz,
2196                                                 size_t *pargz_len,
2197                                                 const char *dirnam,
2198                                                 struct dirent *dp));
2199static  int     lt_dlpath_insertdir   LT_PARAMS((char **ppath,
2200                                                 char *before,
2201                                                 const char *dir));
2202static  int     list_files_by_dir     LT_PARAMS((const char *dirnam,
2203                                                 char **pargz,
2204                                                 size_t *pargz_len));
2205static  int     file_not_found        LT_PARAMS((void));
2206
2207static  char           *user_search_path= 0;
2208static  lt_dlloader    *loaders         = 0;
2209static  lt_dlhandle     handles         = 0;
2210static  int             initialized     = 0;
2211
2212/* Initialize libltdl. */
2213int
2214lt_dlinit ()
2215{
2216  int         errors   = 0;
2217
2218  LT_DLMUTEX_LOCK ();
2219
2220  /* Initialize only at first call. */
2221  if (++initialized == 1)
2222    {
2223      handles = 0;
2224      user_search_path = 0; /* empty search path */
2225
2226#if HAVE_LIBDL
2227      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
2228#endif
2229#if HAVE_SHL_LOAD
2230      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
2231#endif
2232#ifdef __WINDOWS__
2233      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
2234#endif
2235#ifdef __BEOS__
2236      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
2237#endif
2238#if HAVE_DLD
2239      errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
2240#endif
2241#if HAVE_DYLD
2242       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
2243       errors += sys_dyld_init();
2244#endif
2245      errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
2246
2247      if (presym_init (presym.dlloader_data))
2248        {
2249          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
2250          ++errors;
2251        }
2252      else if (errors != 0)
2253        {
2254          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
2255          ++errors;
2256        }
2257    }
2258
2259  LT_DLMUTEX_UNLOCK ();
2260
2261  return errors;
2262}
2263
2264int
2265lt_dlpreload (preloaded)
2266     const lt_dlsymlist *preloaded;
2267{
2268  int errors = 0;
2269
2270  if (preloaded)
2271    {
2272      errors = presym_add_symlist (preloaded);
2273    }
2274  else
2275    {
2276      presym_free_symlists();
2277
2278      LT_DLMUTEX_LOCK ();
2279      if (default_preloaded_symbols)
2280        {
2281          errors = lt_dlpreload (default_preloaded_symbols);
2282        }
2283      LT_DLMUTEX_UNLOCK ();
2284    }
2285
2286  return errors;
2287}
2288
2289int
2290lt_dlpreload_default (preloaded)
2291     const lt_dlsymlist *preloaded;
2292{
2293  LT_DLMUTEX_LOCK ();
2294  default_preloaded_symbols = preloaded;
2295  LT_DLMUTEX_UNLOCK ();
2296  return 0;
2297}
2298
2299int
2300lt_dlexit ()
2301{
2302  /* shut down libltdl */
2303  lt_dlloader *loader;
2304  int          errors   = 0;
2305
2306  LT_DLMUTEX_LOCK ();
2307  loader = loaders;
2308
2309  if (!initialized)
2310    {
2311      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
2312      ++errors;
2313      goto done;
2314    }
2315
2316  /* shut down only at last call. */
2317  if (--initialized == 0)
2318    {
2319      int       level;
2320
2321      while (handles && LT_DLIS_RESIDENT (handles))
2322        {
2323          handles = handles->next;
2324        }
2325
2326      /* close all modules */
2327      for (level = 1; handles; ++level)
2328        {
2329          lt_dlhandle cur = handles;
2330          int saw_nonresident = 0;
2331
2332          while (cur)
2333            {
2334              lt_dlhandle tmp = cur;
2335              cur = cur->next;
2336              if (!LT_DLIS_RESIDENT (tmp))
2337                saw_nonresident = 1;
2338              if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
2339                {
2340                  if (lt_dlclose (tmp))
2341                    {
2342                      ++errors;
2343                    }
2344                }
2345            }
2346          /* done if only resident modules are left */
2347          if (!saw_nonresident)
2348            break;
2349        }
2350
2351      /* close all loaders */
2352      while (loader)
2353        {
2354          lt_dlloader *next = loader->next;
2355          lt_user_data data = loader->dlloader_data;
2356          if (loader->dlloader_exit && loader->dlloader_exit (data))
2357            {
2358              ++errors;
2359            }
2360
2361          LT_DLMEM_REASSIGN (loader, next);
2362        }
2363      loaders = 0;
2364    }
2365
2366 done:
2367  LT_DLMUTEX_UNLOCK ();
2368  return errors;
2369}
2370
2371static int
2372tryall_dlopen (handle, filename)
2373     lt_dlhandle *handle;
2374     const char *filename;
2375{
2376  lt_dlhandle    cur;
2377  lt_dlloader   *loader;
2378  const char    *saved_error;
2379  int            errors         = 0;
2380
2381  LT_DLMUTEX_GETERROR (saved_error);
2382  LT_DLMUTEX_LOCK ();
2383
2384  cur    = handles;
2385  loader = loaders;
2386
2387  /* check whether the module was already opened */
2388  while (cur)
2389    {
2390      /* try to dlopen the program itself? */
2391      if (!cur->info.filename && !filename)
2392        {
2393          break;
2394        }
2395
2396      if (cur->info.filename && filename
2397          && strcmp (cur->info.filename, filename) == 0)
2398        {
2399          break;
2400        }
2401
2402      cur = cur->next;
2403    }
2404
2405  if (cur)
2406    {
2407      ++cur->info.ref_count;
2408      *handle = cur;
2409      goto done;
2410    }
2411
2412  cur = *handle;
2413  if (filename)
2414    {
2415      /* Comment out the check of file permissions using access.
2416         This call seems to always return -1 with error EACCES.
2417      */
2418      /* We need to catch missing file errors early so that
2419         file_not_found() can detect what happened.
2420      if (access (filename, R_OK) != 0)
2421        {
2422          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2423          ++errors;
2424          goto done;
2425        } */
2426
2427      cur->info.filename = lt_estrdup (filename);
2428      if (!cur->info.filename)
2429        {
2430          ++errors;
2431          goto done;
2432        }
2433    }
2434  else
2435    {
2436      cur->info.filename = 0;
2437    }
2438
2439  while (loader)
2440    {
2441      lt_user_data data = loader->dlloader_data;
2442
2443      cur->module = loader->module_open (data, filename);
2444
2445      if (cur->module != 0)
2446        {
2447          break;
2448        }
2449      loader = loader->next;
2450    }
2451
2452  if (!loader)
2453    {
2454      LT_DLFREE (cur->info.filename);
2455      ++errors;
2456      goto done;
2457    }
2458
2459  cur->loader   = loader;
2460  LT_DLMUTEX_SETERROR (saved_error);
2461
2462 done:
2463  LT_DLMUTEX_UNLOCK ();
2464
2465  return errors;
2466}
2467
2468static int
2469tryall_dlopen_module (handle, prefix, dirname, dlname)
2470     lt_dlhandle *handle;
2471     const char *prefix;
2472     const char *dirname;
2473     const char *dlname;
2474{
2475  int      error        = 0;
2476  char     *filename    = 0;
2477  size_t   filename_len = 0;
2478  size_t   dirname_len  = LT_STRLEN (dirname);
2479
2480  assert (handle);
2481  assert (dirname);
2482  assert (dlname);
2483#ifdef LT_DIRSEP_CHAR
2484  /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2485     should make it into this function:  */
2486  assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
2487#endif
2488
2489  if (dirname_len > 0)
2490    if (dirname[dirname_len -1] == '/')
2491      --dirname_len;
2492  filename_len = dirname_len + 1 + LT_STRLEN (dlname);
2493
2494  /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2495     The PREFIX (if any) is handled below.  */
2496  filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
2497  if (!filename)
2498    return 1;
2499
2500  sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
2501
2502  /* Now that we have combined DIRNAME and MODULENAME, if there is
2503     also a PREFIX to contend with, simply recurse with the arguments
2504     shuffled.  Otherwise, attempt to open FILENAME as a module.  */
2505  if (prefix)
2506    {
2507      error += tryall_dlopen_module (handle,
2508                                     (const char *) 0, prefix, filename);
2509    }
2510  else if (tryall_dlopen (handle, filename) != 0)
2511    {
2512      ++error;
2513    }
2514
2515  LT_DLFREE (filename);
2516  return error;
2517}
2518
2519static int
2520find_module (handle, dir, libdir, dlname, old_name, installed)
2521     lt_dlhandle *handle;
2522     const char *dir;
2523     const char *libdir;
2524     const char *dlname;
2525     const char *old_name;
2526     int installed;
2527{
2528  /* Try to open the old library first; if it was dlpreopened,
2529     we want the preopened version of it, even if a dlopenable
2530     module is available.  */
2531  if (old_name && tryall_dlopen (handle, old_name) == 0)
2532    {
2533      return 0;
2534    }
2535
2536  /* Try to open the dynamic library.  */
2537  if (dlname)
2538    {
2539      /* try to open the installed module */
2540      if (installed && libdir)
2541        {
2542          if (tryall_dlopen_module (handle,
2543                                    (const char *) 0, libdir, dlname) == 0)
2544            return 0;
2545        }
2546
2547      /* try to open the not-installed module */
2548      if (!installed)
2549        {
2550          if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2551            return 0;
2552        }
2553
2554      /* maybe it was moved to another directory */
2555      {
2556          if (dir && (tryall_dlopen_module (handle,
2557                                    (const char *) 0, dir, dlname) == 0))
2558            return 0;
2559      }
2560    }
2561
2562  return 1;
2563}
2564
2565
2566static int
2567canonicalize_path (path, pcanonical)
2568     const char *path;
2569     char **pcanonical;
2570{
2571  char *canonical = 0;
2572
2573  assert (path && *path);
2574  assert (pcanonical);
2575
2576  canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2577  if (!canonical)
2578    return 1;
2579
2580  {
2581    size_t dest = 0;
2582    size_t src;
2583    for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2584      {
2585        /* Path separators are not copied to the beginning or end of
2586           the destination, or if another separator would follow
2587           immediately.  */
2588        if (path[src] == LT_PATHSEP_CHAR)
2589          {
2590            if ((dest == 0)
2591                || (path[1+ src] == LT_PATHSEP_CHAR)
2592                || (path[1+ src] == LT_EOS_CHAR))
2593              continue;
2594          }
2595
2596        /* Anything other than a directory separator is copied verbatim.  */
2597        if ((path[src] != '/')
2598#ifdef LT_DIRSEP_CHAR
2599            && (path[src] != LT_DIRSEP_CHAR)
2600#endif
2601            )
2602          {
2603            canonical[dest++] = path[src];
2604          }
2605        /* Directory separators are converted and copied only if they are
2606           not at the end of a path -- i.e. before a path separator or
2607           NULL terminator.  */
2608        else if ((path[1+ src] != LT_PATHSEP_CHAR)
2609                 && (path[1+ src] != LT_EOS_CHAR)
2610#ifdef LT_DIRSEP_CHAR
2611                 && (path[1+ src] != LT_DIRSEP_CHAR)
2612#endif
2613                 && (path[1+ src] != '/'))
2614          {
2615            canonical[dest++] = '/';
2616          }
2617      }
2618
2619    /* Add an end-of-string marker at the end.  */
2620    canonical[dest] = LT_EOS_CHAR;
2621  }
2622
2623  /* Assign new value.  */
2624  *pcanonical = canonical;
2625
2626  return 0;
2627}
2628
2629static int
2630argzize_path (path, pargz, pargz_len)
2631     const char *path;
2632     char **pargz;
2633     size_t *pargz_len;
2634{
2635  error_t error;
2636
2637  assert (path);
2638  assert (pargz);
2639  assert (pargz_len);
2640
2641  if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2642    {
2643      switch (error)
2644        {
2645        case ENOMEM:
2646          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2647          break;
2648        default:
2649          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2650          break;
2651        }
2652
2653      return 1;
2654    }
2655
2656  return 0;
2657}
2658
2659/* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2660   of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2661   non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
2662   it is appended to each SEARCH_PATH element before FUNC is called.  */
2663static int
2664foreach_dirinpath (search_path, base_name, func, data1, data2)
2665     const char *search_path;
2666     const char *base_name;
2667     foreach_callback_func *func;
2668     lt_ptr data1;
2669     lt_ptr data2;
2670{
2671  int    result         = 0;
2672  int    filenamesize   = 0;
2673  size_t lenbase        = LT_STRLEN (base_name);
2674  size_t argz_len       = 0;
2675  char *argz            = 0;
2676  char *filename        = 0;
2677  char *canonical       = 0;
2678
2679  LT_DLMUTEX_LOCK ();
2680
2681  if (!search_path || !*search_path)
2682    {
2683      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2684      goto cleanup;
2685    }
2686
2687  if (canonicalize_path (search_path, &canonical) != 0)
2688    goto cleanup;
2689
2690  if (argzize_path (canonical, &argz, &argz_len) != 0)
2691    goto cleanup;
2692
2693  {
2694    char *dir_name = 0;
2695    while ((dir_name = argz_next (argz, argz_len, dir_name)))
2696      {
2697        size_t lendir = LT_STRLEN (dir_name);
2698
2699        if (lendir +1 +lenbase >= filenamesize)
2700        {
2701          LT_DLFREE (filename);
2702          filenamesize  = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2703          filename      = LT_EMALLOC (char, filenamesize);
2704          if (!filename)
2705            goto cleanup;
2706        }
2707
2708        assert (filenamesize > lendir);
2709        strcpy (filename, dir_name);
2710
2711        if (base_name && *base_name)
2712          {
2713            if (filename[lendir -1] != '/')
2714              filename[lendir++] = '/';
2715            strcpy (filename +lendir, base_name);
2716          }
2717
2718        if ((result = (*func) (filename, data1, data2)))
2719          {
2720            break;
2721          }
2722      }
2723  }
2724
2725 cleanup:
2726  LT_DLFREE (argz);
2727  LT_DLFREE (canonical);
2728  LT_DLFREE (filename);
2729
2730  LT_DLMUTEX_UNLOCK ();
2731
2732  return result;
2733}
2734
2735/* If FILEPATH can be opened, store the name of the directory component
2736   in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
2737   DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
2738static int
2739find_file_callback (filename, data1, data2)
2740     char *filename;
2741     lt_ptr data1;
2742     lt_ptr data2;
2743{
2744  char       **pdir     = (char **) data1;
2745  FILE       **pfile    = (FILE **) data2;
2746  int        is_done    = 0;
2747
2748  assert (filename && *filename);
2749  assert (pdir);
2750  assert (pfile);
2751
2752  if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2753    {
2754      char *dirend = strrchr (filename, '/');
2755
2756      if (dirend > filename)
2757        *dirend   = LT_EOS_CHAR;
2758
2759      LT_DLFREE (*pdir);
2760      *pdir   = lt_estrdup (filename);
2761      is_done = (*pdir == 0) ? -1 : 1;
2762    }
2763
2764  return is_done;
2765}
2766
2767static FILE *
2768find_file (search_path, base_name, pdir)
2769     const char *search_path;
2770     const char *base_name;
2771     char **pdir;
2772{
2773  FILE *file = 0;
2774
2775  foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2776
2777  return file;
2778}
2779
2780static int
2781find_handle_callback (filename, data, ignored)
2782     char *filename;
2783     lt_ptr data;
2784     lt_ptr ignored;
2785{
2786  lt_dlhandle  *handle          = (lt_dlhandle *) data;
2787  int           notfound        = access (filename, R_OK);
2788
2789  /* Bail out if file cannot be read...  */
2790  if (notfound)
2791    return 0;
2792
2793  /* Try to dlopen the file, but do not continue searching in any
2794     case.  */
2795  if (tryall_dlopen (handle, filename) != 0)
2796    *handle = 0;
2797
2798  return 1;
2799}
2800
2801/* If HANDLE was found return it, otherwise return 0.  If HANDLE was
2802   found but could not be opened, *HANDLE will be set to 0.  */
2803static lt_dlhandle *
2804find_handle (search_path, base_name, handle)
2805     const char *search_path;
2806     const char *base_name;
2807     lt_dlhandle *handle;
2808{
2809  if (!search_path)
2810    return 0;
2811
2812  if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2813                          handle, 0))
2814    return 0;
2815
2816  return handle;
2817}
2818
2819static int
2820load_deplibs (handle, deplibs)
2821     lt_dlhandle handle;
2822     char *deplibs;
2823{
2824#if LTDL_DLOPEN_DEPLIBS
2825  char  *p, *save_search_path = 0;
2826  int   depcount = 0;
2827  int   i;
2828  char  **names = 0;
2829#endif
2830  int   errors = 0;
2831
2832  handle->depcount = 0;
2833
2834#if LTDL_DLOPEN_DEPLIBS
2835  if (!deplibs)
2836    {
2837      return errors;
2838    }
2839  ++errors;
2840
2841  LT_DLMUTEX_LOCK ();
2842  if (user_search_path)
2843    {
2844      save_search_path = lt_estrdup (user_search_path);
2845      if (!save_search_path)
2846        goto cleanup;
2847    }
2848
2849  /* extract search paths and count deplibs */
2850  p = deplibs;
2851  while (*p)
2852    {
2853      if (!isspace ((int) *p))
2854        {
2855          char *end = p+1;
2856          while (*end && !isspace((int) *end))
2857            {
2858              ++end;
2859            }
2860
2861          if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2862            {
2863              char save = *end;
2864              *end = 0; /* set a temporary string terminator */
2865              if (lt_dladdsearchdir(p+2))
2866                {
2867                  goto cleanup;
2868                }
2869              *end = save;
2870            }
2871          else
2872            {
2873              ++depcount;
2874            }
2875
2876          p = end;
2877        }
2878      else
2879        {
2880          ++p;
2881        }
2882    }
2883
2884  if (!depcount)
2885    {
2886      errors = 0;
2887      goto cleanup;
2888    }
2889
2890  names = LT_EMALLOC (char *, depcount * sizeof (char*));
2891  if (!names)
2892    goto cleanup;
2893
2894  /* now only extract the actual deplibs */
2895  depcount = 0;
2896  p = deplibs;
2897  while (*p)
2898    {
2899      if (isspace ((int) *p))
2900        {
2901          ++p;
2902        }
2903      else
2904        {
2905          char *end = p+1;
2906          while (*end && !isspace ((int) *end))
2907            {
2908              ++end;
2909            }
2910
2911          if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2912            {
2913              char *name;
2914              char save = *end;
2915              *end = 0; /* set a temporary string terminator */
2916              if (strncmp(p, "-l", 2) == 0)
2917                {
2918                  size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2919                  name = LT_EMALLOC (char, 1+ name_len);
2920                  if (name)
2921                    sprintf (name, "lib%s", p+2);
2922                }
2923              else
2924                name = lt_estrdup(p);
2925
2926              if (!name)
2927                goto cleanup_names;
2928
2929              names[depcount++] = name;
2930              *end = save;
2931            }
2932          p = end;
2933        }
2934    }
2935
2936  /* load the deplibs (in reverse order)
2937     At this stage, don't worry if the deplibs do not load correctly,
2938     they may already be statically linked into the loading application
2939     for instance.  There will be a more enlightening error message
2940     later on if the loaded module cannot resolve all of its symbols.  */
2941  if (depcount)
2942    {
2943      int       j = 0;
2944
2945      handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2946      if (!handle->deplibs)
2947        goto cleanup;
2948
2949      for (i = 0; i < depcount; ++i)
2950        {
2951          handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2952          if (handle->deplibs[j])
2953            {
2954              ++j;
2955            }
2956        }
2957
2958      handle->depcount  = j;    /* Number of successfully loaded deplibs */
2959      errors            = 0;
2960    }
2961
2962 cleanup_names:
2963  for (i = 0; i < depcount; ++i)
2964    {
2965      LT_DLFREE (names[i]);
2966    }
2967
2968 cleanup:
2969  LT_DLFREE (names);
2970  /* restore the old search path */
2971  if (user_search_path) {
2972    LT_DLFREE (user_search_path);
2973    user_search_path = save_search_path;
2974  }
2975  LT_DLMUTEX_UNLOCK ();
2976
2977#endif
2978
2979  return errors;
2980}
2981
2982static int
2983unload_deplibs (handle)
2984     lt_dlhandle handle;
2985{
2986  int i;
2987  int errors = 0;
2988
2989  if (handle->depcount)
2990    {
2991      for (i = 0; i < handle->depcount; ++i)
2992        {
2993          if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
2994            {
2995              errors += lt_dlclose (handle->deplibs[i]);
2996            }
2997        }
2998    }
2999
3000  return errors;
3001}
3002
3003static int
3004trim (dest, str)
3005     char **dest;
3006     const char *str;
3007{
3008  /* remove the leading and trailing "'" from str
3009     and store the result in dest */
3010  const char *end   = strrchr (str, '\'');
3011  size_t len        = LT_STRLEN (str);
3012  char *tmp;
3013
3014  LT_DLFREE (*dest);
3015
3016  if (!end)
3017    return 1;
3018
3019  if (len > 3 && str[0] == '\'')
3020    {
3021      tmp = LT_EMALLOC (char, end - str);
3022      if (!tmp)
3023        return 1;
3024
3025      strncpy(tmp, &str[1], (end - str) - 1);
3026      tmp[len-3] = LT_EOS_CHAR;
3027      *dest = tmp;
3028    }
3029  else
3030    {
3031      *dest = 0;
3032    }
3033
3034  return 0;
3035}
3036
3037static int
3038free_vars (dlname, oldname, libdir, deplibs)
3039     char *dlname;
3040     char *oldname;
3041     char *libdir;
3042     char *deplibs;
3043{
3044  LT_DLFREE (dlname);
3045  LT_DLFREE (oldname);
3046  LT_DLFREE (libdir);
3047  LT_DLFREE (deplibs);
3048
3049  return 0;
3050}
3051
3052static int
3053try_dlopen (phandle, filename)
3054     lt_dlhandle *phandle;
3055     const char *filename;
3056{
3057  const char *  ext             = 0;
3058  const char *  saved_error     = 0;
3059  char *        canonical       = 0;
3060  char *        base_name       = 0;
3061  char *        dir             = 0;
3062  char *        name            = 0;
3063  int           errors          = 0;
3064  lt_dlhandle   newhandle;
3065
3066  assert (phandle);
3067  assert (*phandle == 0);
3068
3069  LT_DLMUTEX_GETERROR (saved_error);
3070
3071  /* dlopen self? */
3072  if (!filename)
3073    {
3074      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3075      if (*phandle == 0)
3076        return 1;
3077
3078      memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3079      newhandle = *phandle;
3080
3081      /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
3082      LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
3083
3084      if (tryall_dlopen (&newhandle, 0) != 0)
3085        {
3086          LT_DLFREE (*phandle);
3087          return 1;
3088        }
3089
3090      goto register_handle;
3091    }
3092
3093  assert (filename && *filename);
3094
3095  /* Doing this immediately allows internal functions to safely
3096     assume only canonicalized paths are passed.  */
3097  if (canonicalize_path (filename, &canonical) != 0)
3098    {
3099      ++errors;
3100      goto cleanup;
3101    }
3102
3103  /* If the canonical module name is a path (relative or absolute)
3104     then split it into a directory part and a name part.  */
3105  base_name = strrchr (canonical, '/');
3106  if (base_name)
3107    {
3108      size_t dirlen = (1+ base_name) - canonical;
3109
3110      dir = LT_EMALLOC (char, 1+ dirlen);
3111      if (!dir)
3112        {
3113          ++errors;
3114          goto cleanup;
3115        }
3116
3117      strncpy (dir, canonical, dirlen);
3118      dir[dirlen] = LT_EOS_CHAR;
3119
3120      ++base_name;
3121    }
3122  else
3123    base_name = canonical;
3124
3125  assert (base_name && *base_name);
3126
3127  /* Check whether we are opening a libtool module (.la extension).  */
3128  ext = strrchr (base_name, '.');
3129  if (ext && strcmp (ext, archive_ext) == 0)
3130    {
3131      /* this seems to be a libtool module */
3132      FILE *    file     = 0;
3133      char *    dlname   = 0;
3134      char *    old_name = 0;
3135      char *    libdir   = 0;
3136      char *    deplibs  = 0;
3137      char *    line     = 0;
3138      size_t    line_len;
3139
3140      /* if we can't find the installed flag, it is probably an
3141         installed libtool archive, produced with an old version
3142         of libtool */
3143      int       installed = 1;
3144
3145      /* extract the module name from the file name */
3146      name = LT_EMALLOC (char, ext - base_name + 1);
3147      if (!name)
3148        {
3149          ++errors;
3150          goto cleanup;
3151        }
3152
3153      /* canonicalize the module name */
3154      {
3155        size_t i;
3156        for (i = 0; i < ext - base_name; ++i)
3157          {
3158            if (isalnum ((int)(base_name[i])))
3159              {
3160                name[i] = base_name[i];
3161              }
3162            else
3163              {
3164                name[i] = '_';
3165              }
3166          }
3167        name[ext - base_name] = LT_EOS_CHAR;
3168      }
3169
3170      /* Now try to open the .la file.  If there is no directory name
3171         component, try to find it first in user_search_path and then other
3172         prescribed paths.  Otherwise (or in any case if the module was not
3173         yet found) try opening just the module name as passed.  */
3174      if (!dir)
3175        {
3176          const char *search_path;
3177
3178          LT_DLMUTEX_LOCK ();
3179          search_path = user_search_path;
3180          if (search_path)
3181            file = find_file (user_search_path, base_name, &dir);
3182          LT_DLMUTEX_UNLOCK ();
3183
3184          if (!file)
3185            {
3186              search_path = getenv (LTDL_SEARCHPATH_VAR);
3187              if (search_path)
3188                file = find_file (search_path, base_name, &dir);
3189            }
3190
3191#ifdef LTDL_SHLIBPATH_VAR
3192          if (!file)
3193            {
3194              search_path = getenv (LTDL_SHLIBPATH_VAR);
3195              if (search_path)
3196                file = find_file (search_path, base_name, &dir);
3197            }
3198#endif
3199#ifdef LTDL_SYSSEARCHPATH
3200          if (!file && sys_search_path)
3201            {
3202              file = find_file (sys_search_path, base_name, &dir);
3203            }
3204#endif
3205        }
3206      if (!file)
3207        {
3208          file = fopen (filename, LT_READTEXT_MODE);
3209        }
3210
3211      /* If we didn't find the file by now, it really isn't there.  Set
3212         the status flag, and bail out.  */
3213      if (!file)
3214        {
3215          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3216          ++errors;
3217          goto cleanup;
3218        }
3219
3220      line_len = LT_FILENAME_MAX;
3221      line = LT_EMALLOC (char, line_len);
3222      if (!line)
3223        {
3224          fclose (file);
3225          ++errors;
3226          goto cleanup;
3227        }
3228
3229      /* read the .la file */
3230      while (!feof (file))
3231        {
3232          if (!fgets (line, (int) line_len, file))
3233            {
3234              break;
3235            }
3236
3237          /* Handle the case where we occasionally need to read a line
3238             that is longer than the initial buffer size.  */
3239          while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
3240            {
3241              line = LT_DLREALLOC (char, line, line_len *2);
3242              if (!fgets (&line[line_len -1], (int) line_len +1, file))
3243                {
3244                  break;
3245                }
3246              line_len *= 2;
3247            }
3248
3249          if (line[0] == '\n' || line[0] == '#')
3250            {
3251              continue;
3252            }
3253
3254#undef  STR_DLNAME
3255#define STR_DLNAME      "dlname="
3256          if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
3257            {
3258              errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
3259            }
3260
3261#undef  STR_OLD_LIBRARY
3262#define STR_OLD_LIBRARY "old_library="
3263          else if (strncmp (line, STR_OLD_LIBRARY,
3264                            sizeof (STR_OLD_LIBRARY) - 1) == 0)
3265            {
3266              errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
3267            }
3268#undef  STR_LIBDIR
3269#define STR_LIBDIR      "libdir="
3270          else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
3271            {
3272              errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
3273            }
3274
3275#undef  STR_DL_DEPLIBS
3276#define STR_DL_DEPLIBS  "dependency_libs="
3277          else if (strncmp (line, STR_DL_DEPLIBS,
3278                            sizeof (STR_DL_DEPLIBS) - 1) == 0)
3279            {
3280              errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
3281            }
3282          else if (strcmp (line, "installed=yes\n") == 0)
3283            {
3284              installed = 1;
3285            }
3286          else if (strcmp (line, "installed=no\n") == 0)
3287            {
3288              installed = 0;
3289            }
3290
3291#undef  STR_LIBRARY_NAMES
3292#define STR_LIBRARY_NAMES "library_names="
3293          else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
3294                                        sizeof (STR_LIBRARY_NAMES) - 1) == 0)
3295            {
3296              char *last_libname;
3297              errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
3298              if (!errors
3299                  && dlname
3300                  && (last_libname = strrchr (dlname, ' ')) != 0)
3301                {
3302                  last_libname = lt_estrdup (last_libname + 1);
3303                  if (!last_libname)
3304                    {
3305                      ++errors;
3306                      goto cleanup;
3307                    }
3308                  LT_DLMEM_REASSIGN (dlname, last_libname);
3309                }
3310            }
3311
3312          if (errors)
3313            break;
3314        }
3315
3316      fclose (file);
3317      LT_DLFREE (line);
3318
3319      /* allocate the handle */
3320      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3321      if (*phandle == 0)
3322        ++errors;
3323
3324      if (errors)
3325        {
3326          free_vars (dlname, old_name, libdir, deplibs);
3327          LT_DLFREE (*phandle);
3328          goto cleanup;
3329        }
3330
3331      assert (*phandle);
3332
3333      memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3334      if (load_deplibs (*phandle, deplibs) == 0)
3335        {
3336          newhandle = *phandle;
3337          /* find_module may replace newhandle */
3338          if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
3339            {
3340              unload_deplibs (*phandle);
3341              ++errors;
3342            }
3343        }
3344      else
3345        {
3346          ++errors;
3347        }
3348
3349      free_vars (dlname, old_name, libdir, deplibs);
3350      if (errors)
3351        {
3352          LT_DLFREE (*phandle);
3353          goto cleanup;
3354        }
3355
3356      if (*phandle != newhandle)
3357        {
3358          unload_deplibs (*phandle);
3359        }
3360    }
3361  else
3362    {
3363      /* not a libtool module */
3364      *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3365      if (*phandle == 0)
3366        {
3367          ++errors;
3368          goto cleanup;
3369        }
3370
3371      memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
3372      newhandle = *phandle;
3373
3374      /* If the module has no directory name component, try to find it
3375         first in user_search_path and then other prescribed paths.
3376         Otherwise (or in any case if the module was not yet found) try
3377         opening just the module name as passed.  */
3378      if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
3379                   && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
3380                                    &newhandle)
3381#ifdef LTDL_SHLIBPATH_VAR
3382                   && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
3383                                    &newhandle)
3384#endif
3385#ifdef LTDL_SYSSEARCHPATH
3386                   && !find_handle (sys_search_path, base_name, &newhandle)
3387#endif
3388                   )))
3389        {
3390          if (tryall_dlopen (&newhandle, filename) != 0)
3391            {
3392              newhandle = NULL;
3393            }
3394        }
3395
3396      if (!newhandle)
3397        {
3398          LT_DLFREE (*phandle);
3399          ++errors;
3400          goto cleanup;
3401        }
3402    }
3403
3404 register_handle:
3405  LT_DLMEM_REASSIGN (*phandle, newhandle);
3406
3407  if ((*phandle)->info.ref_count == 0)
3408    {
3409      (*phandle)->info.ref_count        = 1;
3410      LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
3411
3412      LT_DLMUTEX_LOCK ();
3413      (*phandle)->next          = handles;
3414      handles                   = *phandle;
3415      LT_DLMUTEX_UNLOCK ();
3416    }
3417
3418  LT_DLMUTEX_SETERROR (saved_error);
3419
3420 cleanup:
3421  LT_DLFREE (dir);
3422  LT_DLFREE (name);
3423  LT_DLFREE (canonical);
3424
3425  return errors;
3426}
3427
3428lt_dlhandle
3429lt_dlopen (filename)
3430     const char *filename;
3431{
3432  lt_dlhandle handle = 0;
3433
3434  /* Just incase we missed a code path in try_dlopen() that reports
3435     an error, but forgets to reset handle... */
3436  if (try_dlopen (&handle, filename) != 0)
3437    return 0;
3438
3439  return handle;
3440}
3441
3442/* If the last error messge store was `FILE_NOT_FOUND', then return
3443   non-zero.  */
3444static int
3445file_not_found ()
3446{
3447  const char *error = 0;
3448
3449  LT_DLMUTEX_GETERROR (error);
3450  if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
3451    return 1;
3452
3453  return 0;
3454}
3455
3456/* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3457   open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
3458   and if a file is still not found try again with SHLIB_EXT appended
3459   instead.  */
3460lt_dlhandle
3461lt_dlopenext (filename)
3462     const char *filename;
3463{
3464  lt_dlhandle   handle          = 0;
3465  char *        tmp             = 0;
3466  char *        ext             = 0;
3467  size_t        len;
3468  int           errors          = 0;
3469
3470  if (!filename)
3471    {
3472      return lt_dlopen (filename);
3473    }
3474
3475  assert (filename);
3476
3477  len = LT_STRLEN (filename);
3478  ext = strrchr (filename, '.');
3479
3480  /* If FILENAME already bears a suitable extension, there is no need
3481     to try appending additional extensions.  */
3482  if (ext && ((strcmp (ext, archive_ext) == 0)
3483#ifdef LTDL_SHLIB_EXT
3484              || (strcmp (ext, shlib_ext) == 0)
3485#endif
3486      ))
3487    {
3488      return lt_dlopen (filename);
3489    }
3490
3491  /* First try appending ARCHIVE_EXT.  */
3492  tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
3493  if (!tmp)
3494    return 0;
3495
3496  strcpy (tmp, filename);
3497  strcat (tmp, archive_ext);
3498  errors = try_dlopen (&handle, tmp);
3499
3500  /* If we found FILENAME, stop searching -- whether we were able to
3501     load the file as a module or not.  If the file exists but loading
3502     failed, it is better to return an error message here than to
3503     report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3504     in the module search path.  */
3505  if (handle || ((errors > 0) && !file_not_found ()))
3506    {
3507      LT_DLFREE (tmp);
3508      return handle;
3509    }
3510
3511#ifdef LTDL_SHLIB_EXT
3512  /* Try appending SHLIB_EXT.   */
3513  if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
3514    {
3515      LT_DLFREE (tmp);
3516      tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3517      if (!tmp)
3518        return 0;
3519
3520      strcpy (tmp, filename);
3521    }
3522  else
3523    {
3524      tmp[len] = LT_EOS_CHAR;
3525    }
3526
3527  strcat(tmp, shlib_ext);
3528  errors = try_dlopen (&handle, tmp);
3529
3530  /* As before, if the file was found but loading failed, return now
3531     with the current error message.  */
3532  if (handle || ((errors > 0) && !file_not_found ()))
3533    {
3534      LT_DLFREE (tmp);
3535      return handle;
3536    }
3537#endif
3538
3539  /* Still here?  Then we really did fail to locate any of the file
3540     names we tried.  */
3541  LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3542  LT_DLFREE (tmp);
3543  return 0;
3544}
3545
3546
3547static int
3548lt_argz_insert (pargz, pargz_len, before, entry)
3549     char **pargz;
3550     size_t *pargz_len;
3551     char *before;
3552     const char *entry;
3553{
3554  error_t error;
3555
3556  /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
3557     pargz_len, NULL, entry) failed with EINVAL.  */
3558  if (before)
3559    error = argz_insert (pargz, pargz_len, before, entry);
3560  else
3561    error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
3562
3563  if (error)
3564    {
3565      switch (error)
3566        {
3567        case ENOMEM:
3568          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3569          break;
3570        default:
3571          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3572          break;
3573        }
3574      return 1;
3575    }
3576
3577  return 0;
3578}
3579
3580static int
3581lt_argz_insertinorder (pargz, pargz_len, entry)
3582     char **pargz;
3583     size_t *pargz_len;
3584     const char *entry;
3585{
3586  char *before = 0;
3587
3588  assert (pargz);
3589  assert (pargz_len);
3590  assert (entry && *entry);
3591
3592  if (*pargz)
3593    while ((before = argz_next (*pargz, *pargz_len, before)))
3594      {
3595        int cmp = strcmp (entry, before);
3596
3597        if (cmp < 0)  break;
3598        if (cmp == 0) return 0; /* No duplicates! */
3599      }
3600
3601  return lt_argz_insert (pargz, pargz_len, before, entry);
3602}
3603
3604static int
3605lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3606     char **pargz;
3607     size_t *pargz_len;
3608     const char *dirnam;
3609     struct dirent *dp;
3610{
3611  char   *buf       = 0;
3612  size_t buf_len    = 0;
3613  char   *end       = 0;
3614  size_t end_offset = 0;
3615  size_t dir_len    = 0;
3616  int    errors     = 0;
3617
3618  assert (pargz);
3619  assert (pargz_len);
3620  assert (dp);
3621
3622  dir_len = LT_STRLEN (dirnam);
3623  end     = dp->d_name + LT_D_NAMLEN(dp);
3624
3625  /* Ignore version numbers.  */
3626  {
3627    char *p;
3628    for (p = end; p -1 > dp->d_name; --p)
3629      if (strchr (".0123456789", p[-1]) == 0)
3630        break;
3631
3632    if (*p == '.')
3633      end = p;
3634  }
3635
3636  /* Ignore filename extension.  */
3637  {
3638    char *p;
3639    for (p = end -1; p > dp->d_name; --p)
3640      if (*p == '.')
3641        {
3642          end = p;
3643          break;
3644        }
3645  }
3646
3647  /* Prepend the directory name.  */
3648  end_offset    = end - dp->d_name;
3649  buf_len       = dir_len + 1+ end_offset;
3650  buf           = LT_EMALLOC (char, 1+ buf_len);
3651  if (!buf)
3652    return ++errors;
3653
3654  assert (buf);
3655
3656  strcpy  (buf, dirnam);
3657  strcat  (buf, "/");
3658  strncat (buf, dp->d_name, end_offset);
3659  buf[buf_len] = LT_EOS_CHAR;
3660
3661  /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
3662  if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3663    ++errors;
3664
3665  LT_DLFREE (buf);
3666
3667  return errors;
3668}
3669
3670static int
3671list_files_by_dir (dirnam, pargz, pargz_len)
3672     const char *dirnam;
3673     char **pargz;
3674     size_t *pargz_len;
3675{
3676  DIR   *dirp     = 0;
3677  int    errors   = 0;
3678
3679  assert (dirnam && *dirnam);
3680  assert (pargz);
3681  assert (pargz_len);
3682  assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3683
3684  dirp = opendir (dirnam);
3685  if (dirp)
3686    {
3687      struct dirent *dp = 0;
3688
3689      while ((dp = readdir (dirp)))
3690        if (dp->d_name[0] != '.')
3691          if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3692            {
3693              ++errors;
3694              break;
3695            }
3696
3697      closedir (dirp);
3698    }
3699  else
3700    ++errors;
3701
3702  return errors;
3703}
3704
3705
3706/* If there are any files in DIRNAME, call the function passed in
3707   DATA1 (with the name of each file and DATA2 as arguments).  */
3708static int
3709foreachfile_callback (dirname, data1, data2)
3710     char *dirname;
3711     lt_ptr data1;
3712     lt_ptr data2;
3713{
3714  int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3715        = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3716
3717  int     is_done  = 0;
3718  char   *argz     = 0;
3719  size_t  argz_len = 0;
3720
3721  if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3722    goto cleanup;
3723  if (!argz)
3724    goto cleanup;
3725
3726  {
3727    char *filename = 0;
3728    while ((filename = argz_next (argz, argz_len, filename)))
3729      if ((is_done = (*func) (filename, data2)))
3730        break;
3731  }
3732
3733 cleanup:
3734  LT_DLFREE (argz);
3735
3736  return is_done;
3737}
3738
3739
3740/* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3741   with DATA.  The filenames passed to FUNC would be suitable for
3742   passing to lt_dlopenext.  The extensions are stripped so that
3743   individual modules do not generate several entries (e.g. libfoo.la,
3744   libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
3745   then the same directories that lt_dlopen would search are examined.  */
3746int
3747lt_dlforeachfile (search_path, func, data)
3748     const char *search_path;
3749     int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3750     lt_ptr data;
3751{
3752  int is_done = 0;
3753
3754  if (search_path)
3755    {
3756      /* If a specific path was passed, search only the directories
3757         listed in it.  */
3758      is_done = foreach_dirinpath (search_path, 0,
3759                                   foreachfile_callback, func, data);
3760    }
3761  else
3762    {
3763      /* Otherwise search the default paths.  */
3764      is_done = foreach_dirinpath (user_search_path, 0,
3765                                   foreachfile_callback, func, data);
3766      if (!is_done)
3767        {
3768          is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3769                                       foreachfile_callback, func, data);
3770        }
3771
3772#ifdef LTDL_SHLIBPATH_VAR
3773      if (!is_done)
3774        {
3775          is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3776                                       foreachfile_callback, func, data);
3777        }
3778#endif
3779#ifdef LTDL_SYSSEARCHPATH
3780      if (!is_done)
3781        {
3782          is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3783                                       foreachfile_callback, func, data);
3784        }
3785#endif
3786    }
3787
3788  return is_done;
3789}
3790
3791int
3792lt_dlclose (handle)
3793     lt_dlhandle handle;
3794{
3795  lt_dlhandle cur, last;
3796  int errors = 0;
3797
3798  LT_DLMUTEX_LOCK ();
3799
3800  /* check whether the handle is valid */
3801  last = cur = handles;
3802  while (cur && handle != cur)
3803    {
3804      last = cur;
3805      cur = cur->next;
3806    }
3807
3808  if (!cur)
3809    {
3810      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3811      ++errors;
3812      goto done;
3813    }
3814
3815  handle->info.ref_count--;
3816
3817  /* Note that even with resident modules, we must track the ref_count
3818     correctly incase the user decides to reset the residency flag
3819     later (even though the API makes no provision for that at the
3820     moment).  */
3821  if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3822    {
3823      lt_user_data data = handle->loader->dlloader_data;
3824
3825      if (handle != handles)
3826        {
3827          last->next = handle->next;
3828        }
3829      else
3830        {
3831          handles = handle->next;
3832        }
3833
3834      errors += handle->loader->module_close (data, handle->module);
3835      errors += unload_deplibs(handle);
3836
3837      /* It is up to the callers to free the data itself.  */
3838      LT_DLFREE (handle->caller_data);
3839
3840      LT_DLFREE (handle->info.filename);
3841      LT_DLFREE (handle->info.name);
3842      LT_DLFREE (handle);
3843
3844      goto done;
3845    }
3846
3847  if (LT_DLIS_RESIDENT (handle))
3848    {
3849      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3850      ++errors;
3851    }
3852
3853 done:
3854  LT_DLMUTEX_UNLOCK ();
3855
3856  return errors;
3857}
3858
3859lt_ptr
3860lt_dlsym (handle, symbol)
3861     lt_dlhandle handle;
3862     const char *symbol;
3863{
3864  size_t lensym;
3865  char  lsym[LT_SYMBOL_LENGTH];
3866  char  *sym;
3867  lt_ptr address;
3868  lt_user_data data;
3869
3870  if (!handle)
3871    {
3872      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3873      return 0;
3874    }
3875
3876  if (!symbol)
3877    {
3878      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3879      return 0;
3880    }
3881
3882  lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3883                                        + LT_STRLEN (handle->info.name);
3884
3885  if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3886    {
3887      sym = lsym;
3888    }
3889  else
3890    {
3891      sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3892      if (!sym)
3893        {
3894          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3895          return 0;
3896        }
3897    }
3898
3899  data = handle->loader->dlloader_data;
3900  if (handle->info.name)
3901    {
3902      const char *saved_error;
3903
3904      LT_DLMUTEX_GETERROR (saved_error);
3905
3906      /* this is a libtool module */
3907      if (handle->loader->sym_prefix)
3908        {
3909          strcpy(sym, handle->loader->sym_prefix);
3910          strcat(sym, handle->info.name);
3911        }
3912      else
3913        {
3914          strcpy(sym, handle->info.name);
3915        }
3916
3917      strcat(sym, "_LTX_");
3918      strcat(sym, symbol);
3919
3920      /* try "modulename_LTX_symbol" */
3921      address = handle->loader->find_sym (data, handle->module, sym);
3922      if (address)
3923        {
3924          if (sym != lsym)
3925            {
3926              LT_DLFREE (sym);
3927            }
3928          return address;
3929        }
3930      LT_DLMUTEX_SETERROR (saved_error);
3931    }
3932
3933  /* otherwise try "symbol" */
3934  if (handle->loader->sym_prefix)
3935    {
3936      strcpy(sym, handle->loader->sym_prefix);
3937      strcat(sym, symbol);
3938    }
3939  else
3940    {
3941      strcpy(sym, symbol);
3942    }
3943
3944  address = handle->loader->find_sym (data, handle->module, sym);
3945  if (sym != lsym)
3946    {
3947      LT_DLFREE (sym);
3948    }
3949
3950  return address;
3951}
3952
3953const char *
3954lt_dlerror ()
3955{
3956  const char *error;
3957
3958  LT_DLMUTEX_GETERROR (error);
3959  LT_DLMUTEX_SETERROR (0);
3960
3961  return error ? error : NULL;
3962}
3963
3964static int
3965lt_dlpath_insertdir (ppath, before, dir)
3966     char **ppath;
3967     char *before;
3968     const char *dir;
3969{
3970  int    errors         = 0;
3971  char  *canonical      = 0;
3972  char  *argz           = 0;
3973  size_t argz_len       = 0;
3974
3975  assert (ppath);
3976  assert (dir && *dir);
3977
3978  if (canonicalize_path (dir, &canonical) != 0)
3979    {
3980      ++errors;
3981      goto cleanup;
3982    }
3983
3984  assert (canonical && *canonical);
3985
3986  /* If *PPATH is empty, set it to DIR.  */
3987  if (*ppath == 0)
3988    {
3989      assert (!before);         /* BEFORE cannot be set without PPATH.  */
3990      assert (dir);             /* Without DIR, don't call this function!  */
3991
3992      *ppath = lt_estrdup (dir);
3993      if (*ppath == 0)
3994        ++errors;
3995
3996      return errors;
3997    }
3998
3999  assert (ppath && *ppath);
4000
4001  if (argzize_path (*ppath, &argz, &argz_len) != 0)
4002    {
4003      ++errors;
4004      goto cleanup;
4005    }
4006
4007  /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
4008     if *PPATH is already canonicalized, and hence does not change length
4009     with respect to ARGZ.  We canonicalize each entry as it is added to
4010     the search path, and don't call this function with (uncanonicalized)
4011     user paths, so this is a fair assumption.  */
4012  if (before)
4013    {
4014      assert (*ppath <= before);
4015      assert (before - *ppath <= strlen (*ppath));
4016
4017      before = before - *ppath + argz;
4018    }
4019
4020  if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
4021    {
4022      ++errors;
4023      goto cleanup;
4024    }
4025
4026  argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
4027  LT_DLMEM_REASSIGN (*ppath,  argz);
4028
4029 cleanup:
4030  LT_DLFREE (canonical);
4031  LT_DLFREE (argz);
4032
4033  return errors;
4034}
4035
4036int
4037lt_dladdsearchdir (search_dir)
4038     const char *search_dir;
4039{
4040  int errors = 0;
4041
4042  if (search_dir && *search_dir)
4043    {
4044      LT_DLMUTEX_LOCK ();
4045      if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
4046        ++errors;
4047      LT_DLMUTEX_UNLOCK ();
4048    }
4049
4050  return errors;
4051}
4052
4053int
4054lt_dlinsertsearchdir (before, search_dir)
4055     const char *before;
4056     const char *search_dir;
4057{
4058  int errors = 0;
4059
4060  if (before)
4061    {
4062      LT_DLMUTEX_LOCK ();
4063      if ((before < user_search_path)
4064          || (before >= user_search_path + LT_STRLEN (user_search_path)))
4065        {
4066          LT_DLMUTEX_UNLOCK ();
4067          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
4068          return 1;
4069        }
4070      LT_DLMUTEX_UNLOCK ();
4071    }
4072
4073  if (search_dir && *search_dir)
4074    {
4075      LT_DLMUTEX_LOCK ();
4076      if (lt_dlpath_insertdir (&user_search_path,
4077                               (char *) before, search_dir) != 0)
4078        {
4079          ++errors;
4080        }
4081      LT_DLMUTEX_UNLOCK ();
4082    }
4083
4084  return errors;
4085}
4086
4087int
4088lt_dlsetsearchpath (search_path)
4089     const char *search_path;
4090{
4091  int   errors      = 0;
4092
4093  LT_DLMUTEX_LOCK ();
4094  LT_DLFREE (user_search_path);
4095  LT_DLMUTEX_UNLOCK ();
4096
4097  if (!search_path || !LT_STRLEN (search_path))
4098    {
4099      return errors;
4100    }
4101
4102  LT_DLMUTEX_LOCK ();
4103  if (canonicalize_path (search_path, &user_search_path) != 0)
4104    ++errors;
4105  LT_DLMUTEX_UNLOCK ();
4106
4107  return errors;
4108}
4109
4110const char *
4111lt_dlgetsearchpath ()
4112{
4113  const char *saved_path;
4114
4115  LT_DLMUTEX_LOCK ();
4116  saved_path = user_search_path;
4117  LT_DLMUTEX_UNLOCK ();
4118
4119  return saved_path;
4120}
4121
4122int
4123lt_dlmakeresident (handle)
4124     lt_dlhandle handle;
4125{
4126  int errors = 0;
4127
4128  if (!handle)
4129    {
4130      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4131      ++errors;
4132    }
4133  else
4134    {
4135      LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
4136    }
4137
4138  return errors;
4139}
4140
4141int
4142lt_dlisresident (handle)
4143     lt_dlhandle handle;
4144{
4145  if (!handle)
4146    {
4147      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4148      return -1;
4149    }
4150
4151  return LT_DLIS_RESIDENT (handle);
4152}
4153
4154
4155
4156
4157/* --- MODULE INFORMATION --- */
4158
4159const lt_dlinfo *
4160lt_dlgetinfo (handle)
4161     lt_dlhandle handle;
4162{
4163  if (!handle)
4164    {
4165      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4166      return 0;
4167    }
4168
4169  return &(handle->info);
4170}
4171
4172lt_dlhandle
4173lt_dlhandle_next (place)
4174     lt_dlhandle place;
4175{
4176  return place ? place->next : handles;
4177}
4178
4179int
4180lt_dlforeach (func, data)
4181     int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
4182     lt_ptr data;
4183{
4184  int errors = 0;
4185  lt_dlhandle cur;
4186
4187  LT_DLMUTEX_LOCK ();
4188
4189  cur = handles;
4190  while (cur)
4191    {
4192      lt_dlhandle tmp = cur;
4193
4194      cur = cur->next;
4195      if ((*func) (tmp, data))
4196        {
4197          ++errors;
4198          break;
4199        }
4200    }
4201
4202  LT_DLMUTEX_UNLOCK ();
4203
4204  return errors;
4205}
4206
4207lt_dlcaller_id
4208lt_dlcaller_register ()
4209{
4210  static lt_dlcaller_id last_caller_id = 0;
4211  int result;
4212
4213  LT_DLMUTEX_LOCK ();
4214  result = ++last_caller_id;
4215  LT_DLMUTEX_UNLOCK ();
4216
4217  return result;
4218}
4219
4220lt_ptr
4221lt_dlcaller_set_data (key, handle, data)
4222     lt_dlcaller_id key;
4223     lt_dlhandle handle;
4224     lt_ptr data;
4225{
4226  int n_elements = 0;
4227  lt_ptr stale = (lt_ptr) 0;
4228  int i;
4229
4230  /* This needs to be locked so that the caller data can be updated
4231     simultaneously by different threads.  */
4232  LT_DLMUTEX_LOCK ();
4233
4234  if (handle->caller_data)
4235    while (handle->caller_data[n_elements].key)
4236      ++n_elements;
4237
4238  for (i = 0; i < n_elements; ++i)
4239    {
4240      if (handle->caller_data[i].key == key)
4241        {
4242          stale = handle->caller_data[i].data;
4243          break;
4244        }
4245    }
4246
4247  /* Ensure that there is enough room in this handle's caller_data
4248     array to accept a new element (and an empty end marker).  */
4249  if (i == n_elements)
4250    {
4251      lt_caller_data *temp
4252        = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
4253
4254      if (!temp)
4255        {
4256          stale = 0;
4257          goto done;
4258        }
4259
4260      handle->caller_data = temp;
4261
4262      /* We only need this if we needed to allocate a new caller_data.  */
4263      handle->caller_data[i].key  = key;
4264      handle->caller_data[1+ i].key = 0;
4265    }
4266
4267  handle->caller_data[i].data = data;
4268
4269 done:
4270  LT_DLMUTEX_UNLOCK ();
4271
4272  return stale;
4273}
4274
4275lt_ptr
4276lt_dlcaller_get_data  (key, handle)
4277     lt_dlcaller_id key;
4278     lt_dlhandle handle;
4279{
4280  lt_ptr result = (lt_ptr) 0;
4281
4282  /* This needs to be locked so that the caller data isn't updated by
4283     another thread part way through this function.  */
4284  LT_DLMUTEX_LOCK ();
4285
4286  /* Locate the index of the element with a matching KEY.  */
4287  {
4288    int i;
4289    for (i = 0; handle->caller_data[i].key; ++i)
4290      {
4291        if (handle->caller_data[i].key == key)
4292          {
4293            result = handle->caller_data[i].data;
4294            break;
4295          }
4296      }
4297  }
4298
4299  LT_DLMUTEX_UNLOCK ();
4300
4301  return result;
4302}
4303
4304
4305
4306/* --- USER MODULE LOADER API --- */
4307
4308
4309int
4310lt_dlloader_add (place, dlloader, loader_name)
4311     lt_dlloader *place;
4312     const struct lt_user_dlloader *dlloader;
4313     const char *loader_name;
4314{
4315  int errors = 0;
4316  lt_dlloader *node = 0, *ptr = 0;
4317
4318  if ((dlloader == 0)   /* diagnose null parameters */
4319      || (dlloader->module_open == 0)
4320      || (dlloader->module_close == 0)
4321      || (dlloader->find_sym == 0))
4322    {
4323      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4324      return 1;
4325    }
4326
4327  /* Create a new dlloader node with copies of the user callbacks.  */
4328  node = LT_EMALLOC (lt_dlloader, 1);
4329  if (!node)
4330    return 1;
4331
4332  node->next            = 0;
4333  node->loader_name     = loader_name;
4334  node->sym_prefix      = dlloader->sym_prefix;
4335  node->dlloader_exit   = dlloader->dlloader_exit;
4336  node->module_open     = dlloader->module_open;
4337  node->module_close    = dlloader->module_close;
4338  node->find_sym        = dlloader->find_sym;
4339  node->dlloader_data   = dlloader->dlloader_data;
4340
4341  LT_DLMUTEX_LOCK ();
4342  if (!loaders)
4343    {
4344      /* If there are no loaders, NODE becomes the list! */
4345      loaders = node;
4346    }
4347  else if (!place)
4348    {
4349      /* If PLACE is not set, add NODE to the end of the
4350         LOADERS list. */
4351      for (ptr = loaders; ptr->next; ptr = ptr->next)
4352        {
4353          /*NOWORK*/;
4354        }
4355
4356      ptr->next = node;
4357    }
4358  else if (loaders == place)
4359    {
4360      /* If PLACE is the first loader, NODE goes first. */
4361      node->next = place;
4362      loaders = node;
4363    }
4364  else
4365    {
4366      /* Find the node immediately preceding PLACE. */
4367      for (ptr = loaders; ptr->next != place; ptr = ptr->next)
4368        {
4369          /*NOWORK*/;
4370        }
4371
4372      if (ptr->next != place)
4373        {
4374          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4375          ++errors;
4376        }
4377      else
4378        {
4379          /* Insert NODE between PTR and PLACE. */
4380          node->next = place;
4381          ptr->next  = node;
4382        }
4383    }
4384
4385  LT_DLMUTEX_UNLOCK ();
4386
4387  return errors;
4388}
4389
4390int
4391lt_dlloader_remove (loader_name)
4392     const char *loader_name;
4393{
4394  lt_dlloader *place = lt_dlloader_find (loader_name);
4395  lt_dlhandle handle;
4396  int errors = 0;
4397
4398  if (!place)
4399    {
4400      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4401      return 1;
4402    }
4403
4404  LT_DLMUTEX_LOCK ();
4405
4406  /* Fail if there are any open modules which use this loader. */
4407  for  (handle = handles; handle; handle = handle->next)
4408    {
4409      if (handle->loader == place)
4410        {
4411          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
4412          ++errors;
4413          goto done;
4414        }
4415    }
4416
4417  if (place == loaders)
4418    {
4419      /* PLACE is the first loader in the list. */
4420      loaders = loaders->next;
4421    }
4422  else
4423    {
4424      /* Find the loader before the one being removed. */
4425      lt_dlloader *prev;
4426      for (prev = loaders; prev->next; prev = prev->next)
4427        {
4428          if (!strcmp (prev->next->loader_name, loader_name))
4429            {
4430              break;
4431            }
4432        }
4433
4434      place = prev->next;
4435      prev->next = prev->next->next;
4436    }
4437
4438  if (place->dlloader_exit)
4439    {
4440      errors = place->dlloader_exit (place->dlloader_data);
4441    }
4442
4443  LT_DLFREE (place);
4444
4445 done:
4446  LT_DLMUTEX_UNLOCK ();
4447
4448  return errors;
4449}
4450
4451lt_dlloader *
4452lt_dlloader_next (place)
4453     lt_dlloader *place;
4454{
4455  lt_dlloader *next;
4456
4457  LT_DLMUTEX_LOCK ();
4458  next = place ? place->next : loaders;
4459  LT_DLMUTEX_UNLOCK ();
4460
4461  return next;
4462}
4463
4464const char *
4465lt_dlloader_name (place)
4466     lt_dlloader *place;
4467{
4468  const char *name = 0;
4469
4470  if (place)
4471    {
4472      LT_DLMUTEX_LOCK ();
4473      name = place ? place->loader_name : 0;
4474      LT_DLMUTEX_UNLOCK ();
4475    }
4476  else
4477    {
4478      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4479    }
4480
4481  return name;
4482}
4483
4484lt_user_data *
4485lt_dlloader_data (place)
4486     lt_dlloader *place;
4487{
4488  lt_user_data *data = 0;
4489
4490  if (place)
4491    {
4492      LT_DLMUTEX_LOCK ();
4493      data = place ? &(place->dlloader_data) : 0;
4494      LT_DLMUTEX_UNLOCK ();
4495    }
4496  else
4497    {
4498      LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4499    }
4500
4501  return data;
4502}
4503
4504lt_dlloader *
4505lt_dlloader_find (loader_name)
4506     const char *loader_name;
4507{
4508  lt_dlloader *place = 0;
4509
4510  LT_DLMUTEX_LOCK ();
4511  for (place = loaders; place; place = place->next)
4512    {
4513      if (strcmp (place->loader_name, loader_name) == 0)
4514        {
4515          break;
4516        }
4517    }
4518  LT_DLMUTEX_UNLOCK ();
4519
4520  return place;
4521}
Note: See TracBrowser for help on using the repository browser.