"Fossies" - the Fresh Open Source Software Archive

Member "libmcrypt-2.5.8/libltdl/ltdl.c" (8 Mar 2003, 84843 Bytes) of package /linux/privat/old/libmcrypt-2.5.8.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ltdl.c" see the Fossies "Dox" file reference documentation.

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