LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ltdl.c

Go to the documentation of this file.
00001 /* ltdl.c -- system independent dlopen wrapper
00002    Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc.
00003    Originally by Thomas Tanner <tanner@ffii.org>
00004    This file is part of GNU Libtool.
00005 
00006 This library is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Lesser General Public
00008 License as published by the Free Software Foundation; either
00009 version 2 of the License, or (at your option) any later version.
00010 
00011 As a special exception to the GNU Lesser General Public License,
00012 if you distribute this file as part of a program or library that
00013 is built using GNU libtool, you may include it under the same
00014 distribution terms that you use for the rest of that program.
00015 
00016 This library is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 Lesser General Public License for more details.
00020 
00021 You should have received a copy of the GNU Lesser General Public
00022 License along with this library; if not, write to the Free Software
00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00024 02111-1307  USA
00025 
00026 */
00027 
00028 #include "llvm/Config/config.h"
00029 /*
00030  #if HAVE_CONFIG_H
00031  #  include <config.h>
00032  #endif
00033 */
00034 
00035 #if HAVE_UNISTD_H
00036 #  include <unistd.h>
00037 #endif
00038 
00039 #if HAVE_STDIO_H
00040 #  include <stdio.h>
00041 #endif
00042 
00043 /* Include the header defining malloc.  On K&R C compilers,
00044    that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>.  */
00045 #if HAVE_STDLIB_H
00046 #  include <stdlib.h>
00047 #else
00048 #  if HAVE_MALLOC_H
00049 #    include <malloc.h>
00050 #  endif
00051 #endif
00052 
00053 #if HAVE_STRING_H
00054 #  include <string.h>
00055 #else
00056 #  if HAVE_STRINGS_H
00057 #    include <strings.h>
00058 #  endif
00059 #endif
00060 
00061 #if HAVE_CTYPE_H
00062 #  include <ctype.h>
00063 #endif
00064 
00065 #if HAVE_MEMORY_H
00066 #  include <memory.h>
00067 #endif
00068 
00069 #if HAVE_ERRNO_H
00070 #  include <errno.h>
00071 #endif
00072 
00073 
00074 #ifndef __WINDOWS__
00075 #  ifdef __WIN32__
00076 #    define __WINDOWS__
00077 #  endif
00078 #endif
00079 
00080 
00081 #undef LT_USE_POSIX_DIRENT
00082 #ifdef HAVE_CLOSEDIR
00083 #  ifdef HAVE_OPENDIR
00084 #    ifdef HAVE_READDIR
00085 #      ifdef HAVE_DIRENT_H
00086 #        define LT_USE_POSIX_DIRENT
00087 #      endif /* HAVE_DIRENT_H */
00088 #    endif /* HAVE_READDIR */
00089 #  endif /* HAVE_OPENDIR */
00090 #endif /* HAVE_CLOSEDIR */
00091 
00092 
00093 #undef LT_USE_WINDOWS_DIRENT_EMULATION
00094 #ifndef LT_USE_POSIX_DIRENT
00095 #  ifdef __WINDOWS__
00096 #    define LT_USE_WINDOWS_DIRENT_EMULATION
00097 #  endif /* __WINDOWS__ */
00098 #endif /* LT_USE_POSIX_DIRENT */
00099 
00100 
00101 #ifdef LT_USE_POSIX_DIRENT
00102 #  include <dirent.h>
00103 #  define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
00104 #else
00105 #  ifdef LT_USE_WINDOWS_DIRENT_EMULATION
00106 #    define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
00107 #  else
00108 #    define dirent direct
00109 #    define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
00110 #    if HAVE_SYS_NDIR_H
00111 #      include <sys/ndir.h>
00112 #    endif
00113 #    if HAVE_SYS_DIR_H
00114 #      include <sys/dir.h>
00115 #    endif
00116 #    if HAVE_NDIR_H
00117 #      include <ndir.h>
00118 #    endif
00119 #  endif
00120 #endif
00121 
00122 #if HAVE_ARGZ_H
00123 #  include <argz.h>
00124 #endif
00125 
00126 #if HAVE_ASSERT_H
00127 #  include <assert.h>
00128 #else
00129 #  define assert(arg) ((void) 0)
00130 #endif
00131 
00132 #include "ltdl.h"
00133 
00134 #if WITH_DMALLOC
00135 #  include <dmalloc.h>
00136 #endif
00137 
00138 
00139 
00140 
00141 /* --- WINDOWS SUPPORT --- */
00142 
00143 
00144 #ifdef DLL_EXPORT
00145 #  define LT_GLOBAL_DATA  __declspec(dllexport)
00146 #else
00147 #  define LT_GLOBAL_DATA
00148 #endif
00149 
00150 /* fopen() mode flags for reading a text file */
00151 #undef  LT_READTEXT_MODE
00152 #ifdef __WINDOWS__
00153 #  define LT_READTEXT_MODE "rt"
00154 #else
00155 #  define LT_READTEXT_MODE "r"
00156 #endif
00157 
00158 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
00159 
00160 #include <windows.h>
00161 
00162 #define dirent lt_dirent
00163 #define DIR lt_DIR
00164 
00165 struct dirent
00166 {
00167   char d_name[2048];
00168   int  d_namlen;
00169 };
00170 
00171 typedef struct _DIR
00172 {
00173   HANDLE hSearch;
00174   WIN32_FIND_DATA Win32FindData;
00175   BOOL firsttime;
00176   struct dirent file_info;
00177 } DIR;
00178 
00179 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
00180 
00181 
00182 /* --- MANIFEST CONSTANTS --- */
00183 
00184 
00185 /* Standard libltdl search path environment variable name  */
00186 #undef  LTDL_SEARCHPATH_VAR
00187 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
00188 
00189 /* Standard libtool archive file extension.  */
00190 #undef  LTDL_ARCHIVE_EXT
00191 #define LTDL_ARCHIVE_EXT  ".la"
00192 
00193 /* max. filename length */
00194 #ifndef LT_FILENAME_MAX
00195 #  define LT_FILENAME_MAX 1024
00196 #endif
00197 
00198 /* This is the maximum symbol size that won't require malloc/free */
00199 #undef  LT_SYMBOL_LENGTH
00200 #define LT_SYMBOL_LENGTH  128
00201 
00202 /* This accounts for the _LTX_ separator */
00203 #undef  LT_SYMBOL_OVERHEAD
00204 #define LT_SYMBOL_OVERHEAD  5
00205 
00206 
00207 
00208 
00209 /* --- MEMORY HANDLING --- */
00210 
00211 
00212 /* These are the functions used internally.  In addition to making
00213    use of the associated function pointers above, they also perform
00214    error handling.  */
00215 static char   *lt_estrdup LT_PARAMS((const char *str));
00216 static lt_ptr lt_emalloc  LT_PARAMS((size_t size));
00217 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
00218 
00219 /* static lt_ptr rpl_realloc  LT_PARAMS((lt_ptr ptr, size_t size)); */
00220 #define rpl_realloc realloc
00221 
00222 /* These are the pointers that can be changed by the caller:  */
00223 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)  LT_PARAMS((size_t size))
00224       = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
00225 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
00226       = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
00227 LT_GLOBAL_DATA void   (*lt_dlfree)  LT_PARAMS((lt_ptr ptr))
00228       = (void (*) LT_PARAMS((lt_ptr))) free;
00229 
00230 /* The following macros reduce the amount of typing needed to cast
00231    assigned memory.  */
00232 #if WITH_DMALLOC
00233 
00234 #define LT_DLMALLOC(tp, n)  ((tp *) xmalloc ((n) * sizeof(tp)))
00235 #define LT_DLREALLOC(tp, p, n)  ((tp *) xrealloc ((p), (n) * sizeof(tp)))
00236 #define LT_DLFREE(p)            \
00237   LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
00238 
00239 #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
00240 #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
00241 
00242 #else
00243 
00244 #define LT_DLMALLOC(tp, n)  ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
00245 #define LT_DLREALLOC(tp, p, n)  ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
00246 #define LT_DLFREE(p)            \
00247   LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
00248 
00249 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
00250 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
00251 
00252 #endif
00253 
00254 #define LT_DLMEM_REASSIGN(p, q)     LT_STMT_START { \
00255   if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
00256             } LT_STMT_END
00257 
00258 
00259 /* --- REPLACEMENT FUNCTIONS --- */
00260 
00261 
00262 #undef strdup
00263 #define strdup rpl_strdup
00264 
00265 static char *strdup LT_PARAMS((const char *str));
00266 
00267 static char *
00268 strdup(str)
00269      const char *str;
00270 {
00271   char *tmp = 0;
00272 
00273   if (str)
00274     {
00275       tmp = LT_DLMALLOC (char, 1+ strlen (str));
00276       if (tmp)
00277   {
00278     strcpy(tmp, str);
00279   }
00280     }
00281 
00282   return tmp;
00283 }
00284 
00285 
00286 #if ! HAVE_STRCMP
00287 
00288 #undef strcmp
00289 #define strcmp rpl_strcmp
00290 
00291 static int strcmp LT_PARAMS((const char *str1, const char *str2));
00292 
00293 static int
00294 strcmp (str1, str2)
00295      const char *str1;
00296      const char *str2;
00297 {
00298   if (str1 == str2)
00299     return 0;
00300   if (str1 == 0)
00301     return -1;
00302   if (str2 == 0)
00303     return 1;
00304 
00305   for (;*str1 && *str2; ++str1, ++str2)
00306     {
00307       if (*str1 != *str2)
00308   break;
00309     }
00310 
00311   return (int)(*str1 - *str2);
00312 }
00313 #endif
00314 
00315 
00316 #if ! HAVE_STRCHR
00317 
00318 #  if HAVE_INDEX
00319 #    define strchr index
00320 #  else
00321 #    define strchr rpl_strchr
00322 
00323 static const char *strchr LT_PARAMS((const char *str, int ch));
00324 
00325 static const char*
00326 strchr(str, ch)
00327      const char *str;
00328      int ch;
00329 {
00330   const char *p;
00331 
00332   for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
00333     /*NOWORK*/;
00334 
00335   return (*p == (char)ch) ? p : 0;
00336 }
00337 
00338 #  endif
00339 #endif /* !HAVE_STRCHR */
00340 
00341 
00342 #if ! HAVE_STRRCHR
00343 
00344 #  if HAVE_RINDEX
00345 #    define strrchr rindex
00346 #  else
00347 #    define strrchr rpl_strrchr
00348 
00349 static const char *strrchr LT_PARAMS((const char *str, int ch));
00350 
00351 static const char*
00352 strrchr(str, ch)
00353      const char *str;
00354      int ch;
00355 {
00356   const char *p, *q = 0;
00357 
00358   for (p = str; *p != LT_EOS_CHAR; ++p)
00359     {
00360       if (*p == (char) ch)
00361   {
00362     q = p;
00363   }
00364     }
00365 
00366   return q;
00367 }
00368 
00369 # endif
00370 #endif
00371 
00372 /* NOTE:  Neither bcopy nor the memcpy implementation below can
00373           reliably handle copying in overlapping areas of memory.  Use
00374           memmove (for which there is a fallback implmentation below)
00375     if you need that behaviour.  */
00376 #if ! HAVE_MEMCPY
00377 
00378 #  if HAVE_BCOPY
00379 #    define memcpy(dest, src, size) bcopy (src, dest, size)
00380 #  else
00381 #    define memcpy rpl_memcpy
00382 
00383 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
00384 
00385 static lt_ptr
00386 memcpy (dest, src, size)
00387      lt_ptr dest;
00388      const lt_ptr src;
00389      size_t size;
00390 {
00391   const char *  s = src;
00392   char *  d = dest;
00393   size_t  i = 0;
00394 
00395   for (i = 0; i < size; ++i)
00396     {
00397       d[i] = s[i];
00398     }
00399 
00400   return dest;
00401 }
00402 
00403 #  endif /* !HAVE_BCOPY */
00404 #endif   /* !HAVE_MEMCPY */
00405 
00406 #if ! HAVE_MEMMOVE
00407 #  define memmove rpl_memmove
00408 
00409 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
00410 
00411 static lt_ptr
00412 memmove (dest, src, size)
00413      lt_ptr dest;
00414      const lt_ptr src;
00415      size_t size;
00416 {
00417   const char *  s = src;
00418   char *  d = dest;
00419   size_t  i;
00420 
00421   if (d < s)
00422     for (i = 0; i < size; ++i)
00423       {
00424   d[i] = s[i];
00425       }
00426   else if (d > s && size > 0)
00427     for (i = size -1; ; --i)
00428       {
00429   d[i] = s[i];
00430   if (i == 0)
00431     break;
00432       }
00433 
00434   return dest;
00435 }
00436 
00437 #endif /* !HAVE_MEMMOVE */
00438 
00439 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
00440 
00441 static void closedir LT_PARAMS((DIR *entry));
00442 
00443 static void
00444 closedir(entry)
00445   DIR *entry;
00446 {
00447   assert(entry != (DIR *) NULL);
00448   FindClose(entry->hSearch);
00449   lt_dlfree((lt_ptr)entry);
00450 }
00451 
00452 
00453 static DIR * opendir LT_PARAMS((const char *path));
00454 
00455 static DIR*
00456 opendir (path)
00457   const char *path;
00458 {
00459   char file_specification[LT_FILENAME_MAX];
00460   DIR *entry;
00461 
00462   assert(path != (char *) NULL);
00463   (void) strncpy(file_specification,path,LT_FILENAME_MAX-1);
00464   (void) strcat(file_specification,"\\");
00465   entry = LT_DLMALLOC (DIR,sizeof(DIR));
00466   if (entry != (DIR *) 0)
00467     {
00468       entry->firsttime = TRUE;
00469       entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
00470     }
00471   if (entry->hSearch == INVALID_HANDLE_VALUE)
00472     {
00473       (void) strcat(file_specification,"\\*.*");
00474       entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
00475       if (entry->hSearch == INVALID_HANDLE_VALUE)
00476         {
00477           LT_DLFREE (entry);
00478           return (DIR *) 0;
00479         }
00480     }
00481   return(entry);
00482 }
00483 
00484 
00485 static struct dirent *readdir LT_PARAMS((DIR *entry));
00486 
00487 static struct dirent *readdir(entry)
00488   DIR *entry;
00489 {
00490   int
00491     status;
00492 
00493   if (entry == (DIR *) 0)
00494     return((struct dirent *) 0);
00495   if (!entry->firsttime)
00496     {
00497       status = FindNextFile(entry->hSearch,&entry->Win32FindData);
00498       if (status == 0)
00499         return((struct dirent *) 0);
00500     }
00501   entry->firsttime = FALSE;
00502   (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
00503     LT_FILENAME_MAX-1);
00504   entry->file_info.d_namlen = strlen(entry->file_info.d_name);
00505   return(&entry->file_info);
00506 }
00507 
00508 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
00509 
00510 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
00511     ``realloc is not entirely portable''
00512    In any case we want to use the allocator supplied by the user without
00513    burdening them with an lt_dlrealloc function pointer to maintain.
00514    Instead implement our own version (with known boundary conditions)
00515    using lt_dlmalloc and lt_dlfree. */
00516 
00517 /* #undef realloc
00518    #define realloc rpl_realloc
00519 */
00520 #if 0
00521   /* You can't (re)define realloc unless you also (re)define malloc.
00522      Right now, this code uses the size of the *destination* to decide
00523      how much to copy.  That's not right, but you can't know the size
00524      of the source unless you know enough about, or wrote malloc.  So
00525      this code is disabled... */
00526 
00527 static lt_ptr
00528 realloc (ptr, size)
00529      lt_ptr ptr;
00530      size_t size;
00531 {
00532   if (size == 0)
00533     {
00534       /* For zero or less bytes, free the original memory */
00535       if (ptr != 0)
00536   {
00537     lt_dlfree (ptr);
00538   }
00539 
00540       return (lt_ptr) 0;
00541     }
00542   else if (ptr == 0)
00543     {
00544       /* Allow reallocation of a NULL pointer.  */
00545       return lt_dlmalloc (size);
00546     }
00547   else
00548     {
00549       /* Allocate a new block, copy and free the old block.  */
00550       lt_ptr mem = lt_dlmalloc (size);
00551 
00552       if (mem)
00553   {
00554     memcpy (mem, ptr, size);
00555     lt_dlfree (ptr);
00556   }
00557 
00558       /* Note that the contents of PTR are not damaged if there is
00559    insufficient memory to realloc.  */
00560       return mem;
00561     }
00562 }
00563 #endif
00564 
00565 
00566 #if ! HAVE_ARGZ_APPEND
00567 #  define argz_append rpl_argz_append
00568 
00569 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
00570           const char *buf, size_t buf_len));
00571 
00572 static error_t
00573 argz_append (pargz, pargz_len, buf, buf_len)
00574      char **pargz;
00575      size_t *pargz_len;
00576      const char *buf;
00577      size_t buf_len;
00578 {
00579   size_t argz_len;
00580   char  *argz;
00581 
00582   assert (pargz);
00583   assert (pargz_len);
00584   assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
00585 
00586   /* If nothing needs to be appended, no more work is required.  */
00587   if (buf_len == 0)
00588     return 0;
00589 
00590   /* Ensure there is enough room to append BUF_LEN.  */
00591   argz_len = *pargz_len + buf_len;
00592   argz = LT_DLREALLOC (char, *pargz, argz_len);
00593   if (!argz)
00594     return ENOMEM;
00595 
00596   /* Copy characters from BUF after terminating '\0' in ARGZ.  */
00597   memcpy (argz + *pargz_len, buf, buf_len);
00598 
00599   /* Assign new values.  */
00600   *pargz = argz;
00601   *pargz_len = argz_len;
00602 
00603   return 0;
00604 }
00605 #endif /* !HAVE_ARGZ_APPEND */
00606 
00607 
00608 #if ! HAVE_ARGZ_CREATE_SEP
00609 #  define argz_create_sep rpl_argz_create_sep
00610 
00611 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
00612               char **pargz, size_t *pargz_len));
00613 
00614 static error_t
00615 argz_create_sep (str, delim, pargz, pargz_len)
00616      const char *str;
00617      int delim;
00618      char **pargz;
00619      size_t *pargz_len;
00620 {
00621   size_t argz_len;
00622   char *argz = 0;
00623 
00624   assert (str);
00625   assert (pargz);
00626   assert (pargz_len);
00627 
00628   /* Make a copy of STR, but replacing each occurence of
00629      DELIM with '\0'.  */
00630   argz_len = 1+ LT_STRLEN (str);
00631   if (argz_len)
00632     {
00633       const char *p;
00634       char *q;
00635 
00636       argz = LT_DLMALLOC (char, argz_len);
00637       if (!argz)
00638   return ENOMEM;
00639 
00640       for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
00641   {
00642     if (*p == delim)
00643       {
00644         /* Ignore leading delimiters, and fold consecutive
00645      delimiters in STR into a single '\0' in ARGZ.  */
00646         if ((q > argz) && (q[-1] != LT_EOS_CHAR))
00647     *q++ = LT_EOS_CHAR;
00648         else
00649     --argz_len;
00650       }
00651     else
00652       *q++ = *p;
00653   }
00654       /* Copy terminating LT_EOS_CHAR.  */
00655       *q = *p;
00656     }
00657 
00658   /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory.  */
00659   if (!argz_len)
00660     LT_DLFREE (argz);
00661 
00662   /* Assign new values.  */
00663   *pargz = argz;
00664   *pargz_len = argz_len;
00665 
00666   return 0;
00667 }
00668 #endif /* !HAVE_ARGZ_CREATE_SEP */
00669 
00670 
00671 #if ! HAVE_ARGZ_INSERT
00672 #  define argz_insert rpl_argz_insert
00673 
00674 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
00675           char *before, const char *entry));
00676 
00677 static error_t
00678 argz_insert (pargz, pargz_len, before, entry)
00679      char **pargz;
00680      size_t *pargz_len;
00681      char *before;
00682      const char *entry;
00683 {
00684   assert (pargz);
00685   assert (pargz_len);
00686   assert (entry && *entry);
00687 
00688   /* No BEFORE address indicates ENTRY should be inserted after the
00689      current last element.  */
00690   if (!before)
00691     return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
00692 
00693   /* This probably indicates a programmer error, but to preserve
00694      semantics, scan back to the start of an entry if BEFORE points
00695      into the middle of it.  */
00696   while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
00697     --before;
00698 
00699   {
00700     size_t entry_len  = 1+ LT_STRLEN (entry);
00701     size_t argz_len = *pargz_len + entry_len;
00702     size_t offset = before - *pargz;
00703     char   *argz  = LT_DLREALLOC (char, *pargz, argz_len);
00704 
00705     if (!argz)
00706       return ENOMEM;
00707 
00708     /* Make BEFORE point to the equivalent offset in ARGZ that it
00709        used to have in *PARGZ incase realloc() moved the block.  */
00710     before = argz + offset;
00711 
00712     /* Move the ARGZ entries starting at BEFORE up into the new
00713        space at the end -- making room to copy ENTRY into the
00714        resulting gap.  */
00715     memmove (before + entry_len, before, *pargz_len - offset);
00716     memcpy  (before, entry, entry_len);
00717 
00718     /* Assign new values.  */
00719     *pargz = argz;
00720     *pargz_len = argz_len;
00721   }
00722 
00723   return 0;
00724 }
00725 #endif /* !HAVE_ARGZ_INSERT */
00726 
00727 
00728 #if ! HAVE_ARGZ_NEXT
00729 #  define argz_next rpl_argz_next
00730 
00731 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
00732             const char *entry));
00733 
00734 static char *
00735 argz_next (argz, argz_len, entry)
00736      char *argz;
00737      size_t argz_len;
00738      const char *entry;
00739 {
00740   assert ((argz && argz_len) || (!argz && !argz_len));
00741 
00742   if (entry)
00743     {
00744       /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
00745    within the ARGZ vector.  */
00746       assert ((!argz && !argz_len)
00747         || ((argz <= entry) && (entry < (argz + argz_len))));
00748 
00749       /* Move to the char immediately after the terminating
00750    '\0' of ENTRY.  */
00751       entry = 1+ strchr (entry, LT_EOS_CHAR);
00752 
00753       /* Return either the new ENTRY, or else NULL if ARGZ is
00754    exhausted.  */
00755       return (entry >= argz + argz_len) ? 0 : (char *) entry;
00756     }
00757   else
00758     {
00759       /* This should probably be flagged as a programmer error,
00760    since starting an argz_next loop with the iterator set
00761    to ARGZ is safer.  To preserve semantics, handle the NULL
00762    case by returning the start of ARGZ (if any).  */
00763       if (argz_len > 0)
00764   return argz;
00765       else
00766   return 0;
00767     }
00768 }
00769 #endif /* !HAVE_ARGZ_NEXT */
00770 
00771 
00772 
00773 #if ! HAVE_ARGZ_STRINGIFY
00774 #  define argz_stringify rpl_argz_stringify
00775 
00776 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
00777                int sep));
00778 
00779 static void
00780 argz_stringify (argz, argz_len, sep)
00781      char *argz;
00782      size_t argz_len;
00783      int sep;
00784 {
00785   assert ((argz && argz_len) || (!argz && !argz_len));
00786 
00787   if (sep)
00788     {
00789       --argz_len;   /* don't stringify the terminating EOS */
00790       while (--argz_len > 0)
00791   {
00792     if (argz[argz_len] == LT_EOS_CHAR)
00793       argz[argz_len] = sep;
00794   }
00795     }
00796 }
00797 #endif /* !HAVE_ARGZ_STRINGIFY */
00798 
00799 
00800 
00801 
00802 /* --- TYPE DEFINITIONS -- */
00803 
00804 
00805 /* This type is used for the array of caller data sets in each handler. */
00806 typedef struct {
00807   lt_dlcaller_id  key;
00808   lt_ptr    data;
00809 } lt_caller_data;
00810 
00811 
00812 
00813 
00814 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
00815 
00816 
00817 /* Extract the diagnostic strings from the error table macro in the same
00818    order as the enumerated indices in ltdl.h. */
00819 
00820 static const char *lt_dlerror_strings[] =
00821   {
00822 #define LT_ERROR(name, diagnostic)  (diagnostic),
00823     lt_dlerror_table
00824 #undef LT_ERROR
00825 
00826     0
00827   };
00828 
00829 /* This structure is used for the list of registered loaders. */
00830 struct lt_dlloader {
00831   struct lt_dlloader   *next;
00832   const char         *loader_name;  /* identifying name for each loader */
00833   const char         *sym_prefix; /* prefix for symbols */
00834   lt_module_open       *module_open;
00835   lt_module_close      *module_close;
00836   lt_find_sym        *find_sym;
00837   lt_dlloader_exit     *dlloader_exit;
00838   lt_user_data    dlloader_data;
00839 };
00840 
00841 struct lt_dlhandle_struct {
00842   struct lt_dlhandle_struct   *next;
00843   lt_dlloader        *loader;   /* dlopening interface */
00844   lt_dlinfo   info;
00845   int     depcount; /* number of dependencies */
00846   lt_dlhandle        *deplibs;  /* dependencies */
00847   lt_module   module;   /* system module handle */
00848   lt_ptr    system;   /* system specific data */
00849   lt_caller_data       *caller_data;  /* per caller associated data */
00850   int     flags;    /* various boolean stats */
00851 };
00852 
00853 /* Various boolean flags can be stored in the flags field of an
00854    lt_dlhandle_struct... */
00855 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
00856 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
00857 
00858 #define LT_DLRESIDENT_FLAG      (0x01 << 0)
00859 /* ...add more flags here... */
00860 
00861 #define LT_DLIS_RESIDENT(handle)    LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
00862 
00863 
00864 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
00865 
00866 static  const char  objdir[]    = LTDL_OBJDIR;
00867 static  const char  archive_ext[]   = LTDL_ARCHIVE_EXT;
00868 #ifdef  LTDL_SHLIB_EXT
00869 static  const char  shlib_ext[]   = LTDL_SHLIB_EXT;
00870 #endif
00871 #ifdef  LTDL_SYSSEARCHPATH
00872 static  const char  sys_search_path[] = LTDL_SYSSEARCHPATH;
00873 #endif
00874 
00875 
00876 
00877 
00878 /* --- MUTEX LOCKING --- */
00879 
00880 
00881 /* Macros to make it easier to run the lock functions only if they have
00882    been registered.  The reason for the complicated lock macro is to
00883    ensure that the stored error message from the last error is not
00884    accidentally erased if the current function doesn't generate an
00885    error of its own.  */
00886 #define LT_DLMUTEX_LOCK()     LT_STMT_START { \
00887   if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)();  \
00888             } LT_STMT_END
00889 #define LT_DLMUTEX_UNLOCK()     LT_STMT_START { \
00890   if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
00891             } LT_STMT_END
00892 #define LT_DLMUTEX_SETERROR(errormsg)   LT_STMT_START { \
00893   if (lt_dlmutex_seterror_func)       \
00894     (*lt_dlmutex_seterror_func) (errormsg);   \
00895   else  lt_dllast_error = (errormsg); } LT_STMT_END
00896 #define LT_DLMUTEX_GETERROR(errormsg)   LT_STMT_START { \
00897   if (lt_dlmutex_seterror_func)       \
00898     (errormsg) = (*lt_dlmutex_geterror_func) ();  \
00899   else  (errormsg) = lt_dllast_error; } LT_STMT_END
00900 
00901 /* The mutex functions stored here are global, and are necessarily the
00902    same for all threads that wish to share access to libltdl.  */
00903 static  lt_dlmutex_lock     *lt_dlmutex_lock_func     = 0;
00904 static  lt_dlmutex_unlock   *lt_dlmutex_unlock_func   = 0;
00905 static  lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
00906 static  lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
00907 static  const char      *lt_dllast_error        = 0;
00908 
00909 
00910 /* Either set or reset the mutex functions.  Either all the arguments must
00911    be valid functions, or else all can be NULL to turn off locking entirely.
00912    The registered functions should be manipulating a static global lock
00913    from the lock() and unlock() callbacks, which needs to be reentrant.  */
00914 int
00915 lt_dlmutex_register (lock, unlock, seterror, geterror)
00916      lt_dlmutex_lock *lock;
00917      lt_dlmutex_unlock *unlock;
00918      lt_dlmutex_seterror *seterror;
00919      lt_dlmutex_geterror *geterror;
00920 {
00921   lt_dlmutex_unlock *old_unlock = unlock;
00922   int        errors = 0;
00923 
00924   /* Lock using the old lock() callback, if any.  */
00925   LT_DLMUTEX_LOCK ();
00926 
00927   if ((lock && unlock && seterror && geterror)
00928       || !(lock || unlock || seterror || geterror))
00929     {
00930       lt_dlmutex_lock_func     = lock;
00931       lt_dlmutex_unlock_func   = unlock;
00932       lt_dlmutex_geterror_func = geterror;
00933     }
00934   else
00935     {
00936       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
00937       ++errors;
00938     }
00939 
00940   /* Use the old unlock() callback we saved earlier, if any.  Otherwise
00941      record any errors using internal storage.  */
00942   if (old_unlock)
00943     (*old_unlock) ();
00944 
00945   /* Return the number of errors encountered during the execution of
00946      this function.  */
00947   return errors;
00948 }
00949 
00950 
00951 
00952 
00953 /* --- ERROR HANDLING --- */
00954 
00955 
00956 static  const char    **user_error_strings  = 0;
00957 static  int   errorcount    = LT_ERROR_MAX;
00958 
00959 int
00960 lt_dladderror (diagnostic)
00961      const char *diagnostic;
00962 {
00963   int   errindex = 0;
00964   int   result   = -1;
00965   const char  **temp     = (const char **) 0;
00966 
00967   assert (diagnostic);
00968 
00969   LT_DLMUTEX_LOCK ();
00970 
00971   errindex = errorcount - LT_ERROR_MAX;
00972   temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
00973   if (temp)
00974     {
00975       user_error_strings    = temp;
00976       user_error_strings[errindex]  = diagnostic;
00977       result        = errorcount++;
00978     }
00979 
00980   LT_DLMUTEX_UNLOCK ();
00981 
00982   return result;
00983 }
00984 
00985 int
00986 lt_dlseterror (errindex)
00987      int errindex;
00988 {
00989   int   errors   = 0;
00990 
00991   LT_DLMUTEX_LOCK ();
00992 
00993   if (errindex >= errorcount || errindex < 0)
00994     {
00995       /* Ack!  Error setting the error message! */
00996       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
00997       ++errors;
00998     }
00999   else if (errindex < LT_ERROR_MAX)
01000     {
01001       /* No error setting the error message! */
01002       LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
01003     }
01004   else
01005     {
01006       /* No error setting the error message! */
01007       LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
01008     }
01009 
01010   LT_DLMUTEX_UNLOCK ();
01011 
01012   return errors;
01013 }
01014 
01015 static lt_ptr
01016 lt_emalloc (size)
01017      size_t size;
01018 {
01019   lt_ptr mem = lt_dlmalloc (size);
01020   if (size && !mem)
01021     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
01022   return mem;
01023 }
01024 
01025 static lt_ptr
01026 lt_erealloc (addr, size)
01027      lt_ptr addr;
01028      size_t size;
01029 {
01030   lt_ptr mem = lt_dlrealloc (addr, size);
01031   if (size && !mem)
01032     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
01033   return mem;
01034 }
01035 
01036 static char *
01037 lt_estrdup (str)
01038      const char *str;
01039 {
01040   char *copy = strdup (str);
01041   if (LT_STRLEN (str) && !copy)
01042     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
01043   return copy;
01044 }
01045 
01046 
01047 
01048 
01049 /* --- DLOPEN() INTERFACE LOADER --- */
01050 
01051 
01052 #if HAVE_LIBDL
01053 
01054 /* dynamic linking with dlopen/dlsym */
01055 
01056 #if HAVE_DLFCN_H
01057 #  include <dlfcn.h>
01058 #endif
01059 
01060 #if HAVE_SYS_DL_H
01061 #  include <sys/dl.h>
01062 #endif
01063 
01064 #ifdef RTLD_GLOBAL
01065 #  define LT_GLOBAL   RTLD_GLOBAL
01066 #else
01067 #  ifdef DL_GLOBAL
01068 #    define LT_GLOBAL   DL_GLOBAL
01069 #  endif
01070 #endif /* !RTLD_GLOBAL */
01071 #ifndef LT_GLOBAL
01072 #  define LT_GLOBAL   0
01073 #endif /* !LT_GLOBAL */
01074 
01075 /* We may have to define LT_LAZY_OR_NOW in the command line if we
01076    find out it does not work in some platform. */
01077 #ifndef LT_LAZY_OR_NOW
01078 #  ifdef RTLD_LAZY
01079 #    define LT_LAZY_OR_NOW  RTLD_LAZY
01080 #  else
01081 #    ifdef DL_LAZY
01082 #      define LT_LAZY_OR_NOW  DL_LAZY
01083 #    endif
01084 #  endif /* !RTLD_LAZY */
01085 #endif
01086 #ifndef LT_LAZY_OR_NOW
01087 #  ifdef RTLD_NOW
01088 #    define LT_LAZY_OR_NOW  RTLD_NOW
01089 #  else
01090 #    ifdef DL_NOW
01091 #      define LT_LAZY_OR_NOW  DL_NOW
01092 #    endif
01093 #  endif /* !RTLD_NOW */
01094 #endif
01095 #ifndef LT_LAZY_OR_NOW
01096 #  define LT_LAZY_OR_NOW  0
01097 #endif /* !LT_LAZY_OR_NOW */
01098 
01099 #if HAVE_DLERROR
01100 #  define DLERROR(arg)  dlerror ()
01101 #else
01102 #  define DLERROR(arg)  LT_DLSTRERROR (arg)
01103 #endif
01104 
01105 static lt_module
01106 sys_dl_open (loader_data, filename)
01107      lt_user_data loader_data;
01108      const char *filename;
01109 {
01110   lt_module   module   = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
01111 
01112   if (!module)
01113     {
01114       LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
01115     }
01116 
01117   return module;
01118 }
01119 
01120 static int
01121 sys_dl_close (loader_data, module)
01122      lt_user_data loader_data;
01123      lt_module module;
01124 {
01125   int errors = 0;
01126 
01127   if (dlclose (module) != 0)
01128     {
01129       LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
01130       ++errors;
01131     }
01132 
01133   return errors;
01134 }
01135 
01136 static lt_ptr
01137 sys_dl_sym (loader_data, module, symbol)
01138      lt_user_data loader_data;
01139      lt_module module;
01140      const char *symbol;
01141 {
01142   lt_ptr address = dlsym (module, symbol);
01143 
01144   if (!address)
01145     {
01146       LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
01147     }
01148 
01149   return address;
01150 }
01151 
01152 static struct lt_user_dlloader sys_dl =
01153   {
01154 #  ifdef NEED_USCORE
01155     "_",
01156 #  else
01157     0,
01158 #  endif
01159     sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
01160 
01161 
01162 #endif /* HAVE_LIBDL */
01163 
01164 
01165 
01166 /* --- SHL_LOAD() INTERFACE LOADER --- */
01167 
01168 #if HAVE_SHL_LOAD
01169 
01170 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
01171 
01172 #ifdef HAVE_DL_H
01173 #  include <dl.h>
01174 #endif
01175 
01176 /* some flags are missing on some systems, so we provide
01177  * harmless defaults.
01178  *
01179  * Mandatory:
01180  * BIND_IMMEDIATE  - Resolve symbol references when the library is loaded.
01181  * BIND_DEFERRED   - Delay code symbol resolution until actual reference.
01182  *
01183  * Optionally:
01184  * BIND_FIRST    - Place the library at the head of the symbol search
01185  *         order.
01186  * BIND_NONFATAL   - The default BIND_IMMEDIATE behavior is to treat all
01187  *         unsatisfied symbols as fatal.  This flag allows
01188  *         binding of unsatisfied code symbols to be deferred
01189  *         until use.
01190  *         [Perl: For certain libraries, like DCE, deferred
01191  *         binding often causes run time problems. Adding
01192  *         BIND_NONFATAL to BIND_IMMEDIATE still allows
01193  *         unresolved references in situations like this.]
01194  * BIND_NOSTART    - Do not call the initializer for the shared library
01195  *         when the library is loaded, nor on a future call to
01196  *         shl_unload().
01197  * BIND_VERBOSE    - Print verbose messages concerning possible
01198  *         unsatisfied symbols.
01199  *
01200  * hp9000s700/hp9000s800:
01201  * BIND_RESTRICTED - Restrict symbols visible by the library to those
01202  *         present at library load time.
01203  * DYNAMIC_PATH    - Allow the loader to dynamically search for the
01204  *         library specified by the path argument.
01205  */
01206 
01207 #ifndef DYNAMIC_PATH
01208 #  define DYNAMIC_PATH    0
01209 #endif
01210 #ifndef BIND_RESTRICTED
01211 #  define BIND_RESTRICTED 0
01212 #endif
01213 
01214 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
01215 
01216 static lt_module
01217 sys_shl_open (loader_data, filename)
01218      lt_user_data loader_data;
01219      const char *filename;
01220 {
01221   static shl_t self = (shl_t) 0;
01222   lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
01223 
01224   /* Since searching for a symbol against a NULL module handle will also
01225      look in everything else that was already loaded and exported with
01226      the -E compiler flag, we always cache a handle saved before any
01227      modules are loaded.  */
01228   if (!self)
01229     {
01230       lt_ptr address;
01231       shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
01232     }
01233 
01234   if (!filename)
01235     {
01236       module = self;
01237     }
01238   else
01239     {
01240       module = shl_load (filename, LT_BIND_FLAGS, 0L);
01241 
01242       if (!module)
01243   {
01244     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01245   }
01246     }
01247 
01248   return module;
01249 }
01250 
01251 static int
01252 sys_shl_close (loader_data, module)
01253      lt_user_data loader_data;
01254      lt_module module;
01255 {
01256   int errors = 0;
01257 
01258   if (module && (shl_unload ((shl_t) (module)) != 0))
01259     {
01260       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01261       ++errors;
01262     }
01263 
01264   return errors;
01265 }
01266 
01267 static lt_ptr
01268 sys_shl_sym (loader_data, module, symbol)
01269      lt_user_data loader_data;
01270      lt_module module;
01271      const char *symbol;
01272 {
01273   lt_ptr address = 0;
01274 
01275   /* sys_shl_open should never return a NULL module handle */
01276   if (module == (lt_module) 0)
01277   {
01278     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
01279   }
01280   else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
01281     {
01282       if (!address)
01283   {
01284     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01285   }
01286     }
01287 
01288   return address;
01289 }
01290 
01291 static struct lt_user_dlloader sys_shl = {
01292   0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
01293 };
01294 
01295 #endif /* HAVE_SHL_LOAD */
01296 
01297 
01298 
01299 
01300 /* --- LOADLIBRARY() INTERFACE LOADER --- */
01301 
01302 #ifdef __WINDOWS__
01303 
01304 /* dynamic linking for Win32 */
01305 
01306 #include <windows.h>
01307 
01308 /* Forward declaration; required to implement handle search below. */
01309 static lt_dlhandle handles;
01310 
01311 static lt_module
01312 sys_wll_open (loader_data, filename)
01313      lt_user_data loader_data;
01314      const char *filename;
01315 {
01316   lt_dlhandle cur;
01317   lt_module module     = 0;
01318   const char   *errormsg   = 0;
01319   char         *searchname = 0;
01320   char         *ext;
01321   char    self_name_buf[MAX_PATH];
01322 
01323   if (!filename)
01324     {
01325       /* Get the name of main module */
01326       *self_name_buf = 0;
01327       GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
01328       filename = ext = self_name_buf;
01329     }
01330   else
01331     {
01332       ext = strrchr (filename, '.');
01333     }
01334 
01335   if (ext)
01336     {
01337       /* FILENAME already has an extension. */
01338       searchname = lt_estrdup (filename);
01339     }
01340   else
01341     {
01342       /* Append a `.' to stop Windows from adding an
01343    implicit `.dll' extension. */
01344       searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
01345       if (searchname)
01346   sprintf (searchname, "%s.", filename);
01347     }
01348   if (!searchname)
01349     return 0;
01350 
01351 #if __CYGWIN__
01352   {
01353     char wpath[MAX_PATH];
01354     cygwin_conv_to_full_win32_path(searchname, wpath);
01355     module = LoadLibrary(wpath);
01356   }
01357 #else
01358   module = LoadLibrary (searchname);
01359 #endif
01360   LT_DLFREE (searchname);
01361 
01362   /* libltdl expects this function to fail if it is unable
01363      to physically load the library.  Sadly, LoadLibrary
01364      will search the loaded libraries for a match and return
01365      one of them if the path search load fails.
01366 
01367      We check whether LoadLibrary is returning a handle to
01368      an already loaded module, and simulate failure if we
01369      find one. */
01370   LT_DLMUTEX_LOCK ();
01371   cur = handles;
01372   while (cur)
01373     {
01374       if (!cur->module)
01375   {
01376     cur = 0;
01377     break;
01378   }
01379 
01380       if (cur->module == module)
01381   {
01382     break;
01383   }
01384 
01385       cur = cur->next;
01386   }
01387   LT_DLMUTEX_UNLOCK ();
01388 
01389   if (cur || !module)
01390     {
01391       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01392       module = 0;
01393     }
01394 
01395   return module;
01396 }
01397 
01398 static int
01399 sys_wll_close (loader_data, module)
01400      lt_user_data loader_data;
01401      lt_module module;
01402 {
01403   int       errors   = 0;
01404 
01405   if (FreeLibrary(module) == 0)
01406     {
01407       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01408       ++errors;
01409     }
01410 
01411   return errors;
01412 }
01413 
01414 static lt_ptr
01415 sys_wll_sym (loader_data, module, symbol)
01416      lt_user_data loader_data;
01417      lt_module module;
01418      const char *symbol;
01419 {
01420   lt_ptr      address  = GetProcAddress (module, symbol);
01421 
01422   if (!address)
01423     {
01424       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01425     }
01426 
01427   return address;
01428 }
01429 
01430 static struct lt_user_dlloader sys_wll = {
01431   0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
01432 };
01433 
01434 #endif /* __WINDOWS__ */
01435 
01436 
01437 
01438 
01439 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
01440 
01441 
01442 #ifdef __BEOS__
01443 
01444 /* dynamic linking for BeOS */
01445 
01446 #include <kernel/image.h>
01447 
01448 static lt_module
01449 sys_bedl_open (loader_data, filename)
01450      lt_user_data loader_data;
01451      const char *filename;
01452 {
01453   image_id image = 0;
01454 
01455   if (filename)
01456     {
01457       image = load_add_on (filename);
01458     }
01459   else
01460     {
01461       image_info info;
01462       int32 cookie = 0;
01463       if (get_next_image_info (0, &cookie, &info) == B_OK)
01464   image = load_add_on (info.name);
01465     }
01466 
01467   if (image <= 0)
01468     {
01469       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01470       image = 0;
01471     }
01472 
01473   return (lt_module) image;
01474 }
01475 
01476 static int
01477 sys_bedl_close (loader_data, module)
01478      lt_user_data loader_data;
01479      lt_module module;
01480 {
01481   int errors = 0;
01482 
01483   if (unload_add_on ((image_id) module) != B_OK)
01484     {
01485       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01486       ++errors;
01487     }
01488 
01489   return errors;
01490 }
01491 
01492 static lt_ptr
01493 sys_bedl_sym (loader_data, module, symbol)
01494      lt_user_data loader_data;
01495      lt_module module;
01496      const char *symbol;
01497 {
01498   lt_ptr address = 0;
01499   image_id image = (image_id) module;
01500 
01501   if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
01502     {
01503       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01504       address = 0;
01505     }
01506 
01507   return address;
01508 }
01509 
01510 static struct lt_user_dlloader sys_bedl = {
01511   0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
01512 };
01513 
01514 #endif /* __BEOS__ */
01515 
01516 
01517 
01518 
01519 /* --- DLD_LINK() INTERFACE LOADER --- */
01520 
01521 
01522 #if HAVE_DLD
01523 
01524 /* dynamic linking with dld */
01525 
01526 #if HAVE_DLD_H
01527 #include <dld.h>
01528 #endif
01529 
01530 static lt_module
01531 sys_dld_open (loader_data, filename)
01532      lt_user_data loader_data;
01533      const char *filename;
01534 {
01535   lt_module module = strdup (filename);
01536 
01537   if (dld_link (filename) != 0)
01538     {
01539       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01540       LT_DLFREE (module);
01541       module = 0;
01542     }
01543 
01544   return module;
01545 }
01546 
01547 static int
01548 sys_dld_close (loader_data, module)
01549      lt_user_data loader_data;
01550      lt_module module;
01551 {
01552   int errors = 0;
01553 
01554   if (dld_unlink_by_file ((char*)(module), 1) != 0)
01555     {
01556       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01557       ++errors;
01558     }
01559   else
01560     {
01561       LT_DLFREE (module);
01562     }
01563 
01564   return errors;
01565 }
01566 
01567 static lt_ptr
01568 sys_dld_sym (loader_data, module, symbol)
01569      lt_user_data loader_data;
01570      lt_module module;
01571      const char *symbol;
01572 {
01573   lt_ptr address = dld_get_func (symbol);
01574 
01575   if (!address)
01576     {
01577       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01578     }
01579 
01580   return address;
01581 }
01582 
01583 static struct lt_user_dlloader sys_dld = {
01584   0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
01585 };
01586 
01587 #endif /* HAVE_DLD */
01588 
01589 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
01590 #if HAVE_DYLD
01591 
01592 
01593 #if HAVE_MACH_O_DYLD_H
01594 #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
01595 /* Is this correct? Does it still function properly? */
01596 #define __private_extern__ extern
01597 #endif
01598 # include <mach-o/dyld.h>
01599 #endif
01600 #include <mach-o/getsect.h>
01601 
01602 /* We have to put some stuff here that isn't in older dyld.h files */
01603 #ifndef ENUM_DYLD_BOOL
01604 # define ENUM_DYLD_BOOL
01605 # undef FALSE
01606 # undef TRUE
01607  enum DYLD_BOOL {
01608     FALSE,
01609     TRUE
01610  };
01611 #endif
01612 #ifndef LC_REQ_DYLD
01613 # define LC_REQ_DYLD 0x80000000
01614 #endif
01615 #ifndef LC_LOAD_WEAK_DYLIB
01616 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
01617 #endif
01618 static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
01619 static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
01620 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
01621 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
01622 
01623 #ifndef NSADDIMAGE_OPTION_NONE
01624 #define NSADDIMAGE_OPTION_NONE                          0x0
01625 #endif
01626 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
01627 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR               0x1
01628 #endif
01629 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
01630 #define NSADDIMAGE_OPTION_WITH_SEARCHING                0x2
01631 #endif
01632 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
01633 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED         0x4
01634 #endif
01635 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
01636 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
01637 #endif
01638 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
01639 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND            0x0
01640 #endif
01641 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
01642 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW        0x1
01643 #endif
01644 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
01645 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY      0x2
01646 #endif
01647 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
01648 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
01649 #endif
01650 
01651 
01652 static const char *
01653 lt_int_dyld_error(othererror)
01654   char* othererror;
01655 {
01656 /* return the dyld error string, or the passed in error string if none */
01657   NSLinkEditErrors ler;
01658   int lerno;
01659   const char *errstr;
01660   const char *file;
01661   NSLinkEditError(&ler,&lerno,&file,&errstr);
01662   if (!errstr || !strlen(errstr)) errstr = othererror;
01663   return errstr;
01664 }
01665 
01666 static const struct mach_header *
01667 lt_int_dyld_get_mach_header_from_nsmodule(module)
01668   NSModule module;
01669 {
01670 /* There should probably be an apple dyld api for this */
01671   int i=_dyld_image_count();
01672   int j;
01673   const char *modname=NSNameOfModule(module);
01674   const struct mach_header *mh=NULL;
01675   if (!modname) return NULL;
01676   for (j = 0; j < i; j++)
01677   {
01678     if (!strcmp(_dyld_get_image_name(j),modname))
01679     {
01680       mh=_dyld_get_image_header(j);
01681       break;
01682     }
01683   }
01684   return mh;
01685 }
01686 
01687 static const char* lt_int_dyld_lib_install_name(mh)
01688   const struct mach_header *mh;
01689 {
01690 /* NSAddImage is also used to get the loaded image, but it only works if the lib
01691    is installed, for uninstalled libs we need to check the install_names against
01692    each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
01693    different lib was loaded as a result
01694 */
01695   int j;
01696   struct load_command *lc;
01697   unsigned long offset = sizeof(struct mach_header);
01698   const char* retStr=NULL;
01699   for (j = 0; j < mh->ncmds; j++)
01700   {
01701     lc = (struct load_command*)(((unsigned long)mh) + offset);
01702     if (LC_ID_DYLIB == lc->cmd)
01703     {
01704       retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
01705                   (unsigned long)lc);
01706     }
01707     offset += lc->cmdsize;
01708   }
01709   return retStr;
01710 }
01711 
01712 static const struct mach_header *
01713 lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
01714 {
01715   int i=_dyld_image_count();
01716   int j;
01717   const struct mach_header *mh=NULL;
01718   const char *id=NULL;
01719   for (j = 0; j < i; j++)
01720   {
01721     id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
01722     if ((id) && (!strcmp(id,name)))
01723     {
01724       mh=_dyld_get_image_header(j);
01725       break;
01726     }
01727   }
01728   return mh;
01729 }
01730 
01731 static NSSymbol
01732 lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
01733   const char *symbol;
01734   const struct mach_header *mh;
01735 {
01736   /* Safe to assume our mh is good */
01737   int j;
01738   struct load_command *lc;
01739   unsigned long offset = sizeof(struct mach_header);
01740   NSSymbol retSym = 0;
01741   const struct mach_header *mh1;
01742   if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
01743   {
01744     for (j = 0; j < mh->ncmds; j++)
01745     {
01746       lc = (struct load_command*)(((unsigned long)mh) + offset);
01747       if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
01748       {
01749         mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
01750                     (unsigned long)lc));
01751         if (!mh1)
01752         {
01753           /* Maybe NSAddImage can find it */
01754           mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
01755                     (unsigned long)lc),
01756                     NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
01757                     NSADDIMAGE_OPTION_WITH_SEARCHING +
01758                     NSADDIMAGE_OPTION_RETURN_ON_ERROR );
01759         }
01760         if (mh1)
01761         {
01762           retSym = ltdl_NSLookupSymbolInImage(mh1,
01763                       symbol,
01764                       NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
01765                       | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
01766                       );
01767           if (retSym) break;
01768         }
01769       }
01770       offset += lc->cmdsize;
01771     }
01772   }
01773   return retSym;
01774 }
01775 
01776 static int
01777 sys_dyld_init()
01778 {
01779   int retCode = 0;
01780   int err = 0;
01781   if (!_dyld_present()) {
01782     retCode=1;
01783   }
01784   else {
01785       err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
01786       err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
01787       err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
01788       err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
01789     }
01790  return retCode;
01791 }
01792 
01793 static lt_module
01794 sys_dyld_open (loader_data, filename)
01795      lt_user_data loader_data;
01796      const char *filename;
01797 {
01798   lt_module   module   = 0;
01799   NSObjectFileImage ofi = 0;
01800   NSObjectFileImageReturnCode ofirc;
01801 
01802     if (!filename)
01803       return (lt_module)-1;
01804   ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
01805   switch (ofirc)
01806   {
01807     case NSObjectFileImageSuccess:
01808       module = NSLinkModule(ofi, filename,
01809             NSLINKMODULE_OPTION_RETURN_ON_ERROR
01810              | NSLINKMODULE_OPTION_PRIVATE
01811              | NSLINKMODULE_OPTION_BINDNOW);
01812       NSDestroyObjectFileImage(ofi);
01813       if (module)
01814         ltdl_NSMakePrivateModulePublic(module);
01815       break;
01816     case NSObjectFileImageInappropriateFile:
01817         if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
01818         {
01819         module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
01820         break;
01821       }
01822     default:
01823       LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
01824       return 0;
01825   }
01826   if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
01827   return module;
01828 }
01829 
01830 static int
01831 sys_dyld_close (loader_data, module)
01832      lt_user_data loader_data;
01833      lt_module module;
01834 {
01835   int retCode = 0;
01836   int flags = 0;
01837   if (module == (lt_module)-1) return 0;
01838 #ifdef __BIG_ENDIAN__
01839     if (((struct mach_header *)module)->magic == MH_MAGIC)
01840 #else
01841     if (((struct mach_header *)module)->magic == MH_CIGAM)
01842 #endif
01843   {
01844     LT_DLMUTEX_SETERROR("Can not close a dylib");
01845     retCode = 1;
01846   }
01847   else
01848   {
01849 #if 1
01850 /* Currently, if a module contains c++ static destructors and it is unloaded, we
01851    get a segfault in atexit(), due to compiler and dynamic loader differences of
01852    opinion, this works around that.
01853 */
01854     if ((const struct section *)NULL !=
01855        getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
01856        "__DATA","__mod_term_func"))
01857     {
01858       flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
01859     }
01860 #endif
01861 #ifdef __ppc__
01862       flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
01863 #endif
01864     if (!NSUnLinkModule(module,flags))
01865     {
01866       retCode=1;
01867       LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
01868     }
01869   }
01870 
01871  return retCode;
01872 }
01873 
01874 static lt_ptr
01875 sys_dyld_sym (loader_data, module, symbol)
01876      lt_user_data loader_data;
01877      lt_module module;
01878      const char *symbol;
01879 {
01880   lt_ptr address = 0;
01881     NSSymbol *nssym = 0;
01882     void *unused;
01883     const struct mach_header *mh=NULL;
01884     char saveError[256] = "Symbol not found";
01885     if (module == (lt_module)-1)
01886     {
01887       _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
01888       return address;
01889     }
01890 #ifdef __BIG_ENDIAN__
01891     if (((struct mach_header *)module)->magic == MH_MAGIC)
01892 #else
01893     if (((struct mach_header *)module)->magic == MH_CIGAM)
01894 #endif
01895     {
01896         if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
01897         {
01898           mh=module;
01899       if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
01900       {
01901         nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
01902                       symbol,
01903                       NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
01904                       | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
01905                       );
01906       }
01907       }
01908 
01909     }
01910   else {
01911   nssym = NSLookupSymbolInModule(module, symbol);
01912   }
01913   if (!nssym)
01914   {
01915     strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
01916     saveError[255] = 0;
01917     if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
01918     nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
01919   }
01920   if (!nssym)
01921   {
01922     LT_DLMUTEX_SETERROR (saveError);
01923     return NULL;
01924   }
01925   return NSAddressOfSymbol(nssym);
01926 }
01927 
01928 static struct lt_user_dlloader sys_dyld =
01929   { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
01930 
01931 
01932 #endif /* HAVE_DYLD */
01933 
01934 
01935 /* --- DLPREOPEN() INTERFACE LOADER --- */
01936 
01937 
01938 /* emulate dynamic linking using preloaded_symbols */
01939 
01940 typedef struct lt_dlsymlists_t
01941 {
01942   struct lt_dlsymlists_t       *next;
01943   const lt_dlsymlist         *syms;
01944 } lt_dlsymlists_t;
01945 
01946 static  const lt_dlsymlist     *default_preloaded_symbols = 0;
01947 static  lt_dlsymlists_t        *preloaded_symbols   = 0;
01948 
01949 static int
01950 presym_init (loader_data)
01951      lt_user_data loader_data;
01952 {
01953   int errors = 0;
01954 
01955   LT_DLMUTEX_LOCK ();
01956 
01957   preloaded_symbols = 0;
01958   if (default_preloaded_symbols)
01959     {
01960       errors = lt_dlpreload (default_preloaded_symbols);
01961     }
01962 
01963   LT_DLMUTEX_UNLOCK ();
01964 
01965   return errors;
01966 }
01967 
01968 static int
01969 presym_free_symlists ()
01970 {
01971   lt_dlsymlists_t *lists;
01972 
01973   LT_DLMUTEX_LOCK ();
01974 
01975   lists = preloaded_symbols;
01976   while (lists)
01977     {
01978       lt_dlsymlists_t *tmp = lists;
01979 
01980       lists = lists->next;
01981       LT_DLFREE (tmp);
01982     }
01983   preloaded_symbols = 0;
01984 
01985   LT_DLMUTEX_UNLOCK ();
01986 
01987   return 0;
01988 }
01989 
01990 static int
01991 presym_exit (loader_data)
01992      lt_user_data loader_data;
01993 {
01994   presym_free_symlists ();
01995   return 0;
01996 }
01997 
01998 static int
01999 presym_add_symlist (preloaded)
02000      const lt_dlsymlist *preloaded;
02001 {
02002   lt_dlsymlists_t *tmp;
02003   lt_dlsymlists_t *lists;
02004   int      errors   = 0;
02005 
02006   LT_DLMUTEX_LOCK ();
02007 
02008   lists = preloaded_symbols;
02009   while (lists)
02010     {
02011       if (lists->syms == preloaded)
02012   {
02013     goto done;
02014   }
02015       lists = lists->next;
02016     }
02017 
02018   tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
02019   if (tmp)
02020     {
02021       memset (tmp, 0, sizeof(lt_dlsymlists_t));
02022       tmp->syms = preloaded;
02023       tmp->next = preloaded_symbols;
02024       preloaded_symbols = tmp;
02025     }
02026   else
02027     {
02028       ++errors;
02029     }
02030 
02031  done:
02032   LT_DLMUTEX_UNLOCK ();
02033   return errors;
02034 }
02035 
02036 static lt_module
02037 presym_open (loader_data, filename)
02038      lt_user_data loader_data;
02039      const char *filename;
02040 {
02041   lt_dlsymlists_t *lists;
02042   lt_module    module = (lt_module) 0;
02043 
02044   LT_DLMUTEX_LOCK ();
02045   lists = preloaded_symbols;
02046 
02047   if (!lists)
02048     {
02049       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
02050       goto done;
02051     }
02052 
02053   /* Can't use NULL as the reflective symbol header, as NULL is
02054      used to mark the end of the entire symbol list.  Self-dlpreopened
02055      symbols follow this magic number, chosen to be an unlikely
02056      clash with a real module name.  */
02057   if (!filename)
02058     {
02059       filename = "@PROGRAM@";
02060     }
02061 
02062   while (lists)
02063     {
02064       const lt_dlsymlist *syms = lists->syms;
02065 
02066       while (syms->name)
02067   {
02068     if (!syms->address && strcmp(syms->name, filename) == 0)
02069       {
02070         module = (lt_module) syms;
02071         goto done;
02072       }
02073     ++syms;
02074   }
02075 
02076       lists = lists->next;
02077     }
02078 
02079   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
02080 
02081  done:
02082   LT_DLMUTEX_UNLOCK ();
02083   return module;
02084 }
02085 
02086 static int
02087 presym_close (loader_data, module)
02088      lt_user_data loader_data;
02089      lt_module module;
02090 {
02091   /* Just to silence gcc -Wall */
02092   module = 0;
02093   return 0;
02094 }
02095 
02096 static lt_ptr
02097 presym_sym (loader_data, module, symbol)
02098      lt_user_data loader_data;
02099      lt_module module;
02100      const char *symbol;
02101 {
02102   lt_dlsymlist *syms = (lt_dlsymlist*) module;
02103 
02104   ++syms;
02105   while (syms->address)
02106     {
02107       if (strcmp(syms->name, symbol) == 0)
02108   {
02109     return syms->address;
02110   }
02111 
02112     ++syms;
02113   }
02114 
02115   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
02116 
02117   return 0;
02118 }
02119 
02120 static struct lt_user_dlloader presym = {
02121   0, presym_open, presym_close, presym_sym, presym_exit, 0
02122 };
02123 
02124 
02125 
02126 
02127 
02128 /* --- DYNAMIC MODULE LOADING --- */
02129 
02130 
02131 /* The type of a function used at each iteration of  foreach_dirinpath().  */
02132 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
02133              lt_ptr data2));
02134 
02135 static  int foreach_dirinpath     LT_PARAMS((const char *search_path,
02136              const char *base_name,
02137              foreach_callback_func *func,
02138              lt_ptr data1, lt_ptr data2));
02139 
02140 static  int find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
02141              lt_ptr ignored));
02142 static  int find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
02143              lt_ptr ignored));
02144 static  int foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
02145              lt_ptr data2));
02146 
02147 
02148 static  int     canonicalize_path     LT_PARAMS((const char *path,
02149              char **pcanonical));
02150 static  int argzize_path        LT_PARAMS((const char *path,
02151              char **pargz,
02152              size_t *pargz_len));
02153 static  FILE   *find_file       LT_PARAMS((const char *search_path,
02154              const char *base_name,
02155              char **pdir));
02156 static  lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
02157              const char *base_name,
02158              lt_dlhandle *handle));
02159 static  int find_module       LT_PARAMS((lt_dlhandle *handle,
02160              const char *dir,
02161              const char *libdir,
02162              const char *dlname,
02163              const char *old_name,
02164              int installed));
02165 static  int free_vars       LT_PARAMS((char *dlname, char *oldname,
02166              char *libdir, char *deplibs));
02167 static  int load_deplibs        LT_PARAMS((lt_dlhandle handle,
02168              char *deplibs));
02169 static  int trim          LT_PARAMS((char **dest,
02170              const char *str));
02171 static  int try_dlopen        LT_PARAMS((lt_dlhandle *handle,
02172              const char *filename));
02173 static  int tryall_dlopen       LT_PARAMS((lt_dlhandle *handle,
02174              const char *filename));
02175 static  int unload_deplibs        LT_PARAMS((lt_dlhandle handle));
02176 static  int lt_argz_insert        LT_PARAMS((char **pargz,
02177              size_t *pargz_len,
02178              char *before,
02179              const char *entry));
02180 static  int lt_argz_insertinorder LT_PARAMS((char **pargz,
02181              size_t *pargz_len,
02182              const char *entry));
02183 static  int lt_argz_insertdir     LT_PARAMS((char **pargz,
02184              size_t *pargz_len,
02185              const char *dirnam,
02186              struct dirent *dp));
02187 static  int lt_dlpath_insertdir   LT_PARAMS((char **ppath,
02188              char *before,
02189              const char *dir));
02190 static  int list_files_by_dir     LT_PARAMS((const char *dirnam,
02191              char **pargz,
02192              size_t *pargz_len));
02193 static  int file_not_found        LT_PARAMS((void));
02194 
02195 static  char         *user_search_path= 0;
02196 static  lt_dlloader    *loaders   = 0;
02197 static  lt_dlhandle handles   = 0;
02198 static  int   initialized   = 0;
02199 
02200 /* Initialize libltdl. */
02201 int
02202 lt_dlinit ()
02203 {
02204   int       errors   = 0;
02205 
02206   LT_DLMUTEX_LOCK ();
02207 
02208   /* Initialize only at first call. */
02209   if (++initialized == 1)
02210     {
02211       handles = 0;
02212       user_search_path = 0; /* empty search path */
02213 
02214 #if HAVE_LIBDL
02215       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
02216 #endif
02217 #if HAVE_SHL_LOAD
02218       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
02219 #endif
02220 #ifdef __WINDOWS__
02221       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
02222 #endif
02223 #ifdef __BEOS__
02224       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
02225 #endif
02226 #if HAVE_DLD
02227       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
02228 #endif
02229 #if HAVE_DYLD
02230        errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
02231        errors += sys_dyld_init();
02232 #endif
02233       errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
02234 
02235       if (presym_init (presym.dlloader_data))
02236   {
02237     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
02238     ++errors;
02239   }
02240       else if (errors != 0)
02241   {
02242     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
02243     ++errors;
02244   }
02245     }
02246 
02247   LT_DLMUTEX_UNLOCK ();
02248 
02249   return errors;
02250 }
02251 
02252 int
02253 lt_dlpreload (preloaded)
02254      const lt_dlsymlist *preloaded;
02255 {
02256   int errors = 0;
02257 
02258   if (preloaded)
02259     {
02260       errors = presym_add_symlist (preloaded);
02261     }
02262   else
02263     {
02264       presym_free_symlists();
02265 
02266       LT_DLMUTEX_LOCK ();
02267       if (default_preloaded_symbols)
02268   {
02269     errors = lt_dlpreload (default_preloaded_symbols);
02270   }
02271       LT_DLMUTEX_UNLOCK ();
02272     }
02273 
02274   return errors;
02275 }
02276 
02277 int
02278 lt_dlpreload_default (preloaded)
02279      const lt_dlsymlist *preloaded;
02280 {
02281   LT_DLMUTEX_LOCK ();
02282   default_preloaded_symbols = preloaded;
02283   LT_DLMUTEX_UNLOCK ();
02284   return 0;
02285 }
02286 
02287 int
02288 lt_dlexit ()
02289 {
02290   /* shut down libltdl */
02291   lt_dlloader *loader;
02292   int        errors   = 0;
02293 
02294   LT_DLMUTEX_LOCK ();
02295   loader = loaders;
02296 
02297   if (!initialized)
02298     {
02299       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
02300       ++errors;
02301       goto done;
02302     }
02303 
02304   /* shut down only at last call. */
02305   if (--initialized == 0)
02306     {
02307       int level;
02308 
02309       while (handles && LT_DLIS_RESIDENT (handles))
02310   {
02311     handles = handles->next;
02312   }
02313 
02314       /* close all modules */
02315       for (level = 1; handles; ++level)
02316   {
02317     lt_dlhandle cur = handles;
02318     int saw_nonresident = 0;
02319 
02320     while (cur)
02321       {
02322         lt_dlhandle tmp = cur;
02323         cur = cur->next;
02324         if (!LT_DLIS_RESIDENT (tmp))
02325     saw_nonresident = 1;
02326         if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
02327     {
02328       if (lt_dlclose (tmp))
02329         {
02330           ++errors;
02331         }
02332     }
02333       }
02334     /* done if only resident modules are left */
02335     if (!saw_nonresident)
02336       break;
02337   }
02338 
02339       /* close all loaders */
02340       while (loader)
02341   {
02342     lt_dlloader *next = loader->next;
02343     lt_user_data data = loader->dlloader_data;
02344     if (loader->dlloader_exit && loader->dlloader_exit (data))
02345       {
02346         ++errors;
02347       }
02348 
02349     LT_DLMEM_REASSIGN (loader, next);
02350   }
02351       loaders = 0;
02352     }
02353 
02354  done:
02355   LT_DLMUTEX_UNLOCK ();
02356   return errors;
02357 }
02358 
02359 static int
02360 tryall_dlopen (handle, filename)
02361      lt_dlhandle *handle;
02362      const char *filename;
02363 {
02364   lt_dlhandle  cur;
02365   lt_dlloader   *loader;
02366   const char  *saved_error;
02367   int    errors   = 0;
02368 
02369   LT_DLMUTEX_GETERROR (saved_error);
02370   LT_DLMUTEX_LOCK ();
02371 
02372   cur  = handles;
02373   loader = loaders;
02374 
02375   /* check whether the module was already opened */
02376   while (cur)
02377     {
02378       /* try to dlopen the program itself? */
02379       if (!cur->info.filename && !filename)
02380   {
02381     break;
02382   }
02383 
02384       if (cur->info.filename && filename
02385     && strcmp (cur->info.filename, filename) == 0)
02386   {
02387     break;
02388   }
02389 
02390       cur = cur->next;
02391     }
02392 
02393   if (cur)
02394     {
02395       ++cur->info.ref_count;
02396       *handle = cur;
02397       goto done;
02398     }
02399 
02400   cur = *handle;
02401   if (filename)
02402     {
02403       /* Comment out the check of file permissions using access.
02404    This call seems to always return -1 with error EACCES.
02405       */
02406       /* We need to catch missing file errors early so that
02407    file_not_found() can detect what happened.
02408       if (access (filename, R_OK) != 0)
02409   {
02410     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
02411     ++errors;
02412     goto done;
02413   } */
02414 
02415       cur->info.filename = lt_estrdup (filename);
02416       if (!cur->info.filename)
02417   {
02418     ++errors;
02419     goto done;
02420   }
02421     }
02422   else
02423     {
02424       cur->info.filename = 0;
02425     }
02426 
02427   while (loader)
02428     {
02429       lt_user_data data = loader->dlloader_data;
02430 
02431       cur->module = loader->module_open (data, filename);
02432 
02433       if (cur->module != 0)
02434   {
02435     break;
02436   }
02437       loader = loader->next;
02438     }
02439 
02440   if (!loader)
02441     {
02442       LT_DLFREE (cur->info.filename);
02443       ++errors;
02444       goto done;
02445     }
02446 
02447   cur->loader = loader;
02448   LT_DLMUTEX_SETERROR (saved_error);
02449 
02450  done:
02451   LT_DLMUTEX_UNLOCK ();
02452 
02453   return errors;
02454 }
02455 
02456 static int
02457 tryall_dlopen_module (handle, prefix, dirname, dlname)
02458      lt_dlhandle *handle;
02459      const char *prefix;
02460      const char *dirname;
02461      const char *dlname;
02462 {
02463   int      error  = 0;
02464   char     *filename  = 0;
02465   size_t   filename_len = 0;
02466   size_t   dirname_len  = LT_STRLEN (dirname);
02467 
02468   assert (handle);
02469   assert (dirname);
02470   assert (dlname);
02471 #ifdef LT_DIRSEP_CHAR
02472   /* Only canonicalized names (i.e. with DIRSEP chars already converted)
02473      should make it into this function:  */
02474   assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
02475 #endif
02476 
02477   if (dirname_len > 0)
02478     if (dirname[dirname_len -1] == '/')
02479       --dirname_len;
02480   filename_len = dirname_len + 1 + LT_STRLEN (dlname);
02481 
02482   /* Allocate memory, and combine DIRNAME and MODULENAME into it.
02483      The PREFIX (if any) is handled below.  */
02484   filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
02485   if (!filename)
02486     return 1;
02487 
02488   sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
02489 
02490   /* Now that we have combined DIRNAME and MODULENAME, if there is
02491      also a PREFIX to contend with, simply recurse with the arguments
02492      shuffled.  Otherwise, attempt to open FILENAME as a module.  */
02493   if (prefix)
02494     {
02495       error += tryall_dlopen_module (handle,
02496              (const char *) 0, prefix, filename);
02497     }
02498   else if (tryall_dlopen (handle, filename) != 0)
02499     {
02500       ++error;
02501     }
02502 
02503   LT_DLFREE (filename);
02504   return error;
02505 }
02506 
02507 static int
02508 find_module (handle, dir, libdir, dlname, old_name, installed)
02509      lt_dlhandle *handle;
02510      const char *dir;
02511      const char *libdir;
02512      const char *dlname;
02513      const char *old_name;
02514      int installed;
02515 {
02516   /* Try to open the old library first; if it was dlpreopened,
02517      we want the preopened version of it, even if a dlopenable
02518      module is available.  */
02519   if (old_name && tryall_dlopen (handle, old_name) == 0)
02520     {
02521       return 0;
02522     }
02523 
02524   /* Try to open the dynamic library.  */
02525   if (dlname)
02526     {
02527       /* try to open the installed module */
02528       if (installed && libdir)
02529   {
02530     if (tryall_dlopen_module (handle,
02531             (const char *) 0, libdir, dlname) == 0)
02532       return 0;
02533   }
02534 
02535       /* try to open the not-installed module */
02536       if (!installed)
02537   {
02538     if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
02539       return 0;
02540   }
02541 
02542       /* maybe it was moved to another directory */
02543       {
02544     if (tryall_dlopen_module (handle,
02545             (const char *) 0, dir, dlname) == 0)
02546       return 0;
02547       }
02548     }
02549 
02550   return 1;
02551 }
02552 
02553 
02554 static int
02555 canonicalize_path (path, pcanonical)
02556      const char *path;
02557      char **pcanonical;
02558 {
02559   char *canonical = 0;
02560 
02561   assert (path && *path);
02562   assert (pcanonical);
02563 
02564   canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
02565   if (!canonical)
02566     return 1;
02567 
02568   {
02569     size_t dest = 0;
02570     size_t src;
02571     for (src = 0; path[src] != LT_EOS_CHAR; ++src)
02572       {
02573   /* Path separators are not copied to the beginning or end of
02574      the destination, or if another separator would follow
02575      immediately.  */
02576   if (path[src] == LT_PATHSEP_CHAR)
02577     {
02578       if ((dest == 0)
02579     || (path[1+ src] == LT_PATHSEP_CHAR)
02580     || (path[1+ src] == LT_EOS_CHAR))
02581         continue;
02582     }
02583 
02584   /* Anything other than a directory separator is copied verbatim.  */
02585   if ((path[src] != '/')
02586 #ifdef LT_DIRSEP_CHAR
02587       && (path[src] != LT_DIRSEP_CHAR)
02588 #endif
02589       )
02590     {
02591       canonical[dest++] = path[src];
02592     }
02593   /* Directory separators are converted and copied only if they are
02594      not at the end of a path -- i.e. before a path separator or
02595      NULL terminator.  */
02596   else if ((path[1+ src] != LT_PATHSEP_CHAR)
02597      && (path[1+ src] != LT_EOS_CHAR)
02598 #ifdef LT_DIRSEP_CHAR
02599      && (path[1+ src] != LT_DIRSEP_CHAR)
02600 #endif
02601      && (path[1+ src] != '/'))
02602     {
02603       canonical[dest++] = '/';
02604     }
02605       }
02606 
02607     /* Add an end-of-string marker at the end.  */
02608     canonical[dest] = LT_EOS_CHAR;
02609   }
02610 
02611   /* Assign new value.  */
02612   *pcanonical = canonical;
02613 
02614   return 0;
02615 }
02616 
02617 static int
02618 argzize_path (path, pargz, pargz_len)
02619      const char *path;
02620      char **pargz;
02621      size_t *pargz_len;
02622 {
02623   error_t error;
02624 
02625   assert (path);
02626   assert (pargz);
02627   assert (pargz_len);
02628 
02629   if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
02630     {
02631       switch (error)
02632   {
02633   case ENOMEM:
02634     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
02635     break;
02636   default:
02637     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
02638     break;
02639   }
02640 
02641       return 1;
02642     }
02643 
02644   return 0;
02645 }
02646 
02647 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
02648    of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
02649    non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
02650    it is appended to each SEARCH_PATH element before FUNC is called.  */
02651 static int
02652 foreach_dirinpath (search_path, base_name, func, data1, data2)
02653      const char *search_path;
02654      const char *base_name;
02655      foreach_callback_func *func;
02656      lt_ptr data1;
02657      lt_ptr data2;
02658 {
02659   int  result   = 0;
02660   int  filenamesize = 0;
02661   size_t lenbase  = LT_STRLEN (base_name);
02662   size_t argz_len = 0;
02663   char *argz    = 0;
02664   char *filename  = 0;
02665   char *canonical = 0;
02666 
02667   LT_DLMUTEX_LOCK ();
02668 
02669   if (!search_path || !*search_path)
02670     {
02671       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
02672       goto cleanup;
02673     }
02674 
02675   if (canonicalize_path (search_path, &canonical) != 0)
02676     goto cleanup;
02677 
02678   if (argzize_path (canonical, &argz, &argz_len) != 0)
02679     goto cleanup;
02680 
02681   {
02682     char *dir_name = 0;
02683     while ((dir_name = argz_next (argz, argz_len, dir_name)))
02684       {
02685   size_t lendir = LT_STRLEN (dir_name);
02686 
02687   if (lendir +1 +lenbase >= (size_t)filenamesize)
02688   {
02689     LT_DLFREE (filename);
02690     filenamesize  = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
02691     filename  = LT_EMALLOC (char, filenamesize);
02692     if (!filename)
02693       goto cleanup;
02694   }
02695 
02696   assert ((size_t)filenamesize > lendir);
02697   strcpy (filename, dir_name);
02698 
02699   if (base_name && *base_name)
02700     {
02701       if (filename[lendir -1] != '/')
02702         filename[lendir++] = '/';
02703       strcpy (filename +lendir, base_name);
02704     }
02705 
02706   if ((result = (*func) (filename, data1, data2)))
02707     {
02708       break;
02709     }
02710       }
02711   }
02712 
02713  cleanup:
02714   LT_DLFREE (argz);
02715   LT_DLFREE (canonical);
02716   LT_DLFREE (filename);
02717 
02718   LT_DLMUTEX_UNLOCK ();
02719 
02720   return result;
02721 }
02722 
02723 /* If FILEPATH can be opened, store the name of the directory component
02724    in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
02725    DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
02726 static int
02727 find_file_callback (filename, data1, data2)
02728      char *filename;
02729      lt_ptr data1;
02730      lt_ptr data2;
02731 {
02732   char       **pdir = (char **) data1;
02733   FILE       **pfile  = (FILE **) data2;
02734   int      is_done  = 0;
02735 
02736   assert (filename && *filename);
02737   assert (pdir);
02738   assert (pfile);
02739 
02740   if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
02741     {
02742       char *dirend = strrchr (filename, '/');
02743 
02744       if (dirend > filename)
02745   *dirend   = LT_EOS_CHAR;
02746 
02747       LT_DLFREE (*pdir);
02748       *pdir   = lt_estrdup (filename);
02749       is_done = (*pdir == 0) ? -1 : 1;
02750     }
02751 
02752   return is_done;
02753 }
02754 
02755 static FILE *
02756 find_file (search_path, base_name, pdir)
02757      const char *search_path;
02758      const char *base_name;
02759      char **pdir;
02760 {
02761   FILE *file = 0;
02762 
02763   foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
02764 
02765   return file;
02766 }
02767 
02768 static int
02769 find_handle_callback (filename, data, ignored)
02770      char *filename;
02771      lt_ptr data;
02772      lt_ptr ignored;
02773 {
02774   lt_dlhandle  *handle    = (lt_dlhandle *) data;
02775   int   notfound  = access (filename, R_OK);
02776 
02777   /* Bail out if file cannot be read...  */
02778   if (notfound)
02779     return 0;
02780 
02781   /* Try to dlopen the file, but do not continue searching in any
02782      case.  */
02783   if (tryall_dlopen (handle, filename) != 0)
02784     *handle = 0;
02785 
02786   return 1;
02787 }
02788 
02789 /* If HANDLE was found return it, otherwise return 0.  If HANDLE was
02790    found but could not be opened, *HANDLE will be set to 0.  */
02791 static lt_dlhandle *
02792 find_handle (search_path, base_name, handle)
02793      const char *search_path;
02794      const char *base_name;
02795      lt_dlhandle *handle;
02796 {
02797   if (!search_path)
02798     return 0;
02799 
02800   if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
02801         handle, 0))
02802     return 0;
02803 
02804   return handle;
02805 }
02806 
02807 static int
02808 load_deplibs (handle, deplibs)
02809      lt_dlhandle handle;
02810      char *deplibs;
02811 {
02812 #if LTDL_DLOPEN_DEPLIBS
02813   char  *p, *save_search_path = 0;
02814   int   depcount = 0;
02815   int i;
02816   char  **names = 0;
02817 #endif
02818   int errors = 0;
02819 
02820   handle->depcount = 0;
02821 
02822 #if LTDL_DLOPEN_DEPLIBS
02823   if (!deplibs)
02824     {
02825       return errors;
02826     }
02827   ++errors;
02828 
02829   LT_DLMUTEX_LOCK ();
02830   if (user_search_path)
02831     {
02832       save_search_path = lt_estrdup (user_search_path);
02833       if (!save_search_path)
02834   goto cleanup;
02835     }
02836 
02837   /* extract search paths and count deplibs */
02838   p = deplibs;
02839   while (*p)
02840     {
02841       if (!isspace ((int) *p))
02842   {
02843     char *end = p+1;
02844     while (*end && !isspace((int) *end))
02845       {
02846         ++end;
02847       }
02848 
02849     if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
02850       {
02851         char save = *end;
02852         *end = 0; /* set a temporary string terminator */
02853         if (lt_dladdsearchdir(p+2))
02854     {
02855       goto cleanup;
02856     }
02857         *end = save;
02858       }
02859     else
02860       {
02861         ++depcount;
02862       }
02863 
02864     p = end;
02865   }
02866       else
02867   {
02868     ++p;
02869   }
02870     }
02871 
02872   /* restore the old search path */
02873   LT_DLFREE (user_search_path);
02874   user_search_path = save_search_path;
02875 
02876   LT_DLMUTEX_UNLOCK ();
02877 
02878   if (!depcount)
02879     {
02880       errors = 0;
02881       goto cleanup;
02882     }
02883 
02884   names = LT_EMALLOC (char *, depcount * sizeof (char*));
02885   if (!names)
02886     goto cleanup;
02887 
02888   /* now only extract the actual deplibs */
02889   depcount = 0;
02890   p = deplibs;
02891   while (*p)
02892     {
02893       if (isspace ((int) *p))
02894   {
02895     ++p;
02896   }
02897       else
02898   {
02899     char *end = p+1;
02900     while (*end && !isspace ((int) *end))
02901       {
02902         ++end;
02903       }
02904 
02905     if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
02906       {
02907         char *name;
02908         char save = *end;
02909         *end = 0; /* set a temporary string terminator */
02910         if (strncmp(p, "-l", 2) == 0)
02911     {
02912       size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
02913       name = LT_EMALLOC (char, 1+ name_len);
02914       if (name)
02915         sprintf (name, "lib%s", p+2);
02916     }
02917         else
02918     name = lt_estrdup(p);
02919 
02920         if (!name)
02921     goto cleanup_names;
02922 
02923         names[depcount++] = name;
02924         *end = save;
02925       }
02926     p = end;
02927   }
02928     }
02929 
02930   /* load the deplibs (in reverse order)
02931      At this stage, don't worry if the deplibs do not load correctly,
02932      they may already be statically linked into the loading application
02933      for instance.  There will be a more enlightening error message
02934      later on if the loaded module cannot resolve all of its symbols.  */
02935   if (depcount)
02936     {
02937       int j = 0;
02938 
02939       handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
02940       if (!handle->deplibs)
02941   goto cleanup;
02942 
02943       for (i = 0; i < depcount; ++i)
02944   {
02945     handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
02946     if (handle->deplibs[j])
02947       {
02948         ++j;
02949       }
02950   }
02951 
02952       handle->depcount  = j;  /* Number of successfully loaded deplibs */
02953       errors    = 0;
02954     }
02955 
02956  cleanup_names:
02957   for (i = 0; i < depcount; ++i)
02958     {
02959       LT_DLFREE (names[i]);
02960     }
02961 
02962  cleanup:
02963   LT_DLFREE (names);
02964 #endif
02965 
02966   return errors;
02967 }
02968 
02969 static int
02970 unload_deplibs (handle)
02971      lt_dlhandle handle;
02972 {
02973   int i;
02974   int errors = 0;
02975 
02976   if (handle->depcount)
02977     {
02978       for (i = 0; i < handle->depcount; ++i)
02979   {
02980     if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
02981       {
02982         errors += lt_dlclose (handle->deplibs[i]);
02983       }
02984   }
02985     }
02986 
02987   return errors;
02988 }
02989 
02990 static int
02991 trim (dest, str)
02992      char **dest;
02993      const char *str;
02994 {
02995   /* remove the leading and trailing "'" from str
02996      and store the result in dest */
02997   const char *end   = strrchr (str, '\'');
02998   size_t len      = LT_STRLEN (str);
02999   char *tmp;
03000 
03001   LT_DLFREE (*dest);
03002 
03003   if (len > 3 && str[0] == '\'')
03004     {
03005       tmp = LT_EMALLOC (char, end - str);
03006       if (!tmp)
03007   return 1;
03008 
03009       strncpy(tmp, &str[1], (end - str) - 1);
03010       tmp[len-3] = LT_EOS_CHAR;
03011       *dest = tmp;
03012     }
03013   else
03014     {
03015       *dest = 0;
03016     }
03017 
03018   return 0;
03019 }
03020 
03021 static int
03022 free_vars (dlname, oldname, libdir, deplibs)
03023      char *dlname;
03024      char *oldname;
03025      char *libdir;
03026      char *deplibs;
03027 {
03028   LT_DLFREE (dlname);
03029   LT_DLFREE (oldname);
03030   LT_DLFREE (libdir);
03031   LT_DLFREE (deplibs);
03032 
03033   return 0;
03034 }
03035 
03036 static int
03037 try_dlopen (phandle, filename)
03038      lt_dlhandle *phandle;
03039      const char *filename;
03040 {
03041   const char *  ext   = 0;
03042   const char *  saved_error = 0;
03043   char *  canonical = 0;
03044   char *  base_name = 0;
03045   char *  dir   = 0;
03046   char *  name    = 0;
03047   int   errors    = 0;
03048   lt_dlhandle newhandle;
03049 
03050   assert (phandle);
03051   assert (*phandle == 0);
03052 
03053   LT_DLMUTEX_GETERROR (saved_error);
03054 
03055   /* dlopen self? */
03056   if (!filename)
03057     {
03058       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
03059       if (*phandle == 0)
03060   return 1;
03061 
03062       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
03063       newhandle = *phandle;
03064 
03065       /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
03066       LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
03067 
03068       if (tryall_dlopen (&newhandle, 0) != 0)
03069   {
03070     LT_DLFREE (*phandle);
03071     return 1;
03072   }
03073 
03074       goto register_handle;
03075     }
03076 
03077   assert (filename && *filename);
03078 
03079   /* Doing this immediately allows internal functions to safely
03080      assume only canonicalized paths are passed.  */
03081   if (canonicalize_path (filename, &canonical) != 0)
03082     {
03083       ++errors;
03084       goto cleanup;
03085     }
03086 
03087   /* If the canonical module name is a path (relative or absolute)
03088      then split it into a directory part and a name part.  */
03089   base_name = strrchr (canonical, '/');
03090   if (base_name)
03091     {
03092       size_t dirlen = (1+ base_name) - canonical;
03093 
03094       dir = LT_EMALLOC (char, 1+ dirlen);
03095       if (!dir)
03096   {
03097     ++errors;
03098     goto cleanup;
03099   }
03100 
03101       strncpy (dir, canonical, dirlen);
03102       dir[dirlen] = LT_EOS_CHAR;
03103 
03104       ++base_name;
03105     }
03106   else
03107     LT_DLMEM_REASSIGN (base_name, canonical);
03108 
03109   assert (base_name && *base_name);
03110 
03111   /* Check whether we are opening a libtool module (.la extension).  */
03112   ext = strrchr (base_name, '.');
03113   if (ext && strcmp (ext, archive_ext) == 0)
03114     {
03115       /* this seems to be a libtool module */
03116       FILE *  file   = 0;
03117       char *  dlname   = 0;
03118       char *  old_name = 0;
03119       char *  libdir   = 0;
03120       char *  deplibs  = 0;
03121       char *    line   = 0;
03122       size_t  line_len;
03123 
03124       /* if we can't find the installed flag, it is probably an
03125    installed libtool archive, produced with an old version
03126    of libtool */
03127       int installed = 1;
03128 
03129       /* extract the module name from the file name */
03130       name = LT_EMALLOC (char, ext - base_name + 1);
03131       if (!name)
03132   {
03133     ++errors;
03134     goto cleanup;
03135   }
03136 
03137       /* canonicalize the module name */
03138       {
03139         size_t i;
03140         for (i = 0; i < (size_t)(ext - base_name); ++i)
03141     {
03142       if (isalnum ((int)(base_name[i])))
03143         {
03144           name[i] = base_name[i];
03145         }
03146       else
03147         {
03148           name[i] = '_';
03149         }
03150     }
03151         name[ext - base_name] = LT_EOS_CHAR;
03152       }
03153 
03154       /* Now try to open the .la file.  If there is no directory name
03155          component, try to find it first in user_search_path and then other
03156          prescribed paths.  Otherwise (or in any case if the module was not
03157          yet found) try opening just the module name as passed.  */
03158       if (!dir)
03159   {
03160     const char *search_path;
03161 
03162     LT_DLMUTEX_LOCK ();
03163     search_path = user_search_path;
03164     if (search_path)
03165       file = find_file (user_search_path, base_name, &dir);
03166     LT_DLMUTEX_UNLOCK ();
03167 
03168     if (!file)
03169       {
03170         search_path = getenv (LTDL_SEARCHPATH_VAR);
03171         if (search_path)
03172     file = find_file (search_path, base_name, &dir);
03173       }
03174 
03175 #ifdef LTDL_SHLIBPATH_VAR
03176     if (!file)
03177       {
03178         search_path = getenv (LTDL_SHLIBPATH_VAR);
03179         if (search_path)
03180     file = find_file (search_path, base_name, &dir);
03181       }
03182 #endif
03183 #ifdef LTDL_SYSSEARCHPATH
03184     if (!file && sys_search_path)
03185       {
03186         file = find_file (sys_search_path, base_name, &dir);
03187       }
03188 #endif
03189   }
03190       if (!file)
03191   {
03192     file = fopen (filename, LT_READTEXT_MODE);
03193   }
03194 
03195       /* If we didn't find the file by now, it really isn't there.  Set
03196    the status flag, and bail out.  */
03197       if (!file)
03198   {
03199     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
03200     ++errors;
03201     goto cleanup;
03202   }
03203 
03204       line_len = LT_FILENAME_MAX;
03205       line = LT_EMALLOC (char, line_len);
03206       if (!line)
03207   {
03208     fclose (file);
03209     ++errors;
03210     goto cleanup;
03211   }
03212 
03213       /* read the .la file */
03214       while (!feof (file))
03215   {
03216     if (!fgets (line, (int) line_len, file))
03217       {
03218         break;
03219       }
03220 
03221     /* Handle the case where we occasionally need to read a line
03222        that is longer than the initial buffer size.  */
03223     while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
03224       {
03225         line = LT_DLREALLOC (char, line, line_len *2);
03226         if (!fgets (&line[line_len -1], (int) line_len +1, file))
03227     {
03228       break;
03229     }
03230         line_len *= 2;
03231       }
03232 
03233     if (line[0] == '\n' || line[0] == '#')
03234       {
03235         continue;
03236       }
03237 
03238 #undef  STR_DLNAME
03239 #define STR_DLNAME  "dlname="
03240     if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
03241       {
03242         errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
03243       }
03244 
03245 #undef  STR_OLD_LIBRARY
03246 #define STR_OLD_LIBRARY "old_library="
03247     else if (strncmp (line, STR_OLD_LIBRARY,
03248           sizeof (STR_OLD_LIBRARY) - 1) == 0)
03249       {
03250         errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
03251       }
03252 #undef  STR_LIBDIR
03253 #define STR_LIBDIR  "libdir="
03254     else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
03255       {
03256         errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
03257       }
03258 
03259 #undef  STR_DL_DEPLIBS
03260 #define STR_DL_DEPLIBS  "dependency_libs="
03261     else if (strncmp (line, STR_DL_DEPLIBS,
03262           sizeof (STR_DL_DEPLIBS) - 1) == 0)
03263       {
03264         errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
03265       }
03266     else if (strcmp (line, "installed=yes\n") == 0)
03267       {
03268         installed = 1;
03269       }
03270     else if (strcmp (line, "installed=no\n") == 0)
03271       {
03272         installed = 0;
03273       }
03274 
03275 #undef  STR_LIBRARY_NAMES
03276 #define STR_LIBRARY_NAMES "library_names="
03277     else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
03278           sizeof (STR_LIBRARY_NAMES) - 1) == 0)
03279       {
03280         char *last_libname;
03281         errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
03282         if (!errors
03283       && dlname
03284       && (last_libname = strrchr (dlname, ' ')) != 0)
03285     {
03286       last_libname = lt_estrdup (last_libname + 1);
03287       if (!last_libname)
03288         {
03289           ++errors;
03290           goto cleanup;
03291         }
03292       LT_DLMEM_REASSIGN (dlname, last_libname);
03293     }
03294       }
03295 
03296     if (errors)
03297       break;
03298   }
03299 
03300       fclose (file);
03301       LT_DLFREE (line);
03302 
03303       /* allocate the handle */
03304       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
03305       if (*phandle == 0)
03306   ++errors;
03307 
03308       if (errors)
03309   {
03310     free_vars (dlname, old_name, libdir, deplibs);
03311     LT_DLFREE (*phandle);
03312     goto cleanup;
03313   }
03314 
03315       assert (*phandle);
03316 
03317       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
03318       if (load_deplibs (*phandle, deplibs) == 0)
03319   {
03320     newhandle = *phandle;
03321     /* find_module may replace newhandle */
03322     if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
03323       {
03324         unload_deplibs (*phandle);
03325         ++errors;
03326       }
03327   }
03328       else
03329   {
03330     ++errors;
03331   }
03332 
03333       free_vars (dlname, old_name, libdir, deplibs);
03334       if (errors)
03335   {
03336     LT_DLFREE (*phandle);
03337     goto cleanup;
03338   }
03339 
03340       if (*phandle != newhandle)
03341   {
03342     unload_deplibs (*phandle);
03343   }
03344     }
03345   else
03346     {
03347       /* not a libtool module */
03348       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
03349       if (*phandle == 0)
03350   {
03351     ++errors;
03352     goto cleanup;
03353   }
03354 
03355       memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
03356       newhandle = *phandle;
03357 
03358       /* If the module has no directory name component, try to find it
03359    first in user_search_path and then other prescribed paths.
03360    Otherwise (or in any case if the module was not yet found) try
03361    opening just the module name as passed.  */
03362       if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
03363        && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
03364             &newhandle)
03365 #ifdef LTDL_SHLIBPATH_VAR
03366        && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
03367             &newhandle)
03368 #endif
03369 #ifdef LTDL_SYSSEARCHPATH
03370        && !find_handle (sys_search_path, base_name, &newhandle)
03371 #endif
03372        )))
03373   {
03374           if (tryall_dlopen (&newhandle, filename) != 0)
03375             {
03376               newhandle = NULL;
03377             }
03378   }
03379 
03380       if (!newhandle)
03381   {
03382     LT_DLFREE (*phandle);
03383     ++errors;
03384     goto cleanup;
03385   }
03386     }
03387 
03388  register_handle:
03389   LT_DLMEM_REASSIGN (*phandle, newhandle);
03390 
03391   if ((*phandle)->info.ref_count == 0)
03392     {
03393       (*phandle)->info.ref_count  = 1;
03394       LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
03395 
03396       LT_DLMUTEX_LOCK ();
03397       (*phandle)->next    = handles;
03398       handles     = *phandle;
03399       LT_DLMUTEX_UNLOCK ();
03400     }
03401 
03402   LT_DLMUTEX_SETERROR (saved_error);
03403 
03404  cleanup:
03405   LT_DLFREE (dir);
03406   LT_DLFREE (name);
03407   LT_DLFREE (canonical);
03408 
03409   return errors;
03410 }
03411 
03412 lt_dlhandle
03413 lt_dlopen (filename)
03414      const char *filename;
03415 {
03416   lt_dlhandle handle = 0;
03417 
03418   /* Just incase we missed a code path in try_dlopen() that reports
03419      an error, but forgets to reset handle... */
03420   if (try_dlopen (&handle, filename) != 0)
03421     return 0;
03422 
03423   return handle;
03424 }
03425 
03426 /* If the last error messge store was `FILE_NOT_FOUND', then return
03427    non-zero.  */
03428 static int
03429 file_not_found ()
03430 {
03431   const char *error = 0;
03432 
03433   LT_DLMUTEX_GETERROR (error);
03434   if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
03435     return 1;
03436 
03437   return 0;
03438 }
03439 
03440 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
03441    open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
03442    and if a file is still not found try again with SHLIB_EXT appended
03443    instead.  */
03444 lt_dlhandle
03445 lt_dlopenext (filename)
03446      const char *filename;
03447 {
03448   lt_dlhandle handle    = 0;
03449   char *  tmp   = 0;
03450   char *  ext   = 0;
03451   size_t  len;
03452   int   errors    = 0;
03453 
03454   if (!filename)
03455     {
03456       return lt_dlopen (filename);
03457     }
03458 
03459   assert (filename);
03460 
03461   len = LT_STRLEN (filename);
03462   ext = strrchr (filename, '.');
03463 
03464   /* If FILENAME already bears a suitable extension, there is no need
03465      to try appending additional extensions.  */
03466   if (ext && ((strcmp (ext, archive_ext) == 0)
03467 #ifdef LTDL_SHLIB_EXT
03468         || (strcmp (ext, shlib_ext) == 0)
03469 #endif
03470       ))
03471     {
03472       return lt_dlopen (filename);
03473     }
03474 
03475   /* First try appending ARCHIVE_EXT.  */
03476   tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
03477   if (!tmp)
03478     return 0;
03479 
03480   strcpy (tmp, filename);
03481   strcat (tmp, archive_ext);
03482   errors = try_dlopen (&handle, tmp);
03483 
03484   /* If we found FILENAME, stop searching -- whether we were able to
03485      load the file as a module or not.  If the file exists but loading
03486      failed, it is better to return an error message here than to
03487      report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
03488      in the module search path.  */
03489   if (handle || ((errors > 0) && !file_not_found ()))
03490     {
03491       LT_DLFREE (tmp);
03492       return handle;
03493     }
03494 
03495 #ifdef LTDL_SHLIB_EXT
03496   /* Try appending SHLIB_EXT.   */
03497   if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
03498     {
03499       LT_DLFREE (tmp);
03500       tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
03501       if (!tmp)
03502   return 0;
03503 
03504       strcpy (tmp, filename);
03505     }
03506   else
03507     {
03508       tmp[len] = LT_EOS_CHAR;
03509     }
03510 
03511   strcat(tmp, shlib_ext);
03512   errors = try_dlopen (&handle, tmp);
03513 
03514   /* As before, if the file was found but loading failed, return now
03515      with the current error message.  */
03516   if (handle || ((errors > 0) && !file_not_found ()))
03517     {
03518       LT_DLFREE (tmp);
03519       return handle;
03520     }
03521 #endif
03522 
03523   /* Still here?  Then we really did fail to locate any of the file
03524      names we tried.  */
03525   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
03526   LT_DLFREE (tmp);
03527   return 0;
03528 }
03529 
03530 
03531 static int
03532 lt_argz_insert (pargz, pargz_len, before, entry)
03533      char **pargz;
03534      size_t *pargz_len;
03535      char *before;
03536      const char *entry;
03537 {
03538   error_t error;
03539 
03540   if ((error = argz_insert (pargz, pargz_len, before, entry)))
03541     {
03542       switch (error)
03543   {
03544   case ENOMEM:
03545     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
03546     break;
03547   default:
03548     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
03549     break;
03550   }
03551       return 1;
03552     }
03553 
03554   return 0;
03555 }
03556 
03557 static int
03558 lt_argz_insertinorder (pargz, pargz_len, entry)
03559      char **pargz;
03560      size_t *pargz_len;
03561      const char *entry;
03562 {
03563   char *before = 0;
03564 
03565   assert (pargz);
03566   assert (pargz_len);
03567   assert (entry && *entry);
03568 
03569   if (*pargz)
03570     while ((before = argz_next (*pargz, *pargz_len, before)))
03571       {
03572   int cmp = strcmp (entry, before);
03573 
03574   if (cmp < 0)  break;
03575   if (cmp == 0) return 0; /* No duplicates! */
03576       }
03577 
03578   return lt_argz_insert (pargz, pargz_len, before, entry);
03579 }
03580 
03581 static int
03582 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
03583      char **pargz;
03584      size_t *pargz_len;
03585      const char *dirnam;
03586      struct dirent *dp;
03587 {
03588   char   *buf     = 0;
03589   size_t buf_len    = 0;
03590   char   *end     = 0;
03591   size_t end_offset = 0;
03592   size_t dir_len    = 0;
03593   int    errors     = 0;
03594 
03595   assert (pargz);
03596   assert (pargz_len);
03597   assert (dp);
03598 
03599   dir_len = LT_STRLEN (dirnam);
03600   end     = dp->d_name + LT_D_NAMLEN(dp);
03601 
03602   /* Ignore version numbers.  */
03603   {
03604     char *p;
03605     for (p = end; p -1 > dp->d_name; --p)
03606       if (strchr (".0123456789", p[-1]) == 0)
03607   break;
03608 
03609     if (*p == '.')
03610       end = p;
03611   }
03612 
03613   /* Ignore filename extension.  */
03614   {
03615     char *p;
03616     for (p = end -1; p > dp->d_name; --p)
03617       if (*p == '.')
03618   {
03619     end = p;
03620     break;
03621   }
03622   }
03623 
03624   /* Prepend the directory name.  */
03625   end_offset  = end - dp->d_name;
03626   buf_len = dir_len + 1+ end_offset;
03627   buf   = LT_EMALLOC (char, 1+ buf_len);
03628   if (!buf)
03629     return ++errors;
03630 
03631   assert (buf);
03632 
03633   strcpy  (buf, dirnam);
03634   strcat  (buf, "/");
03635   strncat (buf, dp->d_name, end_offset);
03636   buf[buf_len] = LT_EOS_CHAR;
03637 
03638   /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
03639   if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
03640     ++errors;
03641 
03642   LT_DLFREE (buf);
03643 
03644   return errors;
03645 }
03646 
03647 static int
03648 list_files_by_dir (dirnam, pargz, pargz_len)
03649      const char *dirnam;
03650      char **pargz;
03651      size_t *pargz_len;
03652 {
03653   DIR *dirp   = 0;
03654   int    errors   = 0;
03655 
03656   assert (dirnam && *dirnam);
03657   assert (pargz);
03658   assert (pargz_len);
03659   assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
03660 
03661   dirp = opendir (dirnam);
03662   if (dirp)
03663     {
03664       struct dirent *dp = 0;
03665 
03666       while ((dp = readdir (dirp)))
03667   if (dp->d_name[0] != '.')
03668     if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
03669       {
03670         ++errors;
03671         break;
03672       }
03673 
03674       closedir (dirp);
03675     }
03676   else
03677     ++errors;
03678 
03679   return errors;
03680 }
03681 
03682 
03683 /* If there are any files in DIRNAME, call the function passed in
03684    DATA1 (with the name of each file and DATA2 as arguments).  */
03685 static int
03686 foreachfile_callback (dirname, data1, data2)
03687      char *dirname;
03688      lt_ptr data1;
03689      lt_ptr data2;
03690 {
03691   int (*func) LT_PARAMS((const char *filename, lt_ptr data))
03692   = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
03693 
03694   int   is_done  = 0;
03695   char   *argz     = 0;
03696   size_t  argz_len = 0;
03697 
03698   if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
03699     goto cleanup;
03700   if (!argz)
03701     goto cleanup;
03702 
03703   {
03704     char *filename = 0;
03705     while ((filename = argz_next (argz, argz_len, filename)))
03706       if ((is_done = (*func) (filename, data2)))
03707   break;
03708   }
03709 
03710  cleanup:
03711   LT_DLFREE (argz);
03712 
03713   return is_done;
03714 }
03715 
03716 
03717 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
03718    with DATA.  The filenames passed to FUNC would be suitable for
03719    passing to lt_dlopenext.  The extensions are stripped so that
03720    individual modules do not generate several entries (e.g. libfoo.la,
03721    libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
03722    then the same directories that lt_dlopen would search are examined.  */
03723 int
03724 lt_dlforeachfile (search_path, func, data)
03725      const char *search_path;
03726      int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
03727      lt_ptr data;
03728 {
03729   int is_done = 0;
03730 
03731   if (search_path)
03732     {
03733       /* If a specific path was passed, search only the directories
03734    listed in it.  */
03735       is_done = foreach_dirinpath (search_path, 0,
03736            foreachfile_callback, func, data);
03737     }
03738   else
03739     {
03740       /* Otherwise search the default paths.  */
03741       is_done = foreach_dirinpath (user_search_path, 0,
03742            foreachfile_callback, func, data);
03743       if (!is_done)
03744   {
03745     is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
03746                foreachfile_callback, func, data);
03747   }
03748 
03749 #ifdef LTDL_SHLIBPATH_VAR
03750       if (!is_done)
03751   {
03752     is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
03753                foreachfile_callback, func, data);
03754   }
03755 #endif
03756 #ifdef LTDL_SYSSEARCHPATH
03757       if (!is_done)
03758   {
03759     is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
03760                foreachfile_callback, func, data);
03761   }
03762 #endif
03763     }
03764 
03765   return is_done;
03766 }
03767 
03768 int
03769 lt_dlclose (handle)
03770      lt_dlhandle handle;
03771 {
03772   lt_dlhandle cur, last;
03773   int errors = 0;
03774 
03775   LT_DLMUTEX_LOCK ();
03776 
03777   /* check whether the handle is valid */
03778   last = cur = handles;
03779   while (cur && handle != cur)
03780     {
03781       last = cur;
03782       cur = cur->next;
03783     }
03784 
03785   if (!cur)
03786     {
03787       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
03788       ++errors;
03789       goto done;
03790     }
03791 
03792   handle->info.ref_count--;
03793 
03794   /* Note that even with resident modules, we must track the ref_count
03795      correctly incase the user decides to reset the residency flag
03796      later (even though the API makes no provision for that at the
03797      moment).  */
03798   if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
03799     {
03800       lt_user_data data = handle->loader->dlloader_data;
03801 
03802       if (handle != handles)
03803   {
03804     last->next = handle->next;
03805   }
03806       else
03807   {
03808     handles = handle->next;
03809   }
03810 
03811       errors += handle->loader->module_close (data, handle->module);
03812       errors += unload_deplibs(handle);
03813 
03814       /* It is up to the callers to free the data itself.  */
03815       LT_DLFREE (handle->caller_data);
03816 
03817       LT_DLFREE (handle->info.filename);
03818       LT_DLFREE (handle->info.name);
03819       LT_DLFREE (handle);
03820 
03821       goto done;
03822     }
03823 
03824   if (LT_DLIS_RESIDENT (handle))
03825     {
03826       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
03827       ++errors;
03828     }
03829 
03830  done:
03831   LT_DLMUTEX_UNLOCK ();
03832 
03833   return errors;
03834 }
03835 
03836 lt_ptr
03837 lt_dlsym (handle, symbol)
03838      lt_dlhandle handle;
03839      const char *symbol;
03840 {
03841   size_t lensym;
03842   char  lsym[LT_SYMBOL_LENGTH];
03843   char  *sym;
03844   lt_ptr address;
03845   lt_user_data data;
03846 
03847   if (!handle)
03848     {
03849       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
03850       return 0;
03851     }
03852 
03853   if (!symbol)
03854     {
03855       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
03856       return 0;
03857     }
03858 
03859   lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
03860           + LT_STRLEN (handle->info.name);
03861 
03862   if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
03863     {
03864       sym = lsym;
03865     }
03866   else
03867     {
03868       sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
03869       if (!sym)
03870   {
03871     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
03872     return 0;
03873   }
03874     }
03875 
03876   data = handle->loader->dlloader_data;
03877   if (handle->info.name)
03878     {
03879       const char *saved_error;
03880 
03881       LT_DLMUTEX_GETERROR (saved_error);
03882 
03883       /* this is a libtool module */
03884       if (handle->loader->sym_prefix)
03885   {
03886     strcpy(sym, handle->loader->sym_prefix);
03887     strcat(sym, handle->info.name);
03888   }
03889       else
03890   {
03891     strcpy(sym, handle->info.name);
03892   }
03893 
03894       strcat(sym, "_LTX_");
03895       strcat(sym, symbol);
03896 
03897       /* try "modulename_LTX_symbol" */
03898       address = handle->loader->find_sym (data, handle->module, sym);
03899       if (address)
03900   {
03901     if (sym != lsym)
03902       {
03903         LT_DLFREE (sym);
03904       }
03905     return address;
03906   }
03907       LT_DLMUTEX_SETERROR (saved_error);
03908     }
03909 
03910   /* otherwise try "symbol" */
03911   if (handle->loader->sym_prefix)
03912     {
03913       strcpy(sym, handle->loader->sym_prefix);
03914       strcat(sym, symbol);
03915     }
03916   else
03917     {
03918       strcpy(sym, symbol);
03919     }
03920 
03921   address = handle->loader->find_sym (data, handle->module, sym);
03922   if (sym != lsym)
03923     {
03924       LT_DLFREE (sym);
03925     }
03926 
03927   return address;
03928 }
03929 
03930 const char *
03931 lt_dlerror ()
03932 {
03933   const char *error;
03934 
03935   LT_DLMUTEX_GETERROR (error);
03936   LT_DLMUTEX_SETERROR (0);
03937 
03938   return error ? error : NULL;
03939 }
03940 
03941 static int
03942 lt_dlpath_insertdir (ppath, before, dir)
03943      char **ppath;
03944      char *before;
03945      const char *dir;
03946 {
03947   int    errors   = 0;
03948   char  *canonical  = 0;
03949   char  *argz   = 0;
03950   size_t argz_len = 0;
03951 
03952   assert (ppath);
03953   assert (dir && *dir);
03954 
03955   if (canonicalize_path (dir, &canonical) != 0)
03956     {
03957       ++errors;
03958       goto cleanup;
03959     }
03960 
03961   assert (canonical && *canonical);
03962 
03963   /* If *PPATH is empty, set it to DIR.  */
03964   if (*ppath == 0)
03965     {
03966       assert (!before);   /* BEFORE cannot be set without PPATH.  */
03967       assert (dir);   /* Without DIR, don't call this function!  */
03968 
03969       *ppath = lt_estrdup (dir);
03970       if (*ppath == 0)
03971   ++errors;
03972 
03973       return errors;
03974     }
03975 
03976   assert (ppath && *ppath);
03977 
03978   if (argzize_path (*ppath, &argz, &argz_len) != 0)
03979     {
03980       ++errors;
03981       goto cleanup;
03982     }
03983 
03984   /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
03985      if *PPATH is already canonicalized, and hence does not change length
03986      with respect to ARGZ.  We canonicalize each entry as it is added to
03987      the search path, and don't call this function with (uncanonicalized)
03988      user paths, so this is a fair assumption.  */
03989   if (before)
03990     {
03991       assert (*ppath <= before);
03992       assert (before - *ppath <= (int)strlen (*ppath));
03993 
03994       before = before - *ppath + argz;
03995     }
03996 
03997   if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
03998     {
03999       ++errors;
04000       goto cleanup;
04001     }
04002 
04003   argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
04004   LT_DLMEM_REASSIGN (*ppath,  argz);
04005 
04006  cleanup:
04007   LT_DLFREE (canonical);
04008   LT_DLFREE (argz);
04009 
04010   return errors;
04011 }
04012 
04013 int
04014 lt_dladdsearchdir (search_dir)
04015      const char *search_dir;
04016 {
04017   int errors = 0;
04018 
04019   if (search_dir && *search_dir)
04020     {
04021       LT_DLMUTEX_LOCK ();
04022       if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
04023   ++errors;
04024       LT_DLMUTEX_UNLOCK ();
04025     }
04026 
04027   return errors;
04028 }
04029 
04030 int
04031 lt_dlinsertsearchdir (before, search_dir)
04032      const char *before;
04033      const char *search_dir;
04034 {
04035   int errors = 0;
04036 
04037   if (before)
04038     {
04039       LT_DLMUTEX_LOCK ();
04040       if ((before < user_search_path)
04041     || (before >= user_search_path + LT_STRLEN (user_search_path)))
04042   {
04043     LT_DLMUTEX_UNLOCK ();
04044     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
04045     return 1;
04046   }
04047       LT_DLMUTEX_UNLOCK ();
04048     }
04049 
04050   if (search_dir && *search_dir)
04051     {
04052       LT_DLMUTEX_LOCK ();
04053       if (lt_dlpath_insertdir (&user_search_path,
04054              (char *) before, search_dir) != 0)
04055   {
04056     ++errors;
04057   }
04058       LT_DLMUTEX_UNLOCK ();
04059     }
04060 
04061   return errors;
04062 }
04063 
04064 int
04065 lt_dlsetsearchpath (search_path)
04066      const char *search_path;
04067 {
04068   int   errors      = 0;
04069 
04070   LT_DLMUTEX_LOCK ();
04071   LT_DLFREE (user_search_path);
04072   LT_DLMUTEX_UNLOCK ();
04073 
04074   if (!search_path || !LT_STRLEN (search_path))
04075     {
04076       return errors;
04077     }
04078 
04079   LT_DLMUTEX_LOCK ();
04080   if (canonicalize_path (search_path, &user_search_path) != 0)
04081     ++errors;
04082   LT_DLMUTEX_UNLOCK ();
04083 
04084   return errors;
04085 }
04086 
04087 const char *
04088 lt_dlgetsearchpath ()
04089 {
04090   const char *saved_path;
04091 
04092   LT_DLMUTEX_LOCK ();
04093   saved_path = user_search_path;
04094   LT_DLMUTEX_UNLOCK ();
04095 
04096   return saved_path;
04097 }
04098 
04099 int
04100 lt_dlmakeresident (handle)
04101      lt_dlhandle handle;
04102 {
04103   int errors = 0;
04104 
04105   if (!handle)
04106     {
04107       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
04108       ++errors;
04109     }
04110   else
04111     {
04112       LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
04113     }
04114 
04115   return errors;
04116 }
04117 
04118 int
04119 lt_dlisresident (handle)
04120      lt_dlhandle handle;
04121 {
04122   if (!handle)
04123     {
04124       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
04125       return -1;
04126     }
04127 
04128   return LT_DLIS_RESIDENT (handle);
04129 }
04130 
04131 
04132 
04133 
04134 /* --- MODULE INFORMATION --- */
04135 
04136 const lt_dlinfo *
04137 lt_dlgetinfo (handle)
04138      lt_dlhandle handle;
04139 {
04140   if (!handle)
04141     {
04142       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
04143       return 0;
04144     }
04145 
04146   return &(handle->info);
04147 }
04148 
04149 lt_dlhandle
04150 lt_dlhandle_next (place)
04151      lt_dlhandle place;
04152 {
04153   return place ? place->next : handles;
04154 }
04155 
04156 int
04157 lt_dlforeach (func, data)
04158      int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
04159      lt_ptr data;
04160 {
04161   int errors = 0;
04162   lt_dlhandle cur;
04163 
04164   LT_DLMUTEX_LOCK ();
04165 
04166   cur = handles;
04167   while (cur)
04168     {
04169       lt_dlhandle tmp = cur;
04170 
04171       cur = cur->next;
04172       if ((*func) (tmp, data))
04173   {
04174     ++errors;
04175     break;
04176   }
04177     }
04178 
04179   LT_DLMUTEX_UNLOCK ();
04180 
04181   return errors;
04182 }
04183 
04184 lt_dlcaller_id
04185 lt_dlcaller_register ()
04186 {
04187   static lt_dlcaller_id last_caller_id = 0;
04188   int result;
04189 
04190   LT_DLMUTEX_LOCK ();
04191   result = ++last_caller_id;
04192   LT_DLMUTEX_UNLOCK ();
04193 
04194   return result;
04195 }
04196 
04197 lt_ptr
04198 lt_dlcaller_set_data (key, handle, data)
04199      lt_dlcaller_id key;
04200      lt_dlhandle handle;
04201      lt_ptr data;
04202 {
04203   int n_elements = 0;
04204   lt_ptr stale = (lt_ptr) 0;
04205   int i;
04206 
04207   /* This needs to be locked so that the caller data can be updated
04208      simultaneously by different threads.  */
04209   LT_DLMUTEX_LOCK ();
04210 
04211   if (handle->caller_data)
04212     while (handle->caller_data[n_elements].key)
04213       ++n_elements;
04214 
04215   for (i = 0; i < n_elements; ++i)
04216     {
04217       if (handle->caller_data[i].key == key)
04218   {
04219     stale = handle->caller_data[i].data;
04220     break;
04221   }
04222     }
04223 
04224   /* Ensure that there is enough room in this handle's caller_data
04225      array to accept a new element (and an empty end marker).  */
04226   if (i == n_elements)
04227     {
04228       lt_caller_data *temp
04229   = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
04230 
04231       if (!temp)
04232   {
04233     stale = 0;
04234     goto done;
04235   }
04236 
04237       handle->caller_data = temp;
04238 
04239       /* We only need this if we needed to allocate a new caller_data.  */
04240       handle->caller_data[i].key  = key;
04241       handle->caller_data[1+ i].key = 0;
04242     }
04243 
04244   handle->caller_data[i].data = data;
04245 
04246  done:
04247   LT_DLMUTEX_UNLOCK ();
04248 
04249   return stale;
04250 }
04251 
04252 lt_ptr
04253 lt_dlcaller_get_data  (key, handle)
04254      lt_dlcaller_id key;
04255      lt_dlhandle handle;
04256 {
04257   lt_ptr result = (lt_ptr) 0;
04258 
04259   /* This needs to be locked so that the caller data isn't updated by
04260      another thread part way through this function.  */
04261   LT_DLMUTEX_LOCK ();
04262 
04263   /* Locate the index of the element with a matching KEY.  */
04264   {
04265     int i;
04266     for (i = 0; handle->caller_data[i].key; ++i)
04267       {
04268   if (handle->caller_data[i].key == key)
04269     {
04270       result = handle->caller_data[i].data;
04271       break;
04272     }
04273       }
04274   }
04275 
04276   LT_DLMUTEX_UNLOCK ();
04277 
04278   return result;
04279 }
04280 
04281 
04282 
04283 /* --- USER MODULE LOADER API --- */
04284 
04285 
04286 int
04287 lt_dlloader_add (place, dlloader, loader_name)
04288      lt_dlloader *place;
04289      const struct lt_user_dlloader *dlloader;
04290      const char *loader_name;
04291 {
04292   int errors = 0;
04293   lt_dlloader *node = 0, *ptr = 0;
04294 
04295   if ((dlloader == 0) /* diagnose null parameters */
04296       || (dlloader->module_open == 0)
04297       || (dlloader->module_close == 0)
04298       || (dlloader->find_sym == 0))
04299     {
04300       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
04301       return 1;
04302     }
04303 
04304   /* Create a new dlloader node with copies of the user callbacks.  */
04305   node = LT_EMALLOC (lt_dlloader, 1);
04306   if (!node)
04307     return 1;
04308 
04309   node->next    = 0;
04310   node->loader_name = loader_name;
04311   node->sym_prefix  = dlloader->sym_prefix;
04312   node->dlloader_exit = dlloader->dlloader_exit;
04313   node->module_open = dlloader->module_open;
04314   node->module_close  = dlloader->module_close;
04315   node->find_sym  = dlloader->find_sym;
04316   node->dlloader_data = dlloader->dlloader_data;
04317 
04318   LT_DLMUTEX_LOCK ();
04319   if (!loaders)
04320     {
04321       /* If there are no loaders, NODE becomes the list! */
04322       loaders = node;
04323     }
04324   else if (!place)
04325     {
04326       /* If PLACE is not set, add NODE to the end of the
04327    LOADERS list. */
04328       for (ptr = loaders; ptr->next; ptr = ptr->next)
04329   {
04330     /*NOWORK*/;
04331   }
04332 
04333       ptr->next = node;
04334     }
04335   else if (loaders == place)
04336     {
04337       /* If PLACE is the first loader, NODE goes first. */
04338       node->next = place;
04339       loaders = node;
04340     }
04341   else
04342     {
04343       /* Find the node immediately preceding PLACE. */
04344       for (ptr = loaders; ptr->next != place; ptr = ptr->next)
04345   {
04346     /*NOWORK*/;
04347   }
04348 
04349       if (ptr->next != place)
04350   {
04351     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
04352     ++errors;
04353   }
04354       else
04355   {
04356     /* Insert NODE between PTR and PLACE. */
04357     node->next = place;
04358     ptr->next  = node;
04359   }
04360     }
04361 
04362   LT_DLMUTEX_UNLOCK ();
04363 
04364   return errors;
04365 }
04366 
04367 int
04368 lt_dlloader_remove (loader_name)
04369      const char *loader_name;
04370 {
04371   lt_dlloader *place = lt_dlloader_find (loader_name);
04372   lt_dlhandle handle;
04373   int errors = 0;
04374 
04375   if (!place)
04376     {
04377       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
04378       return 1;
04379     }
04380 
04381   LT_DLMUTEX_LOCK ();
04382 
04383   /* Fail if there are any open modules which use this loader. */
04384   for  (handle = handles; handle; handle = handle->next)
04385     {
04386       if (handle->loader == place)
04387   {
04388     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
04389     ++errors;
04390     goto done;
04391   }
04392     }
04393 
04394   if (place == loaders)
04395     {
04396       /* PLACE is the first loader in the list. */
04397       loaders = loaders->next;
04398     }
04399   else
04400     {
04401       /* Find the loader before the one being removed. */
04402       lt_dlloader *prev;
04403       for (prev = loaders; prev->next; prev = prev->next)
04404   {
04405     if (!strcmp (prev->next->loader_name, loader_name))
04406       {
04407         break;
04408       }
04409   }
04410 
04411       place = prev->next;
04412       prev->next = prev->next->next;
04413     }
04414 
04415   if (place->dlloader_exit)
04416     {
04417       errors = place->dlloader_exit (place->dlloader_data);
04418     }
04419 
04420   LT_DLFREE (place);
04421 
04422  done:
04423   LT_DLMUTEX_UNLOCK ();
04424 
04425   return errors;
04426 }
04427 
04428 lt_dlloader *
04429 lt_dlloader_next (place)
04430      lt_dlloader *place;
04431 {
04432   lt_dlloader *next;
04433 
04434   LT_DLMUTEX_LOCK ();
04435   next = place ? place->next : loaders;
04436   LT_DLMUTEX_UNLOCK ();
04437 
04438   return next;
04439 }
04440 
04441 const char *
04442 lt_dlloader_name (place)
04443      lt_dlloader *place;
04444 {
04445   const char *name = 0;
04446 
04447   if (place)
04448     {
04449       LT_DLMUTEX_LOCK ();
04450       name = place ? place->loader_name : 0;
04451       LT_DLMUTEX_UNLOCK ();
04452     }
04453   else
04454     {
04455       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
04456     }
04457 
04458   return name;
04459 }
04460 
04461 lt_user_data *
04462 lt_dlloader_data (place)
04463      lt_dlloader *place;
04464 {
04465   lt_user_data *data = 0;
04466 
04467   if (place)
04468     {
04469       LT_DLMUTEX_LOCK ();
04470       data = place ? &(place->dlloader_data) : 0;
04471       LT_DLMUTEX_UNLOCK ();
04472     }
04473   else
04474     {
04475       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
04476     }
04477 
04478   return data;
04479 }
04480 
04481 lt_dlloader *
04482 lt_dlloader_find (loader_name)
04483      const char *loader_name;
04484 {
04485   lt_dlloader *place = 0;
04486 
04487   LT_DLMUTEX_LOCK ();
04488   for (place = loaders; place; place = place->next)
04489     {
04490       if (strcmp (place->loader_name, loader_name) == 0)
04491   {
04492     break;
04493   }
04494     }
04495   LT_DLMUTEX_UNLOCK ();
04496 
04497   return place;
04498 }