N-sim
Emulation and simulation of
Wireless Sensor Networks



   Home


   Project Page


   Download


   CVS



   Installation


   Configuration


   Plug-ins




 Hosted by
SourceForge.net Logo

/home/brennan/n-sim/Vaike/linux/system-addons/config/libltdl/ltdl.c

Go to the documentation of this file.
00001 /* ltdl.c -- system independent dlopen wrapper
00002    Copyright (C) 1998, 1999, 2000, 2004, 2005  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., 51 Franklin Street, Fifth Floor, Boston, MA
00024 02110-1301  USA
00025 
00026 */
00027 
00028 #if HAVE_CONFIG_H
00029 #  include <config.h>
00030 #endif
00031 
00032 #if HAVE_UNISTD_H
00033 #  include <unistd.h>
00034 #endif
00035 
00036 #if HAVE_STDIO_H
00037 #  include <stdio.h>
00038 #endif
00039 
00040 /* Include the header defining malloc.  On K&R C compilers,
00041    that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>.  */
00042 #if HAVE_STDLIB_H
00043 #  include <stdlib.h>
00044 #else
00045 #  if HAVE_MALLOC_H
00046 #    include <malloc.h>
00047 #  endif
00048 #endif
00049 
00050 #if HAVE_STRING_H
00051 #  include <string.h>
00052 #else
00053 #  if HAVE_STRINGS_H
00054 #    include <strings.h>
00055 #  endif
00056 #endif
00057 
00058 #if HAVE_CTYPE_H
00059 #  include <ctype.h>
00060 #endif
00061 
00062 #if HAVE_MEMORY_H
00063 #  include <memory.h>
00064 #endif
00065 
00066 #if HAVE_ERRNO_H
00067 #  include <errno.h>
00068 #endif
00069 
00070 
00071 #ifndef __WINDOWS__
00072 #  ifdef __WIN32__
00073 #    define __WINDOWS__
00074 #  endif
00075 #endif
00076 
00077 
00078 #undef LT_USE_POSIX_DIRENT
00079 #ifdef HAVE_CLOSEDIR
00080 #  ifdef HAVE_OPENDIR
00081 #    ifdef HAVE_READDIR
00082 #      ifdef HAVE_DIRENT_H
00083 #        define LT_USE_POSIX_DIRENT
00084 #      endif /* HAVE_DIRENT_H */
00085 #    endif /* HAVE_READDIR */
00086 #  endif /* HAVE_OPENDIR */
00087 #endif /* HAVE_CLOSEDIR */
00088 
00089 
00090 #undef LT_USE_WINDOWS_DIRENT_EMULATION
00091 #ifndef LT_USE_POSIX_DIRENT
00092 #  ifdef __WINDOWS__
00093 #    define LT_USE_WINDOWS_DIRENT_EMULATION
00094 #  endif /* __WINDOWS__ */
00095 #endif /* LT_USE_POSIX_DIRENT */
00096 
00097 
00098 #ifdef LT_USE_POSIX_DIRENT
00099 #  include <dirent.h>
00100 #  define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
00101 #else
00102 #  ifdef LT_USE_WINDOWS_DIRENT_EMULATION
00103 #    define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
00104 #  else
00105 #    define dirent direct
00106 #    define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
00107 #    if HAVE_SYS_NDIR_H
00108 #      include <sys/ndir.h>
00109 #    endif
00110 #    if HAVE_SYS_DIR_H
00111 #      include <sys/dir.h>
00112 #    endif
00113 #    if HAVE_NDIR_H
00114 #      include <ndir.h>
00115 #    endif
00116 #  endif
00117 #endif
00118 
00119 #if HAVE_ARGZ_H
00120 #  include <argz.h>
00121 #endif
00122 
00123 #if HAVE_ASSERT_H
00124 #  include <assert.h>
00125 #else
00126 #  define assert(arg)   ((void) 0)
00127 #endif
00128 
00129 #include "ltdl.h"
00130 
00131 #if WITH_DMALLOC
00132 #  include <dmalloc.h>
00133 #endif
00134 
00135 
00136 
00137 
00138 /* --- WINDOWS SUPPORT --- */
00139 
00140 
00141 #ifdef DLL_EXPORT
00142 #  define LT_GLOBAL_DATA        __declspec(dllexport)
00143 #else
00144 #  define LT_GLOBAL_DATA
00145 #endif
00146 
00147 /* fopen() mode flags for reading a text file */
00148 #undef  LT_READTEXT_MODE
00149 #ifdef __WINDOWS__
00150 #  define LT_READTEXT_MODE "rt"
00151 #else
00152 #  define LT_READTEXT_MODE "r"
00153 #endif
00154 
00155 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
00156 
00157 #include <windows.h>
00158 
00159 #define dirent lt_dirent
00160 #define DIR lt_DIR
00161 
00162 struct dirent
00163 {
00164   char d_name[2048];
00165   int  d_namlen;
00166 };
00167 
00168 typedef struct _DIR
00169 {
00170   HANDLE hSearch;
00171   WIN32_FIND_DATA Win32FindData;
00172   BOOL firsttime;
00173   struct dirent file_info;
00174 } DIR;
00175 
00176 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
00177 
00178 
00179 /* --- MANIFEST CONSTANTS --- */
00180 
00181 
00182 /* Standard libltdl search path environment variable name  */
00183 #undef  LTDL_SEARCHPATH_VAR
00184 #define LTDL_SEARCHPATH_VAR     "LTDL_LIBRARY_PATH"
00185 
00186 /* Standard libtool archive file extension.  */
00187 #undef  LTDL_ARCHIVE_EXT
00188 #define LTDL_ARCHIVE_EXT        ".la"
00189 
00190 /* max. filename length */
00191 #ifndef LT_FILENAME_MAX
00192 #  define LT_FILENAME_MAX       1024
00193 #endif
00194 
00195 /* This is the maximum symbol size that won't require malloc/free */
00196 #undef  LT_SYMBOL_LENGTH
00197 #define LT_SYMBOL_LENGTH        128
00198 
00199 /* This accounts for the _LTX_ separator */
00200 #undef  LT_SYMBOL_OVERHEAD
00201 #define LT_SYMBOL_OVERHEAD      5
00202 
00203 
00204 
00205 
00206 /* --- MEMORY HANDLING --- */
00207 
00208 
00209 /* These are the functions used internally.  In addition to making
00210    use of the associated function pointers above, they also perform
00211    error handling.  */
00212 static char   *lt_estrdup       LT_PARAMS((const char *str));
00213 static lt_ptr lt_emalloc        LT_PARAMS((size_t size));
00214 static lt_ptr lt_erealloc       LT_PARAMS((lt_ptr addr, size_t size));
00215 
00216 /* static lt_ptr rpl_realloc    LT_PARAMS((lt_ptr ptr, size_t size)); */
00217 #define rpl_realloc realloc
00218 
00219 /* These are the pointers that can be changed by the caller:  */
00220 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)    LT_PARAMS((size_t size))
00221                         = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
00222 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc)   LT_PARAMS((lt_ptr ptr, size_t size))
00223                         = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
00224 LT_GLOBAL_DATA void   (*lt_dlfree)      LT_PARAMS((lt_ptr ptr))
00225                         = (void (*) LT_PARAMS((lt_ptr))) free;
00226 
00227 /* The following macros reduce the amount of typing needed to cast
00228    assigned memory.  */
00229 #if WITH_DMALLOC
00230 
00231 #define LT_DLMALLOC(tp, n)      ((tp *) xmalloc ((n) * sizeof(tp)))
00232 #define LT_DLREALLOC(tp, p, n)  ((tp *) xrealloc ((p), (n) * sizeof(tp)))
00233 #define LT_DLFREE(p)                                            \
00234         LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
00235 
00236 #define LT_EMALLOC(tp, n)       ((tp *) xmalloc ((n) * sizeof(tp)))
00237 #define LT_EREALLOC(tp, p, n)   ((tp *) xrealloc ((p), (n) * sizeof(tp)))
00238 
00239 #else
00240 
00241 #define LT_DLMALLOC(tp, n)      ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
00242 #define LT_DLREALLOC(tp, p, n)  ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
00243 #define LT_DLFREE(p)                                            \
00244         LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
00245 
00246 #define LT_EMALLOC(tp, n)       ((tp *) lt_emalloc ((n) * sizeof(tp)))
00247 #define LT_EREALLOC(tp, p, n)   ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
00248 
00249 #endif
00250 
00251 #define LT_DLMEM_REASSIGN(p, q)                 LT_STMT_START { \
00252         if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; }   \
00253                                                 } LT_STMT_END
00254 
00255 
00256 /* --- REPLACEMENT FUNCTIONS --- */
00257 
00258 
00259 #undef strdup
00260 #define strdup rpl_strdup
00261 
00262 static char *strdup LT_PARAMS((const char *str));
00263 
00264 static char *
00265 strdup(str)
00266      const char *str;
00267 {
00268   char *tmp = 0;
00269 
00270   if (str)
00271     {
00272       tmp = LT_DLMALLOC (char, 1+ strlen (str));
00273       if (tmp)
00274         {
00275           strcpy(tmp, str);
00276         }
00277     }
00278 
00279   return tmp;
00280 }
00281 
00282 
00283 #if ! HAVE_STRCMP
00284 
00285 #undef strcmp
00286 #define strcmp rpl_strcmp
00287 
00288 static int strcmp LT_PARAMS((const char *str1, const char *str2));
00289 
00290 static int
00291 strcmp (str1, str2)
00292      const char *str1;
00293      const char *str2;
00294 {
00295   if (str1 == str2)
00296     return 0;
00297   if (str1 == 0)
00298     return -1;
00299   if (str2 == 0)
00300     return 1;
00301 
00302   for (;*str1 && *str2; ++str1, ++str2)
00303     {
00304       if (*str1 != *str2)
00305         break;
00306     }
00307 
00308   return (int)(*str1 - *str2);
00309 }
00310 #endif
00311 
00312 
00313 #if ! HAVE_STRCHR
00314 
00315 #  if HAVE_INDEX
00316 #    define strchr index
00317 #  else
00318 #    define strchr rpl_strchr
00319 
00320 static const char *strchr LT_PARAMS((const char *str, int ch));
00321 
00322 static const char*
00323 strchr(str, ch)
00324      const char *str;
00325      int ch;
00326 {
00327   const char *p;
00328 
00329   for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
00330     /*NOWORK*/;
00331 
00332   return (*p == (char)ch) ? p : 0;
00333 }
00334 
00335 #  endif
00336 #endif /* !HAVE_STRCHR */
00337 
00338 
00339 #if ! HAVE_STRRCHR
00340 
00341 #  if HAVE_RINDEX
00342 #    define strrchr rindex
00343 #  else
00344 #    define strrchr rpl_strrchr
00345 
00346 static const char *strrchr LT_PARAMS((const char *str, int ch));
00347 
00348 static const char*
00349 strrchr(str, ch)
00350      const char *str;
00351      int ch;
00352 {
00353   const char *p, *q = 0;
00354 
00355   for (p = str; *p != LT_EOS_CHAR; ++p)
00356     {
00357       if (*p == (char) ch)
00358         {
00359           q = p;
00360         }
00361     }
00362 
00363   return q;
00364 }
00365 
00366 # endif
00367 #endif
00368 
00369 /* NOTE:  Neither bcopy nor the memcpy implementation below can
00370           reliably handle copying in overlapping areas of memory.  Use
00371           memmove (for which there is a fallback implmentation below)
00372           if you need that behaviour.  */
00373 #if ! HAVE_MEMCPY
00374 
00375 #  if HAVE_BCOPY
00376 #    define memcpy(dest, src, size)     bcopy (src, dest, size)
00377 #  else
00378 #    define memcpy rpl_memcpy
00379 
00380 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
00381 
00382 static lt_ptr
00383 memcpy (dest, src, size)
00384      lt_ptr dest;
00385      const lt_ptr src;
00386      size_t size;
00387 {
00388   const char *  s = src;
00389   char *        d = dest;
00390   size_t        i = 0;
00391 
00392   for (i = 0; i < size; ++i)
00393     {
00394       d[i] = s[i];
00395     }
00396 
00397   return dest;
00398 }
00399 
00400 #  endif /* !HAVE_BCOPY */
00401 #endif   /* !HAVE_MEMCPY */
00402 
00403 #if ! HAVE_MEMMOVE
00404 #  define memmove rpl_memmove
00405 
00406 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
00407 
00408 static lt_ptr
00409 memmove (dest, src, size)
00410      lt_ptr dest;
00411      const lt_ptr src;
00412      size_t size;
00413 {
00414   const char *  s = src;
00415   char *        d = dest;
00416   size_t        i;
00417 
00418   if (d < s)
00419     for (i = 0; i < size; ++i)
00420       {
00421         d[i] = s[i];
00422       }
00423   else if (d > s && size > 0)
00424     for (i = size -1; ; --i)
00425       {
00426         d[i] = s[i];
00427         if (i == 0)
00428           break;
00429       }
00430 
00431   return dest;
00432 }
00433 
00434 #endif /* !HAVE_MEMMOVE */
00435 
00436 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
00437 
00438 static void closedir LT_PARAMS((DIR *entry));
00439 
00440 static void
00441 closedir(entry)
00442   DIR *entry;
00443 {
00444   assert(entry != (DIR *) NULL);
00445   FindClose(entry->hSearch);
00446   lt_dlfree((lt_ptr)entry);
00447 }
00448 
00449 
00450 static DIR * opendir LT_PARAMS((const char *path));
00451 
00452 static DIR*
00453 opendir (path)
00454   const char *path;
00455 {
00456   char file_specification[LT_FILENAME_MAX];
00457   DIR *entry;
00458 
00459   assert(path != (char *) NULL);
00460   /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
00461   (void) strncpy (file_specification, path, LT_FILENAME_MAX-6);
00462   file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR;
00463   (void) strcat(file_specification,"\\");
00464   entry = LT_DLMALLOC (DIR,sizeof(DIR));
00465   if (entry != (DIR *) 0)
00466     {
00467       entry->firsttime = TRUE;
00468       entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
00469     }
00470   if (entry->hSearch == INVALID_HANDLE_VALUE)
00471     {
00472       (void) strcat(file_specification,"\\*.*");
00473       entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
00474       if (entry->hSearch == INVALID_HANDLE_VALUE)
00475         {
00476           LT_DLFREE (entry);
00477           return (DIR *) 0;
00478         }
00479     }
00480   return(entry);
00481 }
00482 
00483 
00484 static struct dirent *readdir LT_PARAMS((DIR *entry));
00485 
00486 static struct dirent *readdir(entry)
00487   DIR *entry;
00488 {
00489   int
00490     status;
00491 
00492   if (entry == (DIR *) 0)
00493     return((struct dirent *) 0);
00494   if (!entry->firsttime)
00495     {
00496       status = FindNextFile(entry->hSearch,&entry->Win32FindData);
00497       if (status == 0)
00498         return((struct dirent *) 0);
00499     }
00500   entry->firsttime = FALSE;
00501   (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
00502     LT_FILENAME_MAX-1);
00503   entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
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 occurrence 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   {
01352     /* Silence dialog from LoadLibrary on some failures.
01353        No way to get the error mode, but to set it,
01354        so set it twice to preserve any previous flags. */
01355     UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
01356     SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
01357 
01358 #if defined(__CYGWIN__)
01359     {
01360       char wpath[MAX_PATH];
01361       cygwin_conv_to_full_win32_path (searchname, wpath);
01362       module = LoadLibrary (wpath);
01363     }
01364 #else
01365     module = LoadLibrary (searchname);
01366 #endif
01367 
01368     /* Restore the error mode. */
01369     SetErrorMode(errormode);
01370   }
01371 
01372   LT_DLFREE (searchname);
01373 
01374   /* libltdl expects this function to fail if it is unable
01375      to physically load the library.  Sadly, LoadLibrary
01376      will search the loaded libraries for a match and return
01377      one of them if the path search load fails.
01378 
01379      We check whether LoadLibrary is returning a handle to
01380      an already loaded module, and simulate failure if we
01381      find one. */
01382   LT_DLMUTEX_LOCK ();
01383   cur = handles;
01384   while (cur)
01385     {
01386       if (!cur->module)
01387         {
01388           cur = 0;
01389           break;
01390         }
01391 
01392       if (cur->module == module)
01393         {
01394           break;
01395         }
01396 
01397       cur = cur->next;
01398   }
01399   LT_DLMUTEX_UNLOCK ();
01400 
01401   if (cur || !module)
01402     {
01403       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01404       module = 0;
01405     }
01406 
01407   return module;
01408 }
01409 
01410 static int
01411 sys_wll_close (loader_data, module)
01412      lt_user_data loader_data;
01413      lt_module module;
01414 {
01415   int         errors   = 0;
01416 
01417   if (FreeLibrary(module) == 0)
01418     {
01419       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01420       ++errors;
01421     }
01422 
01423   return errors;
01424 }
01425 
01426 static lt_ptr
01427 sys_wll_sym (loader_data, module, symbol)
01428      lt_user_data loader_data;
01429      lt_module module;
01430      const char *symbol;
01431 {
01432   lt_ptr      address  = GetProcAddress (module, symbol);
01433 
01434   if (!address)
01435     {
01436       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01437     }
01438 
01439   return address;
01440 }
01441 
01442 static struct lt_user_dlloader sys_wll = {
01443   0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
01444 };
01445 
01446 #endif /* __WINDOWS__ */
01447 
01448 
01449 
01450 
01451 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
01452 
01453 
01454 #ifdef __BEOS__
01455 
01456 /* dynamic linking for BeOS */
01457 
01458 #include <kernel/image.h>
01459 
01460 static lt_module
01461 sys_bedl_open (loader_data, filename)
01462      lt_user_data loader_data;
01463      const char *filename;
01464 {
01465   image_id image = 0;
01466 
01467   if (filename)
01468     {
01469       image = load_add_on (filename);
01470     }
01471   else
01472     {
01473       image_info info;
01474       int32 cookie = 0;
01475       if (get_next_image_info (0, &cookie, &info) == B_OK)
01476         image = load_add_on (info.name);
01477     }
01478 
01479   if (image <= 0)
01480     {
01481       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01482       image = 0;
01483     }
01484 
01485   return (lt_module) image;
01486 }
01487 
01488 static int
01489 sys_bedl_close (loader_data, module)
01490      lt_user_data loader_data;
01491      lt_module module;
01492 {
01493   int errors = 0;
01494 
01495   if (unload_add_on ((image_id) module) != B_OK)
01496     {
01497       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01498       ++errors;
01499     }
01500 
01501   return errors;
01502 }
01503 
01504 static lt_ptr
01505 sys_bedl_sym (loader_data, module, symbol)
01506      lt_user_data loader_data;
01507      lt_module module;
01508      const char *symbol;
01509 {
01510   lt_ptr address = 0;
01511   image_id image = (image_id) module;
01512 
01513   if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
01514     {
01515       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01516       address = 0;
01517     }
01518 
01519   return address;
01520 }
01521 
01522 static struct lt_user_dlloader sys_bedl = {
01523   0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
01524 };
01525 
01526 #endif /* __BEOS__ */
01527 
01528 
01529 
01530 
01531 /* --- DLD_LINK() INTERFACE LOADER --- */
01532 
01533 
01534 #if HAVE_DLD
01535 
01536 /* dynamic linking with dld */
01537 
01538 #if HAVE_DLD_H
01539 #include <dld.h>
01540 #endif
01541 
01542 static lt_module
01543 sys_dld_open (loader_data, filename)
01544      lt_user_data loader_data;
01545      const char *filename;
01546 {
01547   lt_module module = strdup (filename);
01548 
01549   if (dld_link (filename) != 0)
01550     {
01551       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
01552       LT_DLFREE (module);
01553       module = 0;
01554     }
01555 
01556   return module;
01557 }
01558 
01559 static int
01560 sys_dld_close (loader_data, module)
01561      lt_user_data loader_data;
01562      lt_module module;
01563 {
01564   int errors = 0;
01565 
01566   if (dld_unlink_by_file ((char*)(module), 1) != 0)
01567     {
01568       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
01569       ++errors;
01570     }
01571   else
01572     {
01573       LT_DLFREE (module);
01574     }
01575 
01576   return errors;
01577 }
01578 
01579 static lt_ptr
01580 sys_dld_sym (loader_data, module, symbol)
01581      lt_user_data loader_data;
01582      lt_module module;
01583      const char *symbol;
01584 {
01585   lt_ptr address = dld_get_func (symbol);
01586 
01587   if (!address)
01588     {
01589       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
01590     }
01591 
01592   return address;
01593 }
01594 
01595 static struct lt_user_dlloader sys_dld = {
01596   0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
01597 };
01598 
01599 #endif /* HAVE_DLD */
01600 
01601 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
01602 #if HAVE_DYLD
01603 
01604 
01605 #if HAVE_MACH_O_DYLD_H
01606 #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
01607 /* Is this correct? Does it still function properly? */
01608 #define __private_extern__ extern
01609 #endif
01610 # include <mach-o/dyld.h>
01611 #endif
01612 #include <mach-o/getsect.h>
01613 
01614 /* We have to put some stuff here that isn't in older dyld.h files */
01615 #ifndef ENUM_DYLD_BOOL
01616 # define ENUM_DYLD_BOOL
01617 # undef FALSE
01618 # undef TRUE
01619  enum DYLD_BOOL {
01620     FALSE,
01621     TRUE
01622  };
01623 #endif
01624 #ifndef LC_REQ_DYLD
01625 # define LC_REQ_DYLD 0x80000000
01626 #endif
01627 #ifndef LC_LOAD_WEAK_DYLIB
01628 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
01629 #endif
01630 static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
01631 static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
01632 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
01633 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
01634 
01635 #ifndef NSADDIMAGE_OPTION_NONE
01636 #define NSADDIMAGE_OPTION_NONE                          0x0
01637 #endif
01638 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
01639 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR               0x1
01640 #endif
01641 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
01642 #define NSADDIMAGE_OPTION_WITH_SEARCHING                0x2
01643 #endif
01644 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
01645 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED         0x4
01646 #endif
01647 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
01648 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
01649 #endif
01650 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
01651 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND            0x0
01652 #endif
01653 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
01654 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW        0x1
01655 #endif
01656 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
01657 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY      0x2
01658 #endif
01659 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
01660 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
01661 #endif
01662 
01663 
01664 static const char *
01665 lt_int_dyld_error(othererror)
01666         char* othererror;
01667 {
01668 /* return the dyld error string, or the passed in error string if none */
01669         NSLinkEditErrors ler;
01670         int lerno;
01671         const char *errstr;
01672         const char *file;
01673         NSLinkEditError(&ler,&lerno,&file,&errstr);
01674         if (!errstr || !strlen(errstr)) errstr = othererror;
01675         return errstr;
01676 }
01677 
01678 static const struct mach_header *
01679 lt_int_dyld_get_mach_header_from_nsmodule(module)
01680         NSModule module;
01681 {
01682 /* There should probably be an apple dyld api for this */
01683         int i=_dyld_image_count();
01684         int j;
01685         const char *modname=NSNameOfModule(module);
01686         const struct mach_header *mh=NULL;
01687         if (!modname) return NULL;
01688         for (j = 0; j < i; j++)
01689         {
01690                 if (!strcmp(_dyld_get_image_name(j),modname))
01691                 {
01692                         mh=_dyld_get_image_header(j);
01693                         break;
01694                 }
01695         }
01696         return mh;
01697 }
01698 
01699 static const char* lt_int_dyld_lib_install_name(mh)
01700         const struct mach_header *mh;
01701 {
01702 /* NSAddImage is also used to get the loaded image, but it only works if the lib
01703    is installed, for uninstalled libs we need to check the install_names against
01704    each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
01705    different lib was loaded as a result
01706 */
01707         int j;
01708         struct load_command *lc;
01709         unsigned long offset = sizeof(struct mach_header);
01710         const char* retStr=NULL;
01711         for (j = 0; j < mh->ncmds; j++)
01712         {
01713                 lc = (struct load_command*)(((unsigned long)mh) + offset);
01714                 if (LC_ID_DYLIB == lc->cmd)
01715                 {
01716                         retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
01717                                                                         (unsigned long)lc);
01718                 }
01719                 offset += lc->cmdsize;
01720         }
01721         return retStr;
01722 }
01723 
01724 static const struct mach_header *
01725 lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
01726 {
01727         int i=_dyld_image_count();
01728         int j;
01729         const struct mach_header *mh=NULL;
01730         const char *id=NULL;
01731         for (j = 0; j < i; j++)
01732         {
01733                 id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
01734                 if ((id) && (!strcmp(id,name)))
01735                 {
01736                         mh=_dyld_get_image_header(j);
01737                         break;
01738                 }
01739         }
01740         return mh;
01741 }
01742 
01743 static NSSymbol
01744 lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
01745         const char *symbol;
01746         const struct mach_header *mh;
01747 {
01748         /* Safe to assume our mh is good */
01749         int j;
01750         struct load_command *lc;
01751         unsigned long offset = sizeof(struct mach_header);
01752         NSSymbol retSym = 0;
01753         const struct mach_header *mh1;
01754         if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
01755         {
01756                 for (j = 0; j < mh->ncmds; j++)
01757                 {
01758                         lc = (struct load_command*)(((unsigned long)mh) + offset);
01759                         if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
01760                         {
01761                                 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
01762                                                                                 (unsigned long)lc));
01763                                 if (!mh1)
01764                                 {
01765                                         /* Maybe NSAddImage can find it */
01766                                         mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
01767                                                                                 (unsigned long)lc),
01768                                                                                 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
01769                                                                                 NSADDIMAGE_OPTION_WITH_SEARCHING +
01770                                                                                 NSADDIMAGE_OPTION_RETURN_ON_ERROR );
01771                                 }
01772                                 if (mh1)
01773                                 {
01774                                         retSym = ltdl_NSLookupSymbolInImage(mh1,
01775                                                                                         symbol,
01776                                                                                         NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
01777                                                                                         | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
01778                                                                                         );
01779                                         if (retSym) break;
01780                                 }
01781                         }
01782                         offset += lc->cmdsize;
01783                 }
01784         }
01785         return retSym;
01786 }
01787 
01788 static int
01789 sys_dyld_init()
01790 {
01791         int retCode = 0;
01792         int err = 0;
01793         if (!_dyld_present()) {
01794                 retCode=1;
01795         }
01796         else {
01797       err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
01798       err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
01799       err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
01800       err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
01801     }
01802  return retCode;
01803 }
01804 
01805 static lt_module
01806 sys_dyld_open (loader_data, filename)
01807      lt_user_data loader_data;
01808      const char *filename;
01809 {
01810         lt_module   module   = 0;
01811         NSObjectFileImage ofi = 0;
01812         NSObjectFileImageReturnCode ofirc;
01813 
01814         if (!filename)
01815                 return (lt_module)-1;
01816         ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
01817         switch (ofirc)
01818         {
01819                 case NSObjectFileImageSuccess:
01820                         module = NSLinkModule(ofi, filename,
01821                                                 NSLINKMODULE_OPTION_RETURN_ON_ERROR
01822                                                  | NSLINKMODULE_OPTION_PRIVATE
01823                                                  | NSLINKMODULE_OPTION_BINDNOW);
01824                         NSDestroyObjectFileImage(ofi);
01825                         if (module)
01826                                 ltdl_NSMakePrivateModulePublic(module);
01827                         break;
01828                 case NSObjectFileImageInappropriateFile:
01829                     if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
01830                     {
01831                                 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
01832                                 break;
01833                         }
01834                 default:
01835                         LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
01836                         return 0;
01837         }
01838         if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
01839   return module;
01840 }
01841 
01842 static int
01843 sys_dyld_close (loader_data, module)
01844      lt_user_data loader_data;
01845      lt_module module;
01846 {
01847         int retCode = 0;
01848         int flags = 0;
01849         if (module == (lt_module)-1) return 0;
01850 #ifdef __BIG_ENDIAN__
01851         if (((struct mach_header *)module)->magic == MH_MAGIC)
01852 #else
01853     if (((struct mach_header *)module)->magic == MH_CIGAM)
01854 #endif
01855         {
01856           LT_DLMUTEX_SETERROR("Can not close a dylib");
01857           retCode = 1;
01858         }
01859         else
01860         {
01861 #if 1
01862 /* Currently, if a module contains c++ static destructors and it is unloaded, we
01863    get a segfault in atexit(), due to compiler and dynamic loader differences of
01864    opinion, this works around that.
01865 */
01866                 if ((const struct section *)NULL !=
01867                    getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
01868                    "__DATA","__mod_term_func"))
01869                 {
01870                         flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
01871                 }
01872 #endif
01873 #ifdef __ppc__
01874                         flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
01875 #endif
01876                 if (!NSUnLinkModule(module,flags))
01877                 {
01878                         retCode=1;
01879                         LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
01880                 }
01881         }
01882 
01883  return retCode;
01884 }
01885 
01886 static lt_ptr
01887 sys_dyld_sym (loader_data, module, symbol)
01888      lt_user_data loader_data;
01889      lt_module module;
01890      const char *symbol;
01891 {
01892         lt_ptr address = 0;
01893         NSSymbol *nssym = 0;
01894         void *unused;
01895         const struct mach_header *mh=NULL;
01896         char saveError[256] = "Symbol not found";
01897         if (module == (lt_module)-1)
01898         {
01899                 _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
01900                 return address;
01901         }
01902 #ifdef __BIG_ENDIAN__
01903         if (((struct mach_header *)module)->magic == MH_MAGIC)
01904 #else
01905     if (((struct mach_header *)module)->magic == MH_CIGAM)
01906 #endif
01907         {
01908             if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
01909             {
01910                 mh=module;
01911                         if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
01912                         {
01913                                 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
01914                                                                                         symbol,
01915                                                                                         NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
01916                                                                                         | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
01917                                                                                         );
01918                         }
01919             }
01920 
01921         }
01922   else {
01923         nssym = NSLookupSymbolInModule(module, symbol);
01924         }
01925         if (!nssym)
01926         {
01927                 strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
01928                 saveError[255] = 0;
01929                 if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
01930                 nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
01931         }
01932         if (!nssym)
01933         {
01934                 LT_DLMUTEX_SETERROR (saveError);
01935                 return NULL;
01936         }
01937         return NSAddressOfSymbol(nssym);
01938 }
01939 
01940 static struct lt_user_dlloader sys_dyld =
01941   { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
01942 
01943 
01944 #endif /* HAVE_DYLD */
01945 
01946 
01947 /* --- DLPREOPEN() INTERFACE LOADER --- */
01948 
01949 
01950 /* emulate dynamic linking using preloaded_symbols */
01951 
01952 typedef struct lt_dlsymlists_t
01953 {
01954   struct lt_dlsymlists_t       *next;
01955   const lt_dlsymlist           *syms;
01956 } lt_dlsymlists_t;
01957 
01958 static  const lt_dlsymlist     *default_preloaded_symbols       = 0;
01959 static  lt_dlsymlists_t        *preloaded_symbols               = 0;
01960 
01961 static int
01962 presym_init (loader_data)
01963      lt_user_data loader_data;
01964 {
01965   int errors = 0;
01966 
01967   LT_DLMUTEX_LOCK ();
01968 
01969   preloaded_symbols = 0;
01970   if (default_preloaded_symbols)
01971     {
01972       errors = lt_dlpreload (default_preloaded_symbols);
01973     }
01974 
01975   LT_DLMUTEX_UNLOCK ();
01976 
01977   return errors;
01978 }
01979 
01980 static int
01981 presym_free_symlists ()
01982 {
01983   lt_dlsymlists_t *lists;
01984 
01985   LT_DLMUTEX_LOCK ();
01986 
01987   lists = preloaded_symbols;
01988   while (lists)
01989     {
01990       lt_dlsymlists_t   *tmp = lists;
01991 
01992       lists = lists->next;
01993       LT_DLFREE (tmp);
01994     }
01995   preloaded_symbols = 0;
01996 
01997   LT_DLMUTEX_UNLOCK ();
01998 
01999   return 0;
02000 }
02001 
02002 static int
02003 presym_exit (loader_data)
02004      lt_user_data loader_data;
02005 {
02006   presym_free_symlists ();
02007   return 0;
02008 }
02009 
02010 static int
02011 presym_add_symlist (preloaded)
02012      const lt_dlsymlist *preloaded;
02013 {
02014   lt_dlsymlists_t *tmp;
02015   lt_dlsymlists_t *lists;
02016   int              errors   = 0;
02017 
02018   LT_DLMUTEX_LOCK ();
02019 
02020   lists = preloaded_symbols;
02021   while (lists)
02022     {
02023       if (lists->syms == preloaded)
02024         {
02025           goto done;
02026         }
02027       lists = lists->next;
02028     }
02029 
02030   tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
02031   if (tmp)
02032     {
02033       memset (tmp, 0, sizeof(lt_dlsymlists_t));
02034       tmp->syms = preloaded;
02035       tmp->next = preloaded_symbols;
02036       preloaded_symbols = tmp;
02037     }
02038   else
02039     {
02040       ++errors;
02041     }
02042 
02043  done:
02044   LT_DLMUTEX_UNLOCK ();
02045   return errors;
02046 }
02047 
02048 static lt_module
02049 presym_open (loader_data, filename)
02050      lt_user_data loader_data;
02051      const char *filename;
02052 {
02053   lt_dlsymlists_t *lists;
02054   lt_module        module = (lt_module) 0;
02055 
02056   LT_DLMUTEX_LOCK ();
02057   lists = preloaded_symbols;
02058 
02059   if (!lists)
02060     {
02061       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
02062       goto done;
02063     }
02064 
02065   /* Can't use NULL as the reflective symbol header, as NULL is
02066      used to mark the end of the entire symbol list.  Self-dlpreopened
02067      symbols follow this magic number, chosen to be an unlikely
02068      clash with a real module name.  */
02069   if (!filename)
02070     {
02071       filename = "@PROGRAM@";
02072     }
02073 
02074   while (lists)
02075     {
02076       const lt_dlsymlist *syms = lists->syms;
02077 
02078       while (syms->name)
02079         {
02080           if (!syms->address && strcmp(syms->name, filename) == 0)
02081             {
02082               module = (lt_module) syms;
02083               goto done;
02084             }
02085           ++syms;
02086         }
02087 
02088       lists = lists->next;
02089     }
02090 
02091   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
02092 
02093  done:
02094   LT_DLMUTEX_UNLOCK ();
02095   return module;
02096 }
02097 
02098 static int
02099 presym_close (loader_data, module)
02100      lt_user_data loader_data;
02101      lt_module module;
02102 {
02103   /* Just to silence gcc -Wall */
02104   module = 0;
02105   return 0;
02106 }
02107 
02108 static lt_ptr
02109 presym_sym (loader_data, module, symbol)
02110      lt_user_data loader_data;
02111      lt_module module;
02112      const char *symbol;
02113 {
02114   lt_dlsymlist *syms = (lt_dlsymlist*) module;
02115 
02116   ++syms;
02117   while (syms->address)
02118     {
02119       if (strcmp(syms->name, symbol) == 0)
02120         {
02121           return syms->address;
02122         }
02123 
02124     ++syms;
02125   }
02126 
02127   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
02128 
02129   return 0;
02130 }
02131 
02132 static struct lt_user_dlloader presym = {
02133   0, presym_open, presym_close, presym_sym, presym_exit, 0
02134 };
02135 
02136 
02137 
02138 
02139 
02140 /* --- DYNAMIC MODULE LOADING --- */
02141 
02142 
02143 /* The type of a function used at each iteration of  foreach_dirinpath().  */
02144 typedef int     foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
02145                                                  lt_ptr data2));
02146 
02147 static  int     foreach_dirinpath     LT_PARAMS((const char *search_path,
02148                                                  const char *base_name,
02149                                                  foreach_callback_func *func,
02150                                                  lt_ptr data1, lt_ptr data2));
02151 
02152 static  int     find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
02153                                                  lt_ptr ignored));
02154 static  int     find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
02155                                                  lt_ptr ignored));
02156 static  int     foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
02157                                                  lt_ptr data2));
02158 
02159 
02160 static  int     canonicalize_path     LT_PARAMS((const char *path,
02161                                                  char **pcanonical));
02162 static  int     argzize_path          LT_PARAMS((const char *path,
02163                                                  char **pargz,
02164                                                  size_t *pargz_len));
02165 static  FILE   *find_file             LT_PARAMS((const char *search_path,
02166                                                  const char *base_name,
02167                                                  char **pdir));
02168 static  lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
02169                                                  const char *base_name,
02170                                                  lt_dlhandle *handle));
02171 static  int     find_module           LT_PARAMS((lt_dlhandle *handle,
02172                                                  const char *dir,
02173                                                  const char *libdir,
02174                                                  const char *dlname,
02175                                                  const char *old_name,
02176                                                  int installed));
02177 static  int     free_vars             LT_PARAMS((char *dlname, char *oldname,
02178                                                  char *libdir, char *deplibs));
02179 static  int     load_deplibs          LT_PARAMS((lt_dlhandle handle,
02180                                                  char *deplibs));
02181 static  int     trim                  LT_PARAMS((char **dest,
02182                                                  const char *str));
02183 static  int     try_dlopen            LT_PARAMS((lt_dlhandle *handle,
02184                                                  const char *filename));
02185 static  int     tryall_dlopen         LT_PARAMS((lt_dlhandle *handle,
02186                                                  const char *filename));
02187 static  int     unload_deplibs        LT_PARAMS((lt_dlhandle handle));
02188 static  int     lt_argz_insert        LT_PARAMS((char **pargz,
02189                                                  size_t *pargz_len,
02190                                                  char *before,
02191                                                  const char *entry));
02192 static  int     lt_argz_insertinorder LT_PARAMS((char **pargz,
02193                                                  size_t *pargz_len,
02194                                                  const char *entry));
02195 static  int     lt_argz_insertdir     LT_PARAMS((char **pargz,
02196                                                  size_t *pargz_len,
02197                                                  const char *dirnam,
02198                                                  struct dirent *dp));
02199 static  int     lt_dlpath_insertdir   LT_PARAMS((char **ppath,
02200                                                  char *before,
02201                                                  const char *dir));
02202 static  int     list_files_by_dir     LT_PARAMS((const char *dirnam,
02203                                                  char **pargz,
02204                                                  size_t *pargz_len));
02205 static  int     file_not_found        LT_PARAMS((void));
02206 
02207 static  char           *user_search_path= 0;
02208 static  lt_dlloader    *loaders         = 0;
02209 static  lt_dlhandle     handles         = 0;
02210 static  int             initialized     = 0;
02211 
02212 /* Initialize libltdl. */
02213 int
02214 lt_dlinit ()
02215 {
02216   int         errors   = 0;
02217 
02218   LT_DLMUTEX_LOCK ();
02219 
02220   /* Initialize only at first call. */
02221   if (++initialized == 1)
02222     {
02223       handles = 0;
02224       user_search_path = 0; /* empty search path */
02225 
02226 #if HAVE_LIBDL
02227       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
02228 #endif
02229 #if HAVE_SHL_LOAD
02230       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
02231 #endif
02232 #ifdef __WINDOWS__
02233       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
02234 #endif
02235 #ifdef __BEOS__
02236       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
02237 #endif
02238 #if HAVE_DLD
02239       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
02240 #endif
02241 #if HAVE_DYLD
02242        errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
02243        errors += sys_dyld_init();
02244 #endif
02245       errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
02246 
02247       if (presym_init (presym.dlloader_data))
02248         {
02249           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
02250           ++errors;
02251         }
02252       else if (errors != 0)
02253         {
02254           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
02255           ++errors;
02256         }
02257     }
02258 
02259   LT_DLMUTEX_UNLOCK ();
02260 
02261   return errors;
02262 }
02263 
02264 int
02265 lt_dlpreload (preloaded)
02266      const lt_dlsymlist *preloaded;
02267 {
02268   int errors = 0;
02269 
02270   if (preloaded)
02271     {
02272       errors = presym_add_symlist (preloaded);
02273     }
02274   else
02275     {
02276       presym_free_symlists();
02277 
02278       LT_DLMUTEX_LOCK ();
02279       if (default_preloaded_symbols)
02280         {
02281           errors = lt_dlpreload (default_preloaded_symbols);
02282         }
02283       LT_DLMUTEX_UNLOCK ();
02284     }
02285 
02286   return errors;
02287 }
02288 
02289 int
02290 lt_dlpreload_default (preloaded)
02291      const lt_dlsymlist *preloaded;
02292 {
02293   LT_DLMUTEX_LOCK ();
02294   default_preloaded_symbols = preloaded;
02295   LT_DLMUTEX_UNLOCK ();
02296   return 0;
02297 }
02298 
02299 int
02300 lt_dlexit ()
02301 {
02302   /* shut down libltdl */
02303   lt_dlloader *loader;
02304   int          errors   = 0;
02305 
02306   LT_DLMUTEX_LOCK ();
02307   loader = loaders;
02308 
02309   if (!initialized)
02310     {
02311       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
02312       ++errors;
02313       goto done;
02314     }
02315 
02316   /* shut down only at last call. */
02317   if (--initialized == 0)
02318     {
02319       int       level;
02320 
02321       while (handles && LT_DLIS_RESIDENT (handles))
02322         {
02323           handles = handles->next;
02324         }
02325 
02326       /* close all modules */
02327       for (level = 1; handles; ++level)
02328         {
02329           lt_dlhandle cur = handles;
02330           int saw_nonresident = 0;
02331 
02332           while (cur)
02333             {
02334               lt_dlhandle tmp = cur;
02335               cur = cur->next;
02336               if (!LT_DLIS_RESIDENT (tmp))
02337                 saw_nonresident = 1;
02338               if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
02339                 {
02340                   if (lt_dlclose (tmp))
02341                     {
02342                       ++errors;
02343                     }
02344                 }
02345             }
02346           /* done if only resident modules are left */
02347           if (!saw_nonresident)
02348             break;
02349         }
02350 
02351       /* close all loaders */
02352       while (loader)
02353         {
02354           lt_dlloader *next = loader->next;
02355           lt_user_data data = loader->dlloader_data;
02356           if (loader->dlloader_exit && loader->dlloader_exit (data))
02357             {
02358               ++errors;
02359             }
02360 
02361           LT_DLMEM_REASSIGN (loader, next);
02362         }
02363       loaders = 0;
02364     }
02365 
02366  done:
02367   LT_DLMUTEX_UNLOCK ();
02368   return errors;
02369 }
02370 
02371 static int
02372 tryall_dlopen (handle, filename)
02373      lt_dlhandle *handle;
02374      const char *filename;
02375 {
02376   lt_dlhandle    cur;
02377   lt_dlloader   *loader;
02378   const char    *saved_error;
02379   int            errors         = 0;
02380 
02381   LT_DLMUTEX_GETERROR (saved_error);
02382   LT_DLMUTEX_LOCK ();
02383 
02384   cur    = handles;
02385   loader = loaders;
02386 
02387   /* check whether the module was already opened */
02388   while (cur)
02389     {
02390       /* try to dlopen the program itself? */
02391       if (!cur->info.filename && !filename)
02392         {
02393           break;
02394         }
02395 
02396       if (cur->info.filename && filename
02397           && strcmp (cur->info.filename, filename) == 0)
02398         {
02399           break;
02400         }
02401 
02402       cur = cur->next;
02403     }
02404 
02405   if (cur)
02406     {
02407       ++cur->info.ref_count;
02408       *handle = cur;
02409       goto done;
02410     }
02411 
02412   cur = *handle;
02413   if (filename)
02414     {
02415       /* Comment out the check of file permissions using access.
02416          This call seems to always return -1 with error EACCES.
02417       */
02418       /* We need to catch missing file errors early so that
02419          file_not_found() can detect what happened.
02420       if (access (filename, R_OK) != 0)
02421         {
02422           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
02423           ++errors;
02424           goto done;
02425         } */
02426 
02427       cur->info.filename = lt_estrdup (filename);
02428       if (!cur->info.filename)
02429         {
02430           ++errors;
02431           goto done;
02432         }
02433     }
02434   else
02435     {
02436       cur->info.filename = 0;
02437     }
02438 
02439   while (loader)
02440     {
02441       lt_user_data data = loader->dlloader_data;
02442 
02443       cur->module = loader->module_open (data, filename);
02444 
02445       if (cur->module != 0)
02446         {
02447           break;
02448         }
02449       loader = loader->next;
02450     }
02451 
02452   if (!loader)
02453     {
02454       LT_DLFREE (cur->info.filename);
02455       ++errors;
02456       goto done;
02457     }
02458 
02459   cur->loader   = loader;
02460   LT_DLMUTEX_SETERROR (saved_error);
02461 
02462  done:
02463   LT_DLMUTEX_UNLOCK ();
02464 
02465   return errors;
02466 }
02467 
02468 static int
02469 tryall_dlopen_module (handle, prefix, dirname, dlname)
02470      lt_dlhandle *handle;
02471      const char *prefix;
02472      const char *dirname;
02473      const char *dlname;
02474 {
02475   int      error        = 0;
02476   char     *filename    = 0;
02477   size_t   filename_len = 0;
02478   size_t   dirname_len  = LT_STRLEN (dirname);
02479 
02480   assert (handle);
02481   assert (dirname);
02482   assert (dlname);
02483 #ifdef LT_DIRSEP_CHAR
02484   /* Only canonicalized names (i.e. with DIRSEP chars already converted)
02485      should make it into this function:  */
02486   assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
02487 #endif
02488 
02489   if (dirname_len > 0)
02490     if (dirname[dirname_len -1] == '/')
02491       --dirname_len;
02492   filename_len = dirname_len + 1 + LT_STRLEN (dlname);
02493 
02494   /* Allocate memory, and combine DIRNAME and MODULENAME into it.
02495      The PREFIX (if any) is handled below.  */
02496   filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
02497   if (!filename)
02498     return 1;
02499 
02500   sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
02501 
02502   /* Now that we have combined DIRNAME and MODULENAME, if there is
02503      also a PREFIX to contend with, simply recurse with the arguments
02504      shuffled.  Otherwise, attempt to open FILENAME as a module.  */
02505   if (prefix)
02506     {
02507       error += tryall_dlopen_module (handle,
02508                                      (const char *) 0, prefix, filename);
02509     }
02510   else if (tryall_dlopen (handle, filename) != 0)
02511     {
02512       ++error;
02513     }
02514 
02515   LT_DLFREE (filename);
02516   return error;
02517 }
02518 
02519 static int
02520 find_module (handle, dir, libdir, dlname, old_name, installed)
02521      lt_dlhandle *handle;
02522      const char *dir;
02523      const char *libdir;
02524      const char *dlname;
02525      const char *old_name;
02526      int installed;
02527 {
02528   /* Try to open the old library first; if it was dlpreopened,
02529      we want the preopened version of it, even if a dlopenable
02530      module is available.  */
02531   if (old_name && tryall_dlopen (handle, old_name) == 0)
02532     {
02533       return 0;
02534     }
02535 
02536   /* Try to open the dynamic library.  */
02537   if (dlname)
02538     {
02539       /* try to open the installed module */
02540       if (installed && libdir)
02541         {
02542           if (tryall_dlopen_module (handle,
02543                                     (const char *) 0, libdir, dlname) == 0)
02544             return 0;
02545         }
02546 
02547       /* try to open the not-installed module */
02548       if (!installed)
02549         {
02550           if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
02551             return 0;
02552         }
02553 
02554       /* maybe it was moved to another directory */
02555       {
02556           if (dir && (tryall_dlopen_module (handle,
02557                                     (const char *) 0, dir, dlname) == 0))
02558             return 0;
02559       }
02560     }
02561 
02562   return 1;
02563 }
02564 
02565 
02566 static int
02567 canonicalize_path (path, pcanonical)
02568      const char *path;
02569      char **pcanonical;
02570 {
02571   char *canonical = 0;
02572 
02573   assert (path && *path);
02574   assert (pcanonical);
02575 
02576   canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
02577   if (!canonical)
02578     return 1;
02579 
02580   {
02581     size_t dest = 0;
02582     size_t src;
02583     for (src = 0; path[src] != LT_EOS_CHAR; ++src)
02584       {
02585         /* Path separators are not copied to the beginning or end of
02586            the destination, or if another separator would follow
02587            immediately.  */
02588         if (path[src] == LT_PATHSEP_CHAR)
02589           {
02590             if ((dest == 0)
02591                 || (path[1+ src] == LT_PATHSEP_CHAR)
02592                 || (path[1+ src] == LT_EOS_CHAR))
02593               continue;
02594           }
02595 
02596         /* Anything other than a directory separator is copied verbatim.  */
02597         if ((path[src] != '/')
02598 #ifdef LT_DIRSEP_CHAR
02599             && (path[src] != LT_DIRSEP_CHAR)
02600 #endif
02601             )
02602           {
02603             canonical[dest++] = path[src];
02604           }
02605         /* Directory separators are converted and copied only if they are
02606            not at the end of a path -- i.e. before a path separator or
02607            NULL terminator.  */
02608         else if ((path[1+ src] != LT_PATHSEP_CHAR)
02609                  && (path[1+ src] != LT_EOS_CHAR)
02610 #ifdef LT_DIRSEP_CHAR
02611                  && (path[1+ src] != LT_DIRSEP_CHAR)
02612 #endif
02613                  && (path[1+ src] != '/'))
02614           {
02615             canonical[dest++] = '/';
02616           }
02617       }
02618 
02619     /* Add an end-of-string marker at the end.  */
02620     canonical[dest] = LT_EOS_CHAR;
02621   }
02622 
02623   /* Assign new value.  */
02624   *pcanonical = canonical;
02625 
02626   return 0;
02627 }
02628 
02629 static int
02630 argzize_path (path, pargz, pargz_len)
02631      const char *path;
02632      char **pargz;
02633      size_t *pargz_len;
02634 {
02635   error_t error;
02636 
02637   assert (path);
02638   assert (pargz);
02639   assert (pargz_len);
02640 
02641   if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
02642     {
02643       switch (error)
02644         {
02645         case ENOMEM:
02646           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
02647           break;
02648         default:
02649           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
02650           break;
02651         }
02652 
02653       return 1;
02654     }
02655 
02656   return 0;
02657 }
02658 
02659 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
02660    of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
02661    non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
02662    it is appended to each SEARCH_PATH element before FUNC is called.  */
02663 static int
02664 foreach_dirinpath (search_path, base_name, func, data1, data2)
02665      const char *search_path;
02666      const char *base_name;
02667      foreach_callback_func *func;
02668      lt_ptr data1;
02669      lt_ptr data2;
02670 {
02671   int    result         = 0;
02672   int    filenamesize   = 0;
02673   size_t lenbase        = LT_STRLEN (base_name);
02674   size_t argz_len       = 0;
02675   char *argz            = 0;
02676   char *filename        = 0;
02677   char *canonical       = 0;
02678 
02679   LT_DLMUTEX_LOCK ();
02680 
02681   if (!search_path || !*search_path)
02682     {
02683       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
02684       goto cleanup;
02685     }
02686 
02687   if (canonicalize_path (search_path, &canonical) != 0)
02688     goto cleanup;
02689 
02690   if (argzize_path (canonical, &argz, &argz_len) != 0)
02691     goto cleanup;
02692 
02693   {
02694     char *dir_name = 0;
02695     while ((dir_name = argz_next (argz, argz_len, dir_name)))
02696       {
02697         size_t lendir = LT_STRLEN (dir_name);
02698 
02699         if (lendir +1 +lenbase >= filenamesize)
02700         {
02701           LT_DLFREE (filename);
02702           filenamesize  = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
02703           filename      = LT_EMALLOC (char, filenamesize);
02704           if (!filename)
02705             goto cleanup;
02706         }
02707 
02708         assert (filenamesize > lendir);
02709         strcpy (filename, dir_name);
02710 
02711         if (base_name && *base_name)
02712           {
02713             if (filename[lendir -1] != '/')
02714               filename[lendir++] = '/';
02715             strcpy (filename +lendir, base_name);
02716           }
02717 
02718         if ((result = (*func) (filename, data1, data2)))
02719           {
02720             break;
02721           }
02722       }
02723   }
02724 
02725  cleanup:
02726   LT_DLFREE (argz);
02727   LT_DLFREE (canonical);
02728   LT_DLFREE (filename);
02729 
02730   LT_DLMUTEX_UNLOCK ();
02731 
02732   return result;
02733 }
02734 
02735 /* If FILEPATH can be opened, store the name of the directory component
02736    in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
02737    DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
02738 static int
02739 find_file_callback (filename, data1, data2)
02740      char *filename;
02741      lt_ptr data1;
02742      lt_ptr data2;
02743 {
02744   char       **pdir     = (char **) data1;
02745   FILE       **pfile    = (FILE **) data2;
02746   int        is_done    = 0;
02747 
02748   assert (filename && *filename);
02749   assert (pdir);
02750   assert (pfile);
02751 
02752   if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
02753     {
02754       char *dirend = strrchr (filename, '/');
02755 
02756       if (dirend > filename)
02757         *dirend   = LT_EOS_CHAR;
02758 
02759       LT_DLFREE (*pdir);
02760       *pdir   = lt_estrdup (filename);
02761       is_done = (*pdir == 0) ? -1 : 1;
02762     }
02763 
02764   return is_done;
02765 }
02766 
02767 static FILE *
02768 find_file (search_path, base_name, pdir)
02769      const char *search_path;
02770      const char *base_name;
02771      char **pdir;
02772 {
02773   FILE *file = 0;
02774 
02775   foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
02776 
02777   return file;
02778 }
02779 
02780 static int
02781 find_handle_callback (filename, data, ignored)
02782      char *filename;
02783      lt_ptr data;
02784      lt_ptr ignored;
02785 {
02786   lt_dlhandle  *handle          = (lt_dlhandle *) data;
02787   int           notfound        = access (filename, R_OK);
02788 
02789   /* Bail out if file cannot be read...  */
02790   if (notfound)
02791     return 0;
02792 
02793   /* Try to dlopen the file, but do not continue searching in any
02794      case.  */
02795   if (tryall_dlopen (handle, filename) != 0)
02796     *handle = 0;
02797 
02798   return 1;
02799 }
02800 
02801 /* If HANDLE was found return it, otherwise return 0.  If HANDLE was
02802    found but could not be opened, *HANDLE will be set to 0.  */
02803 static lt_dlhandle *
02804 find_handle (search_path, base_name, handle)
02805      const char *search_path;
02806      const char *base_name;
02807      lt_dlhandle *handle;
02808 {
02809   if (!search_path)
02810     return 0;
02811 
02812   if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
02813                           handle, 0))
02814     return 0;
02815 
02816   return handle;
02817 }
02818 
02819 static int
02820 load_deplibs (handle, deplibs)
02821      lt_dlhandle handle;
02822      char *deplibs;
02823 {
02824 #if LTDL_DLOPEN_DEPLIBS
02825   char  *p, *save_search_path = 0;
02826   int   depcount = 0;
02827   int   i;
02828   char  **names = 0;
02829 #endif
02830   int   errors = 0;
02831 
02832   handle->depcount = 0;
02833 
02834 #if LTDL_DLOPEN_DEPLIBS
02835   if (!deplibs)
02836     {
02837       return errors;
02838     }
02839   ++errors;
02840 
02841   LT_DLMUTEX_LOCK ();
02842   if (user_search_path)
02843     {
02844       save_search_path = lt_estrdup (user_search_path);
02845       if (!save_search_path)
02846         goto cleanup;
02847     }
02848 
02849   /* extract search paths and count deplibs */
02850   p = deplibs;
02851   while (*p)
02852     {
02853       if (!isspace ((int) *p))
02854         {
02855           char *end = p+1;
02856           while (*end && !isspace((int) *end))
02857             {
02858               ++end;
02859             }
02860 
02861           if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
02862             {
02863               char save = *end;
02864               *end = 0; /* set a temporary string terminator */
02865               if (lt_dladdsearchdir(p+2))
02866                 {
02867                   goto cleanup;
02868                 }
02869               *end = save;
02870             }
02871           else
02872             {
02873               ++depcount;
02874             }
02875 
02876           p = end;
02877         }
02878       else
02879         {
02880           ++p;
02881         }
02882     }
02883 
02884   if (!depcount)
02885     {
02886       errors = 0;
02887       goto cleanup;
02888     }
02889 
02890   names = LT_EMALLOC (char *, depcount * sizeof (char*));
02891   if (!names)
02892     goto cleanup;
02893 
02894   /* now only extract the actual deplibs */
02895   depcount = 0;
02896   p = deplibs;
02897   while (*p)
02898     {
02899       if (isspace ((int) *p))
02900         {
02901           ++p;
02902         }
02903       else
02904         {
02905           char *end = p+1;
02906           while (*end && !isspace ((int) *end))
02907             {
02908               ++end;
02909             }
02910 
02911           if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
02912             {
02913               char *name;
02914               char save = *end;
02915               *end = 0; /* set a temporary string terminator */
02916               if (strncmp(p, "-l", 2) == 0)
02917                 {
02918                   size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
02919                   name = LT_EMALLOC (char, 1+ name_len);
02920                   if (name)
02921                     sprintf (name, "lib%s", p+2);
02922                 }
02923               else
02924                 name = lt_estrdup(p);
02925 
02926               if (!name)
02927                 goto cleanup_names;
02928 
02929               names[depcount++] = name;
02930               *end = save;
02931             }
02932           p = end;
02933         }
02934     }
02935 
02936   /* load the deplibs (in reverse order)
02937      At this stage, don't worry if the deplibs do not load correctly,
02938      they may already be statically linked into the loading application
02939      for instance.  There will be a more enlightening error message
02940      later on if the loaded module cannot resolve all of its symbols.  */
02941   if (depcount)
02942     {
02943       int       j = 0;
02944 
02945       handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
02946       if (!handle->deplibs)
02947         goto cleanup;
02948 
02949       for (i = 0; i < depcount; ++i)
02950         {
02951           handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
02952           if (handle->deplibs[j])
02953             {
02954               ++j;
02955             }
02956         }
02957 
02958       handle->depcount  = j;    /* Number of successfully loaded deplibs */
02959       errors            = 0;
02960     }
02961 
02962  cleanup_names:
02963   for (i = 0; i < depcount; ++i)
02964     {
02965       LT_DLFREE (names[i]);
02966     }
02967 
02968  cleanup:
02969   LT_DLFREE (names);
02970   /* restore the old search path */
02971   if (user_search_path) {
02972     LT_DLFREE (user_search_path);
02973     user_search_path = save_search_path;
02974   }
02975   LT_DLMUTEX_UNLOCK ();
02976 
02977 #endif
02978 
02979   return errors;
02980 }
02981 
02982 static int
02983 unload_deplibs (handle)
02984      lt_dlhandle handle;
02985 {
02986   int i;
02987   int errors = 0;
02988 
02989   if (handle->depcount)
02990     {
02991       for (i = 0; i < handle->depcount; ++i)
02992         {
02993           if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
02994             {
02995               errors += lt_dlclose (handle->deplibs[i]);
02996             }
02997         }
02998     }
02999 
03000   return errors;
03001 }
03002 
03003 static int
03004 trim (dest, str)
03005      char **dest;
03006      const char *str;
03007 {
03008   /* remove the leading and trailing "'" from str
03009      and store the result in dest */
03010   const char *end   = strrchr (str, '\'');
03011   size_t len        = LT_STRLEN (str);
03012   char *tmp;
03013 
03014   LT_DLFREE (*dest);
03015 
03016   if (!end)
03017     return 1;
03018 
03019   if (len > 3 && str[0] == '\'')
03020     {
03021       tmp = LT_EMALLOC (char, end - str);
03022       if (!tmp)
03023         return 1;
03024 
03025       strncpy(tmp, &str[1], (end - str) - 1);
03026       tmp[len-3] = LT_EOS_CHAR;
03027       *dest = tmp;
03028     }
03029   else
03030     {
03031       *dest = 0;
03032     }
03033 
03034   return 0;
03035 }
03036 
03037 static int
03038 free_vars (dlname, oldname, libdir, deplibs)
03039      char *dlname;
03040      char *oldname;
03041      char *libdir;
03042      char *deplibs;
03043 {
03044   LT_DLFREE (dlname);
03045   LT_DLFREE (oldname);
03046   LT_DLFREE (libdir);
03047   LT_DLFREE (deplibs);
03048 
03049   return 0;
03050 }
03051 
03052 static int
03053 try_dlopen (phandle, filename)
03054      lt_dlhandle *phandle;
03055      const char *filename;
03056 {
03057   const char *  ext             = 0;
03058   const char *  saved_error     = 0;
03059   char *        canonical       = 0;
03060   char *        base_name       = 0;
03061   char *        dir             = 0;
03062   char *        name            = 0;
03063   int           errors          = 0;
03064   lt_dlhandle   newhandle;
03065 
03066   assert (phandle);
03067   assert (*phandle == 0);
03068 
03069   LT_DLMUTEX_GETERROR (saved_error);
03070 
03071   /* dlopen self? */
03072   if (!filename)
03073     {
03074       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
03075       if (*phandle == 0)
03076         return 1;
03077 
03078       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
03079       newhandle = *phandle;
03080 
03081       /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
03082       LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
03083 
03084       if (tryall_dlopen (&newhandle, 0) != 0)
03085         {
03086           LT_DLFREE (*phandle);
03087           return 1;
03088         }
03089 
03090       goto register_handle;
03091     }
03092 
03093   assert (filename && *filename);
03094 
03095   /* Doing this immediately allows internal functions to safely
03096      assume only canonicalized paths are passed.  */
03097   if (canonicalize_path (filename, &canonical) != 0)
03098     {
03099       ++errors;
03100       goto cleanup;
03101     }
03102 
03103   /* If the canonical module name is a path (relative or absolute)
03104      then split it into a directory part and a name part.  */
03105   base_name = strrchr (canonical, '/');
03106   if (base_name)
03107     {
03108       size_t dirlen = (1+ base_name) - canonical;
03109 
03110       dir = LT_EMALLOC (char, 1+ dirlen);
03111       if (!dir)
03112         {
03113           ++errors;
03114           goto cleanup;
03115         }
03116 
03117       strncpy (dir, canonical, dirlen);
03118       dir[dirlen] = LT_EOS_CHAR;
03119 
03120       ++base_name;
03121     }
03122   else
03123     base_name = canonical;
03124 
03125   assert (base_name && *base_name);
03126 
03127   /* Check whether we are opening a libtool module (.la extension).  */
03128   ext = strrchr (base_name, '.');
03129   if (ext && strcmp (ext, archive_ext) == 0)
03130     {
03131       /* this seems to be a libtool module */
03132       FILE *    file     = 0;
03133       char *    dlname   = 0;
03134       char *    old_name = 0;
03135       char *    libdir   = 0;
03136       char *    deplibs  = 0;
03137       char *    line     = 0;
03138       size_t    line_len;
03139 
03140       /* if we can't find the installed flag, it is probably an
03141          installed libtool archive, produced with an old version
03142          of libtool */
03143       int       installed = 1;
03144 
03145       /* extract the module name from the file name */
03146       name = LT_EMALLOC (char, ext - base_name + 1);
03147       if (!name)
03148         {
03149           ++errors;
03150           goto cleanup;
03151         }
03152 
03153       /* canonicalize the module name */
03154       {
03155         size_t i;
03156         for (i = 0; i < ext - base_name; ++i)
03157           {
03158             if (isalnum ((int)(base_name[i])))
03159               {
03160                 name[i] = base_name[i];
03161               }
03162             else
03163               {
03164                 name[i] = '_';
03165               }
03166           }
03167         name[ext - base_name] = LT_EOS_CHAR;
03168       }
03169 
03170       /* Now try to open the .la file.  If there is no directory name
03171          component, try to find it first in user_search_path and then other
03172          prescribed paths.  Otherwise (or in any case if the module was not
03173          yet found) try opening just the module name as passed.  */
03174       if (!dir)
03175         {
03176           const char *search_path;
03177 
03178           LT_DLMUTEX_LOCK ();
03179           search_path = user_search_path;
03180           if (search_path)
03181             file = find_file (user_search_path, base_name, &dir);
03182           LT_DLMUTEX_UNLOCK ();
03183 
03184           if (!file)
03185             {
03186               search_path = getenv (LTDL_SEARCHPATH_VAR);
03187               if (search_path)
03188                 file = find_file (search_path, base_name, &dir);
03189             }
03190 
03191 #ifdef LTDL_SHLIBPATH_VAR
03192           if (!file)
03193             {
03194               search_path = getenv (LTDL_SHLIBPATH_VAR);
03195               if (search_path)
03196                 file = find_file (search_path, base_name, &dir);
03197             }
03198 #endif
03199 #ifdef LTDL_SYSSEARCHPATH
03200           if (!file && sys_search_path)
03201             {
03202               file = find_file (sys_search_path, base_name, &dir);
03203             }
03204 #endif
03205         }
03206       if (!file)
03207         {
03208           file = fopen (filename, LT_READTEXT_MODE);
03209         }
03210 
03211       /* If we didn't find the file by now, it really isn't there.  Set
03212          the status flag, and bail out.  */
03213       if (!file)
03214         {
03215           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
03216           ++errors;
03217           goto cleanup;
03218         }
03219 
03220       line_len = LT_FILENAME_MAX;
03221       line = LT_EMALLOC (char, line_len);
03222       if (!line)
03223         {
03224           fclose (file);
03225           ++errors;
03226           goto cleanup;
03227         }
03228 
03229       /* read the .la file */
03230       while (!feof (file))
03231         {
03232           if (!fgets (line, (int) line_len, file))
03233             {
03234               break;
03235             }
03236 
03237           /* Handle the case where we occasionally need to read a line
03238              that is longer than the initial buffer size.  */
03239           while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
03240             {
03241               line = LT_DLREALLOC (char, line, line_len *2);
03242               if (!fgets (&line[line_len -1], (int) line_len +1, file))
03243                 {
03244                   break;
03245                 }
03246               line_len *= 2;
03247             }
03248 
03249           if (line[0] == '\n' || line[0] == '#')
03250             {
03251               continue;
03252             }
03253 
03254 #undef  STR_DLNAME
03255 #define STR_DLNAME      "dlname="
03256           if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
03257             {
03258               errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
03259             }
03260 
03261 #undef  STR_OLD_LIBRARY
03262 #define STR_OLD_LIBRARY "old_library="
03263           else if (strncmp (line, STR_OLD_LIBRARY,
03264                             sizeof (STR_OLD_LIBRARY) - 1) == 0)
03265             {
03266               errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
03267             }
03268 #undef  STR_LIBDIR
03269 #define STR_LIBDIR      "libdir="
03270           else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
03271             {
03272               errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
03273             }
03274 
03275 #undef  STR_DL_DEPLIBS
03276 #define STR_DL_DEPLIBS  "dependency_libs="
03277           else if (strncmp (line, STR_DL_DEPLIBS,
03278                             sizeof (STR_DL_DEPLIBS) - 1) == 0)
03279             {
03280               errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
03281             }
03282           else if (strcmp (line, "installed=yes\n") == 0)
03283             {
03284               installed = 1;
03285             }
03286           else if (strcmp (line, "installed=no\n") == 0)
03287             {
03288               installed = 0;
03289             }
03290 
03291 #undef  STR_LIBRARY_NAMES
03292 #define STR_LIBRARY_NAMES "library_names="
03293           else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
03294                                         sizeof (STR_LIBRARY_NAMES) - 1) == 0)
03295             {
03296               char *last_libname;
03297               errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
03298               if (!errors
03299                   && dlname
03300                   && (last_libname = strrchr (dlname, ' ')) != 0)
03301                 {
03302                   last_libname = lt_estrdup (last_libname + 1);
03303                   if (!last_libname)
03304                     {
03305                       ++errors;
03306                       goto cleanup;
03307                     }
03308                   LT_DLMEM_REASSIGN (dlname, last_libname);
03309                 }
03310             }
03311 
03312           if (errors)
03313             break;
03314         }
03315 
03316       fclose (file);
03317       LT_DLFREE (line);
03318 
03319       /* allocate the handle */
03320       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
03321       if (*phandle == 0)
03322         ++errors;
03323 
03324       if (errors)
03325         {
03326           free_vars (dlname, old_name, libdir, deplibs);
03327           LT_DLFREE (*phandle);
03328           goto cleanup;
03329         }
03330 
03331       assert (*phandle);
03332 
03333       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
03334       if (load_deplibs (*phandle, deplibs) == 0)
03335         {
03336           newhandle = *phandle;
03337           /* find_module may replace newhandle */
03338           if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
03339             {
03340               unload_deplibs (*phandle);
03341               ++errors;
03342             }
03343         }
03344       else
03345         {
03346           ++errors;
03347         }
03348 
03349       free_vars (dlname, old_name, libdir, deplibs);
03350       if (errors)
03351         {
03352           LT_DLFREE (*phandle);
03353           goto cleanup;
03354         }
03355 
03356       if (*phandle != newhandle)
03357         {
03358           unload_deplibs (*phandle);
03359         }
03360     }
03361   else
03362     {
03363       /* not a libtool module */
03364       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
03365       if (*phandle == 0)
03366         {
03367           ++errors;
03368           goto cleanup;
03369         }
03370 
03371       memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
03372       newhandle = *phandle;
03373 
03374       /* If the module has no directory name component, try to find it
03375          first in user_search_path and then other prescribed paths.
03376          Otherwise (or in any case if the module was not yet found) try
03377          opening just the module name as passed.  */
03378       if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
03379                    && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
03380                                     &newhandle)
03381 #ifdef LTDL_SHLIBPATH_VAR
03382                    && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
03383                                     &newhandle)
03384 #endif
03385 #ifdef LTDL_SYSSEARCHPATH
03386                    && !find_handle (sys_search_path, base_name, &newhandle)
03387 #endif
03388                    )))
03389         {
03390           if (tryall_dlopen (&newhandle, filename) != 0)
03391             {
03392               newhandle = NULL;
03393             }
03394         }
03395 
03396       if (!newhandle)
03397         {
03398           LT_DLFREE (*phandle);
03399           ++errors;
03400           goto cleanup;
03401         }
03402     }
03403 
03404  register_handle:
03405   LT_DLMEM_REASSIGN (*phandle, newhandle);
03406 
03407   if ((*phandle)->info.ref_count == 0)
03408     {
03409       (*phandle)->info.ref_count        = 1;
03410       LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
03411 
03412       LT_DLMUTEX_LOCK ();
03413       (*phandle)->next          = handles;
03414       handles                   = *phandle;
03415       LT_DLMUTEX_UNLOCK ();
03416     }
03417 
03418   LT_DLMUTEX_SETERROR (saved_error);
03419 
03420  cleanup:
03421   LT_DLFREE (dir);
03422   LT_DLFREE (name);
03423   LT_DLFREE (canonical);
03424 
03425   return errors;
03426 }
03427 
03428 lt_dlhandle
03429 lt_dlopen (filename)
03430      const char *filename;
03431 {
03432   lt_dlhandle handle = 0;
03433 
03434   /* Just incase we missed a code path in try_dlopen() that reports
03435      an error, but forgets to reset handle... */
03436   if (try_dlopen (&handle, filename) != 0)
03437     return 0;
03438 
03439   return handle;
03440 }
03441 
03442 /* If the last error messge store was `FILE_NOT_FOUND', then return
03443    non-zero.  */
03444 static int
03445 file_not_found ()
03446 {
03447   const char *error = 0;
03448 
03449   LT_DLMUTEX_GETERROR (error);
03450   if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
03451     return 1;
03452 
03453   return 0;
03454 }
03455 
03456 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
03457    open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
03458    and if a file is still not found try again with SHLIB_EXT appended
03459    instead.  */
03460 lt_dlhandle
03461 lt_dlopenext (filename)
03462      const char *filename;
03463 {
03464   lt_dlhandle   handle          = 0;
03465   char *        tmp             = 0;
03466   char *        ext             = 0;
03467   size_t        len;
03468   int           errors          = 0;
03469 
03470   if (!filename)
03471     {
03472       return lt_dlopen (filename);
03473     }
03474 
03475   assert (filename);
03476 
03477   len = LT_STRLEN (filename);
03478   ext = strrchr (filename, '.');
03479 
03480   /* If FILENAME already bears a suitable extension, there is no need
03481      to try appending additional extensions.  */
03482   if (ext && ((strcmp (ext, archive_ext) == 0)
03483 #ifdef LTDL_SHLIB_EXT
03484               || (strcmp (ext, shlib_ext) == 0)
03485 #endif
03486       ))
03487     {
03488       return lt_dlopen (filename);
03489     }
03490 
03491   /* First try appending ARCHIVE_EXT.  */
03492   tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
03493   if (!tmp)
03494     return 0;
03495 
03496   strcpy (tmp, filename);
03497   strcat (tmp, archive_ext);
03498   errors = try_dlopen (&handle, tmp);
03499 
03500   /* If we found FILENAME, stop searching -- whether we were able to
03501      load the file as a module or not.  If the file exists but loading
03502      failed, it is better to return an error message here than to
03503      report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
03504      in the module search path.  */
03505   if (handle || ((errors > 0) && !file_not_found ()))
03506     {
03507       LT_DLFREE (tmp);
03508       return handle;
03509     }
03510 
03511 #ifdef LTDL_SHLIB_EXT
03512   /* Try appending SHLIB_EXT.   */
03513   if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
03514     {
03515       LT_DLFREE (tmp);
03516       tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
03517       if (!tmp)
03518         return 0;
03519 
03520       strcpy (tmp, filename);
03521     }
03522   else
03523     {
03524       tmp[len] = LT_EOS_CHAR;
03525     }
03526 
03527   strcat(tmp, shlib_ext);
03528   errors = try_dlopen (&handle, tmp);
03529 
03530   /* As before, if the file was found but loading failed, return now
03531      with the current error message.  */
03532   if (handle || ((errors > 0) && !file_not_found ()))
03533     {
03534       LT_DLFREE (tmp);
03535       return handle;
03536     }
03537 #endif
03538 
03539   /* Still here?  Then we really did fail to locate any of the file
03540      names we tried.  */
03541   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
03542   LT_DLFREE (tmp);
03543   return 0;
03544 }
03545 
03546 
03547 static int
03548 lt_argz_insert (pargz, pargz_len, before, entry)
03549      char **pargz;
03550      size_t *pargz_len;
03551      char *before;
03552      const char *entry;
03553 {
03554   error_t error;
03555 
03556   /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
03557      pargz_len, NULL, entry) failed with EINVAL.  */
03558   if (before)
03559     error = argz_insert (pargz, pargz_len, before, entry);
03560   else
03561     error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
03562 
03563   if (error)
03564     {
03565       switch (error)
03566         {
03567         case ENOMEM:
03568           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
03569           break;
03570         default:
03571           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
03572           break;
03573         }
03574       return 1;
03575     }
03576 
03577   return 0;
03578 }
03579 
03580 static int
03581 lt_argz_insertinorder (pargz, pargz_len, entry)
03582      char **pargz;
03583      size_t *pargz_len;
03584      const char *entry;
03585 {
03586   char *before = 0;
03587 
03588   assert (pargz);
03589   assert (pargz_len);
03590   assert (entry && *entry);
03591 
03592   if (*pargz)
03593     while ((before = argz_next (*pargz, *pargz_len, before)))
03594       {
03595         int cmp = strcmp (entry, before);
03596 
03597         if (cmp < 0)  break;
03598         if (cmp == 0) return 0; /* No duplicates! */
03599       }
03600 
03601   return lt_argz_insert (pargz, pargz_len, before, entry);
03602 }
03603 
03604 static int
03605 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
03606      char **pargz;
03607      size_t *pargz_len;
03608      const char *dirnam;
03609      struct dirent *dp;
03610 {
03611   char   *buf       = 0;
03612   size_t buf_len    = 0;
03613   char   *end       = 0;
03614   size_t end_offset = 0;
03615   size_t dir_len    = 0;
03616   int    errors     = 0;
03617 
03618   assert (pargz);
03619   assert (pargz_len);
03620   assert (dp);
03621 
03622   dir_len = LT_STRLEN (dirnam);
03623   end     = dp->d_name + LT_D_NAMLEN(dp);
03624 
03625   /* Ignore version numbers.  */
03626   {
03627     char *p;
03628     for (p = end; p -1 > dp->d_name; --p)
03629       if (strchr (".0123456789", p[-1]) == 0)
03630         break;
03631 
03632     if (*p == '.')
03633       end = p;
03634   }
03635 
03636   /* Ignore filename extension.  */
03637   {
03638     char *p;
03639     for (p = end -1; p > dp->d_name; --p)
03640       if (*p == '.')
03641         {
03642           end = p;
03643           break;
03644         }
03645   }
03646 
03647   /* Prepend the directory name.  */
03648   end_offset    = end - dp->d_name;
03649   buf_len       = dir_len + 1+ end_offset;
03650   buf           = LT_EMALLOC (char, 1+ buf_len);
03651   if (!buf)
03652     return ++errors;
03653 
03654   assert (buf);
03655 
03656   strcpy  (buf, dirnam);
03657   strcat  (buf, "/");
03658   strncat (buf, dp->d_name, end_offset);
03659   buf[buf_len] = LT_EOS_CHAR;
03660 
03661   /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
03662   if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
03663     ++errors;
03664 
03665   LT_DLFREE (buf);
03666 
03667   return errors;
03668 }
03669 
03670 static int
03671 list_files_by_dir (dirnam, pargz, pargz_len)
03672      const char *dirnam;
03673      char **pargz;
03674      size_t *pargz_len;
03675 {
03676   DIR   *dirp     = 0;
03677   int    errors   = 0;
03678 
03679   assert (dirnam && *dirnam);
03680   assert (pargz);
03681   assert (pargz_len);
03682   assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
03683 
03684   dirp = opendir (dirnam);
03685   if (dirp)
03686     {
03687       struct dirent *dp = 0;
03688 
03689       while ((dp = readdir (dirp)))
03690         if (dp->d_name[0] != '.')
03691           if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
03692             {
03693               ++errors;
03694               break;
03695             }
03696 
03697       closedir (dirp);
03698     }
03699   else
03700     ++errors;
03701 
03702   return errors;
03703 }
03704 
03705 
03706 /* If there are any files in DIRNAME, call the function passed in
03707    DATA1 (with the name of each file and DATA2 as arguments).  */
03708 static int
03709 foreachfile_callback (dirname, data1, data2)
03710      char *dirname;
03711      lt_ptr data1;
03712      lt_ptr data2;
03713 {
03714   int (*func) LT_PARAMS((const char *filename, lt_ptr data))
03715         = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
03716 
03717   int     is_done  = 0;
03718   char   *argz     = 0;
03719   size_t  argz_len = 0;
03720 
03721   if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
03722     goto cleanup;
03723   if (!argz)
03724     goto cleanup;
03725 
03726   {
03727     char *filename = 0;
03728     while ((filename = argz_next (argz, argz_len, filename)))
03729       if ((is_done = (*func) (filename, data2)))
03730         break;
03731   }
03732 
03733  cleanup:
03734   LT_DLFREE (argz);
03735 
03736   return is_done;
03737 }
03738 
03739 
03740 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
03741    with DATA.  The filenames passed to FUNC would be suitable for
03742    passing to lt_dlopenext.  The extensions are stripped so that
03743    individual modules do not generate several entries (e.g. libfoo.la,
03744    libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
03745    then the same directories that lt_dlopen would search are examined.  */
03746 int
03747 lt_dlforeachfile (search_path, func, data)
03748      const char *search_path;
03749      int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
03750      lt_ptr data;
03751 {
03752   int is_done = 0;
03753 
03754   if (search_path)
03755     {
03756       /* If a specific path was passed, search only the directories
03757          listed in it.  */
03758       is_done = foreach_dirinpath (search_path, 0,
03759                                    foreachfile_callback, func, data);
03760     }
03761   else
03762     {
03763       /* Otherwise search the default paths.  */
03764       is_done = foreach_dirinpath (user_search_path, 0,
03765                                    foreachfile_callback, func, data);
03766       if (!is_done)
03767         {
03768           is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
03769                                        foreachfile_callback, func, data);
03770         }
03771 
03772 #ifdef LTDL_SHLIBPATH_VAR
03773       if (!is_done)
03774         {
03775           is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
03776                                        foreachfile_callback, func, data);
03777         }
03778 #endif
03779 #ifdef LTDL_SYSSEARCHPATH
03780       if (!is_done)
03781         {
03782           is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
03783                                        foreachfile_callback, func, data);
03784         }
03785 #endif
03786     }
03787 
03788   return is_done;
03789 }
03790 
03791 int
03792 lt_dlclose (handle)
03793      lt_dlhandle handle;
03794 {
03795   lt_dlhandle cur, last;
03796   int errors = 0;
03797 
03798   LT_DLMUTEX_LOCK ();
03799 
03800   /* check whether the handle is valid */
03801   last = cur = handles;
03802   while (cur && handle != cur)
03803     {
03804       last = cur;
03805       cur = cur->next;
03806     }
03807 
03808   if (!cur)
03809     {
03810       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
03811       ++errors;
03812       goto done;
03813     }
03814 
03815   handle->info.ref_count--;
03816 
03817   /* Note that even with resident modules, we must track the ref_count
03818      correctly incase the user decides to reset the residency flag
03819      later (even though the API makes no provision for that at the
03820      moment).  */
03821   if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
03822     {
03823       lt_user_data data = handle->loader->dlloader_data;
03824 
03825       if (handle != handles)
03826         {
03827           last->next = handle->next;
03828         }
03829       else
03830         {
03831           handles = handle->next;
03832         }
03833 
03834       errors += handle->loader->module_close (data, handle->module);
03835       errors += unload_deplibs(handle);
03836 
03837       /* It is up to the callers to free the data itself.  */
03838       LT_DLFREE (handle->caller_data);
03839 
03840       LT_DLFREE (handle->info.filename);
03841       LT_DLFREE (handle->info.name);
03842       LT_DLFREE (handle);
03843 
03844       goto done;
03845     }
03846 
03847   if (LT_DLIS_RESIDENT (handle))
03848     {
03849       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
03850       ++errors;
03851     }
03852 
03853  done:
03854   LT_DLMUTEX_UNLOCK ();
03855 
03856   return errors;
03857 }
03858 
03859 lt_ptr
03860 lt_dlsym (handle, symbol)
03861      lt_dlhandle handle;
03862      const char *symbol;
03863 {
03864   size_t lensym;
03865   char  lsym[LT_SYMBOL_LENGTH];
03866   char  *sym;
03867   lt_ptr address;
03868   lt_user_data data;
03869 
03870   if (!handle)
03871     {
03872       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
03873       return 0;
03874     }
03875 
03876   if (!symbol)
03877     {
03878       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
03879       return 0;
03880     }
03881 
03882   lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
03883                                         + LT_STRLEN (handle->info.name);
03884 
03885   if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
03886     {
03887       sym = lsym;
03888     }
03889   else
03890     {
03891       sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
03892       if (!sym)
03893         {
03894           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
03895           return 0;
03896         }
03897     }
03898 
03899   data = handle->loader->dlloader_data;
03900   if (handle->info.name)
03901     {
03902       const char *saved_error;
03903 
03904       LT_DLMUTEX_GETERROR (saved_error);
03905 
03906       /* this is a libtool module */
03907       if (handle->loader->sym_prefix)
03908         {
03909           strcpy(sym, handle->loader->sym_prefix);
03910           strcat(sym, handle->info.name);
03911         }
03912       else
03913         {
03914           strcpy(sym, handle->info.name);
03915         }
03916 
03917       strcat(sym, "_LTX_");
03918       strcat(sym, symbol);
03919 
03920       /* try "modulename_LTX_symbol" */
03921       address = handle->loader->find_sym (data, handle->module, sym);
03922       if (address)
03923         {
03924           if (sym != lsym)
03925             {
03926               LT_DLFREE (sym);
03927             }
03928           return address;
03929         }
03930       LT_DLMUTEX_SETERROR (saved_error);
03931     }
03932 
03933   /* otherwise try "symbol" */
03934   if (handle->loader->sym_prefix)
03935     {
03936       strcpy(sym, handle->loader->sym_prefix);
03937       strcat(sym, symbol);
03938     }
03939   else
03940     {
03941       strcpy(sym, symbol);
03942     }
03943 
03944   address = handle->loader->find_sym (data, handle->module, sym);
03945   if (sym != lsym)
03946     {
03947       LT_DLFREE (sym);
03948     }
03949 
03950   return address;
03951 }
03952 
03953 const char *
03954 lt_dlerror ()
03955 {
03956   const char *error;
03957 
03958   LT_DLMUTEX_GETERROR (error);
03959   LT_DLMUTEX_SETERROR (0);
03960 
03961   return error ? error : NULL;
03962 }
03963 
03964 static int
03965 lt_dlpath_insertdir (ppath, before, dir)
03966      char **ppath;
03967      char *before;
03968      const char *dir;
03969 {
03970   int    errors         = 0;
03971   char  *canonical      = 0;
03972   char  *argz           = 0;
03973   size_t argz_len       = 0;
03974 
03975   assert (ppath);
03976   assert (dir && *dir);
03977 
03978   if (canonicalize_path (dir, &canonical) != 0)
03979     {
03980       ++errors;
03981       goto cleanup;
03982     }
03983 
03984   assert (canonical && *canonical);
03985 
03986   /* If *PPATH is empty, set it to DIR.  */
03987   if (*ppath == 0)
03988     {
03989       assert (!before);         /* BEFORE cannot be set without PPATH.  */
03990       assert (dir);             /* Without DIR, don't call this function!  */
03991 
03992       *ppath = lt_estrdup (dir);
03993       if (*ppath == 0)
03994         ++errors;
03995 
03996       return errors;
03997     }
03998 
03999   assert (ppath && *ppath);
04000 
04001   if (argzize_path (*ppath, &argz, &argz_len) != 0)
04002     {
04003       ++errors;
04004       goto cleanup;
04005     }
04006 
04007   /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
04008      if *PPATH is already canonicalized, and hence does not change length
04009      with respect to ARGZ.  We canonicalize each entry as it is added to
04010      the search path, and don't call this function with (uncanonicalized)
04011      user paths, so this is a fair assumption.  */
04012   if (before)
04013     {
04014       assert (*ppath <= before);
04015       assert (before - *ppath <= strlen (*ppath));
04016 
04017       before = before - *ppath + argz;
04018     }
04019 
04020   if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
04021     {
04022       ++errors;
04023       goto cleanup;
04024     }
04025 
04026   argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
04027   LT_DLMEM_REASSIGN (*ppath,  argz);
04028 
04029  cleanup:
04030   LT_DLFREE (canonical);
04031   LT_DLFREE (argz);
04032 
04033   return errors;
04034 }
04035 
04036 int
04037 lt_dladdsearchdir (search_dir)
04038      const char *search_dir;
04039 {
04040   int errors = 0;
04041 
04042   if (search_dir && *search_dir)
04043     {
04044       LT_DLMUTEX_LOCK ();
04045       if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
04046         ++errors;
04047       LT_DLMUTEX_UNLOCK ();
04048     }
04049 
04050   return errors;
04051 }
04052 
04053 int
04054 lt_dlinsertsearchdir (before, search_dir)
04055      const char *before;
04056      const char *search_dir;
04057 {
04058   int errors = 0;
04059 
04060   if (before)
04061     {
04062       LT_DLMUTEX_LOCK ();
04063       if ((before < user_search_path)
04064           || (before >= user_search_path + LT_STRLEN (user_search_path)))
04065         {
04066           LT_DLMUTEX_UNLOCK ();
04067           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
04068           return 1;
04069         }
04070       LT_DLMUTEX_UNLOCK ();
04071     }
04072 
04073   if (search_dir && *search_dir)
04074     {
04075       LT_DLMUTEX_LOCK ();
04076       if (lt_dlpath_insertdir (&user_search_path,
04077                                (char *) before, search_dir) != 0)
04078         {
04079           ++errors;
04080         }
04081       LT_DLMUTEX_UNLOCK ();
04082     }
04083 
04084   return errors;
04085 }
04086 
04087 int
04088 lt_dlsetsearchpath (search_path)
04089      const char *search_path;
04090 {
04091   int   errors      = 0;
04092 
04093   LT_DLMUTEX_LOCK ();
04094   LT_DLFREE (user_search_path);
04095   LT_DLMUTEX_UNLOCK ();
04096 
04097   if (!search_path || !LT_STRLEN (search_path))
04098     {
04099       return errors;
04100     }
04101 
04102   LT_DLMUTEX_LOCK ();
04103   if (canonicalize_path (search_path, &user_search_path) != 0)
04104     ++errors;
04105   LT_DLMUTEX_UNLOCK ();
04106 
04107   return errors;
04108 }
04109 
04110 const char *
04111 lt_dlgetsearchpath ()
04112 {
04113   const char *saved_path;
04114 
04115   LT_DLMUTEX_LOCK ();
04116   saved_path = user_search_path;
04117   LT_DLMUTEX_UNLOCK ();
04118 
04119   return saved_path;
04120 }
04121 
04122 int
04123 lt_dlmakeresident (handle)
04124      lt_dlhandle handle;
04125 {
04126   int errors = 0;
04127 
04128   if (!handle)
04129     {
04130       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
04131       ++errors;
04132     }
04133   else
04134     {
04135       LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
04136     }
04137 
04138   return errors;
04139 }
04140 
04141 int
04142 lt_dlisresident (handle)
04143      lt_dlhandle handle;
04144 {
04145   if (!handle)
04146     {
04147       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
04148       return -1;
04149     }
04150 
04151   return LT_DLIS_RESIDENT (handle);
04152 }
04153 
04154 
04155 
04156 
04157 /* --- MODULE INFORMATION --- */
04158 
04159 const lt_dlinfo *
04160 lt_dlgetinfo (handle)
04161      lt_dlhandle handle;
04162 {
04163   if (!handle)
04164     {
04165       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
04166       return 0;
04167     }
04168 
04169   return &(handle->info);
04170 }
04171 
04172 lt_dlhandle
04173 lt_dlhandle_next (place)
04174      lt_dlhandle place;
04175 {
04176   return place ? place->next : handles;
04177 }
04178 
04179 int
04180 lt_dlforeach (func, data)
04181      int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
04182      lt_ptr data;
04183 {
04184   int errors = 0;
04185   lt_dlhandle cur;
04186 
04187   LT_DLMUTEX_LOCK ();
04188 
04189   cur = handles;
04190   while (cur)
04191     {
04192       lt_dlhandle tmp = cur;
04193 
04194       cur = cur->next;
04195       if ((*func) (tmp, data))
04196         {
04197           ++errors;
04198           break;
04199         }
04200     }
04201 
04202   LT_DLMUTEX_UNLOCK ();
04203 
04204   return errors;
04205 }
04206 
04207 lt_dlcaller_id
04208 lt_dlcaller_register ()
04209 {
04210   static lt_dlcaller_id last_caller_id = 0;
04211   int result;
04212 
04213   LT_DLMUTEX_LOCK ();
04214   result = ++last_caller_id;
04215   LT_DLMUTEX_UNLOCK ();
04216 
04217   return result;
04218 }
04219 
04220 lt_ptr
04221 lt_dlcaller_set_data (key, handle, data)
04222      lt_dlcaller_id key;
04223      lt_dlhandle handle;
04224      lt_ptr data;
04225 {
04226   int n_elements = 0;
04227   lt_ptr stale = (lt_ptr) 0;
04228   int i;
04229 
04230   /* This needs to be locked so that the caller data can be updated
04231      simultaneously by different threads.  */
04232   LT_DLMUTEX_LOCK ();
04233 
04234   if (handle->caller_data)
04235     while (handle->caller_data[n_elements].key)
04236       ++n_elements;
04237 
04238   for (i = 0; i < n_elements; ++i)
04239     {
04240       if (handle->caller_data[i].key == key)
04241         {
04242           stale = handle->caller_data[i].data;
04243           break;
04244         }
04245     }
04246 
04247   /* Ensure that there is enough room in this handle's caller_data
04248      array to accept a new element (and an empty end marker).  */
04249   if (i == n_elements)
04250     {
04251       lt_caller_data *temp
04252         = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
04253 
04254       if (!temp)
04255         {
04256           stale = 0;
04257           goto done;
04258         }
04259 
04260       handle->caller_data = temp;
04261 
04262       /* We only need this if we needed to allocate a new caller_data.  */
04263       handle->caller_data[i].key  = key;
04264       handle->caller_data[1+ i].key = 0;
04265     }
04266 
04267   handle->caller_data[i].data = data;
04268 
04269  done:
04270   LT_DLMUTEX_UNLOCK ();
04271 
04272   return stale;
04273 }
04274 
04275 lt_ptr
04276 lt_dlcaller_get_data  (key, handle)
04277      lt_dlcaller_id key;
04278      lt_dlhandle handle;
04279 {
04280   lt_ptr result = (lt_ptr) 0;
04281 
04282   /* This needs to be locked so that the caller data isn't updated by
04283      another thread part way through this function.  */
04284   LT_DLMUTEX_LOCK ();
04285 
04286   /* Locate the index of the element with a matching KEY.  */
04287   {
04288     int i;
04289     for (i = 0; handle->caller_data[i].key; ++i)
04290       {
04291         if (handle->caller_data[i].key == key)
04292           {
04293             result = handle->caller_data[i].data;
04294             break;
04295           }
04296       }
04297   }
04298 
04299   LT_DLMUTEX_UNLOCK ();
04300 
04301   return result;
04302 }
04303 
04304 
04305 
04306 /* --- USER MODULE LOADER API --- */
04307 
04308 
04309 int
04310 lt_dlloader_add (place, dlloader, loader_name)
04311      lt_dlloader *place;
04312      const struct lt_user_dlloader *dlloader;
04313      const char *loader_name;
04314 {
04315   int errors = 0;
04316   lt_dlloader *node = 0, *ptr = 0;
04317 
04318   if ((dlloader == 0)   /* diagnose null parameters */
04319       || (dlloader->module_open == 0)
04320       || (dlloader->module_close == 0)
04321       || (dlloader->find_sym == 0))
04322     {
04323       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
04324       return 1;
04325     }
04326 
04327   /* Create a new dlloader node with copies of the user callbacks.  */
04328   node = LT_EMALLOC (lt_dlloader, 1);
04329   if (!node)
04330     return 1;
04331 
04332   node->next            = 0;
04333   node->loader_name     = loader_name;
04334   node->sym_prefix      = dlloader->sym_prefix;
04335   node->dlloader_exit   = dlloader->dlloader_exit;
04336   node->module_open     = dlloader->module_open;
04337   node->module_close    = dlloader->module_close;
04338   node->find_sym        = dlloader->find_sym;
04339   node->dlloader_data   = dlloader->dlloader_data;
04340 
04341   LT_DLMUTEX_LOCK ();
04342   if (!loaders)
04343     {
04344       /* If there are no loaders, NODE becomes the list! */
04345       loaders = node;
04346     }
04347   else if (!place)
04348     {
04349       /* If PLACE is not set, add NODE to the end of the
04350          LOADERS list. */
04351       for (ptr = loaders; ptr->next; ptr = ptr->next)
04352         {
04353           /*NOWORK*/;
04354         }
04355 
04356       ptr->next = node;
04357     }
04358   else if (loaders == place)
04359     {
04360       /* If PLACE is the first loader, NODE goes first. */
04361       node->next = place;
04362       loaders = node;
04363     }
04364   else
04365     {
04366       /* Find the node immediately preceding PLACE. */
04367       for (ptr = loaders; ptr->next != place; ptr = ptr->next)
04368         {
04369           /*NOWORK*/;
04370         }
04371 
04372       if (ptr->next != place)
04373         {
04374           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
04375           ++errors;
04376         }
04377       else
04378         {
04379           /* Insert NODE between PTR and PLACE. */
04380           node->next = place;
04381           ptr->next  = node;
04382         }
04383     }
04384 
04385   LT_DLMUTEX_UNLOCK ();
04386 
04387   return errors;
04388 }
04389 
04390 int
04391 lt_dlloader_remove (loader_name)
04392      const char *loader_name;
04393 {
04394   lt_dlloader *place = lt_dlloader_find (loader_name);
04395   lt_dlhandle handle;
04396   int errors = 0;
04397 
04398   if (!place)
04399     {
04400       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
04401       return 1;
04402     }
04403 
04404   LT_DLMUTEX_LOCK ();
04405 
04406   /* Fail if there are any open modules which use this loader. */
04407   for  (handle = handles; handle; handle = handle->next)
04408     {
04409       if (handle->loader == place)
04410         {
04411           LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
04412           ++errors;
04413           goto done;
04414         }
04415     }
04416 
04417   if (place == loaders)
04418     {
04419       /* PLACE is the first loader in the list. */
04420       loaders = loaders->next;
04421     }
04422   else
04423     {
04424       /* Find the loader before the one being removed. */
04425       lt_dlloader *prev;
04426       for (prev = loaders; prev->next; prev = prev->next)
04427         {
04428           if (!strcmp (prev->next->loader_name, loader_name))
04429             {
04430               break;
04431             }
04432         }
04433 
04434       place = prev->next;
04435       prev->next = prev->next->next;
04436     }
04437 
04438   if (place->dlloader_exit)
04439     {
04440       errors = place->dlloader_exit (place->dlloader_data);
04441     }
04442 
04443   LT_DLFREE (place);
04444 
04445  done:
04446   LT_DLMUTEX_UNLOCK ();
04447 
04448   return errors;
04449 }
04450 
04451 lt_dlloader *
04452 lt_dlloader_next (place)
04453      lt_dlloader *place;
04454 {
04455   lt_dlloader *next;
04456 
04457   LT_DLMUTEX_LOCK ();
04458   next = place ? place->next : loaders;
04459   LT_DLMUTEX_UNLOCK ();
04460 
04461   return next;
04462 }
04463 
04464 const char *
04465 lt_dlloader_name (place)
04466      lt_dlloader *place;
04467 {
04468   const char *name = 0;
04469 
04470   if (place)
04471     {
04472       LT_DLMUTEX_LOCK ();
04473       name = place ? place->loader_name : 0;
04474       LT_DLMUTEX_UNLOCK ();
04475     }
04476   else
04477     {
04478       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
04479     }
04480 
04481   return name;
04482 }
04483 
04484 lt_user_data *
04485 lt_dlloader_data (place)
04486      lt_dlloader *place;
04487 {
04488   lt_user_data *data = 0;
04489 
04490   if (place)
04491     {
04492       LT_DLMUTEX_LOCK ();
04493       data = place ? &(place->dlloader_data) : 0;
04494       LT_DLMUTEX_UNLOCK ();
04495     }
04496   else
04497     {
04498       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
04499     }
04500 
04501   return data;
04502 }
04503 
04504 lt_dlloader *
04505 lt_dlloader_find (loader_name)
04506      const char *loader_name;
04507 {
04508   lt_dlloader *place = 0;
04509 
04510   LT_DLMUTEX_LOCK ();
04511   for (place = loaders; place; place = place->next)
04512     {
04513       if (strcmp (place->loader_name, loader_name) == 0)
04514         {
04515           break;
04516         }
04517     }
04518   LT_DLMUTEX_UNLOCK ();
04519 
04520   return place;
04521 }


© 2007, Los Alamos National Security, LLC.