root/libltdl/ltdl.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lt__alloc_die_callback
  2. loader_init_callback
  3. loader_init
  4. lt_dlinit
  5. lt_dlexit
  6. tryall_dlopen
  7. tryall_dlopen_module
  8. find_module
  9. canonicalize_path
  10. argzize_path
  11. foreach_dirinpath
  12. find_file_callback
  13. find_file
  14. find_handle_callback
  15. find_handle
  16. load_deplibs
  17. load_deplibs
  18. unload_deplibs
  19. trim
  20. parse_dotla_file
  21. try_dlopen
  22. file_not_found
  23. has_library_ext
  24. lt_dladvise_init
  25. lt_dladvise_destroy
  26. lt_dladvise_ext
  27. lt_dladvise_resident
  28. lt_dladvise_local
  29. lt_dladvise_global
  30. lt_dladvise_preload
  31. lt_dlopen
  32. lt_dlopenext
  33. lt_dlopenadvise
  34. lt_argz_insert
  35. lt_argz_insertinorder
  36. lt_argz_insertdir
  37. list_files_by_dir
  38. foreachfile_callback
  39. lt_dlforeachfile
  40. lt_dlclose
  41. lt_dlsym
  42. lt_dlerror
  43. lt_dlpath_insertdir
  44. lt_dladdsearchdir
  45. lt_dlinsertsearchdir
  46. lt_dlsetsearchpath
  47. lt_dlgetsearchpath
  48. lt_dlmakeresident
  49. lt_dlisresident
  50. lt_dlinterface_register
  51. lt_dlinterface_free
  52. lt_dlcaller_set_data
  53. lt_dlcaller_get_data
  54. lt_dlgetinfo
  55. lt_dlhandle_iterate
  56. lt_dlhandle_fetch
  57. lt_dlhandle_map

   1 /* ltdl.c -- system independent dlopen wrapper
   2 
   3    Copyright (C) 1998, 1999, 2000, 2004, 2005, 2006,
   4                  2007, 2008, 2011 Free Software Foundation, Inc.
   5    Written by Thomas Tanner, 1998
   6 
   7    NOTE: The canonical source of this file is maintained with the
   8    GNU Libtool package.  Report bugs to bug-libtool@gnu.org.
   9 
  10 GNU Libltdl is free software; you can redistribute it and/or
  11 modify it under the terms of the GNU Lesser General Public
  12 License as published by the Free Software Foundation; either
  13 version 2 of the License, or (at your option) any later version.
  14 
  15 As a special exception to the GNU Lesser General Public License,
  16 if you distribute this file as part of a program or library that
  17 is built using GNU Libtool, you may include this file under the
  18 same distribution terms that you use for the rest of that program.
  19 
  20 GNU Libltdl is distributed in the hope that it will be useful,
  21 but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23 GNU Lesser General Public License for more details.
  24 
  25 You should have received a copy of the GNU Lesser General Public
  26 License along with GNU Libltdl; see the file COPYING.LIB.  If not, a
  27 copy can be downloaded from  http://www.gnu.org/licenses/lgpl.html,
  28 or obtained by writing to the Free Software Foundation, Inc.,
  29 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  30 */
  31 
  32 #include "lt__private.h"
  33 #include "lt_system.h"
  34 #include "lt_dlloader.h"
  35 
  36 
  37 /* --- MANIFEST CONSTANTS --- */
  38 
  39 
  40 /* Standard libltdl search path environment variable name  */
  41 #undef  LTDL_SEARCHPATH_VAR
  42 #define LTDL_SEARCHPATH_VAR     "LTDL_LIBRARY_PATH"
  43 
  44 /* Standard libtool archive file extension.  */
  45 #undef  LT_ARCHIVE_EXT
  46 #define LT_ARCHIVE_EXT  ".la"
  47 
  48 /* max. filename length */
  49 #if !defined(LT_FILENAME_MAX)
  50 #  define LT_FILENAME_MAX       1024
  51 #endif
  52 
  53 #if !defined(LT_LIBEXT)
  54 #  define LT_LIBEXT "a"
  55 #endif
  56 
  57 #if !defined(LT_LIBPREFIX)
  58 #  define LT_LIBPREFIX "lib"
  59 #endif
  60 
  61 /* This is the maximum symbol size that won't require malloc/free */
  62 #undef  LT_SYMBOL_LENGTH
  63 #define LT_SYMBOL_LENGTH        128
  64 
  65 /* This accounts for the _LTX_ separator */
  66 #undef  LT_SYMBOL_OVERHEAD
  67 #define LT_SYMBOL_OVERHEAD      5
  68 
  69 /* Various boolean flags can be stored in the flags field of an
  70    lt_dlhandle... */
  71 #define LT_DLIS_RESIDENT(handle)  ((handle)->info.is_resident)
  72 #define LT_DLIS_SYMGLOBAL(handle) ((handle)->info.is_symglobal)
  73 #define LT_DLIS_SYMLOCAL(handle)  ((handle)->info.is_symlocal)
  74 
  75 
  76 static  const char      objdir[]                = LT_OBJDIR;
  77 static  const char      archive_ext[]           = LT_ARCHIVE_EXT;
  78 static  const char      libext[]                = LT_LIBEXT;
  79 static  const char      libprefix[]             = LT_LIBPREFIX;
  80 #if defined(LT_MODULE_EXT)
  81 static  const char      shlib_ext[]             = LT_MODULE_EXT;
  82 #endif
  83 /* If the loadable module suffix is not the same as the linkable
  84  * shared library suffix, this will be defined. */
  85 #if defined(LT_SHARED_EXT)
  86 static  const char      shared_ext[]            = LT_SHARED_EXT;
  87 #endif
  88 #if defined(LT_DLSEARCH_PATH)
  89 static  const char      sys_dlsearch_path[]     = LT_DLSEARCH_PATH;
  90 #endif
  91 
  92 
  93 
  94 
  95 /* --- DYNAMIC MODULE LOADING --- */
  96 
  97 
  98 /* The type of a function used at each iteration of  foreach_dirinpath().  */
  99 typedef int     foreach_callback_func (char *filename, void *data1,
 100                                        void *data2);
 101 /* foreachfile_callback itself calls a function of this type: */
 102 typedef int     file_worker_func      (const char *filename, void *data);
 103 
 104 
 105 static  int     foreach_dirinpath     (const char *search_path,
 106                                        const char *base_name,
 107                                        foreach_callback_func *func,
 108                                        void *data1, void *data2);
 109 static  int     find_file_callback    (char *filename, void *data1,
 110                                        void *data2);
 111 static  int     find_handle_callback  (char *filename, void *data,
 112                                        void *ignored);
 113 static  int     foreachfile_callback  (char *filename, void *data1,
 114                                        void *data2);
 115 
 116 
 117 static  int     canonicalize_path     (const char *path, char **pcanonical);
 118 static  int     argzize_path          (const char *path,
 119                                        char **pargz, size_t *pargz_len);
 120 static  FILE   *find_file             (const char *search_path,
 121                                        const char *base_name, char **pdir);
 122 static  lt_dlhandle *find_handle      (const char *search_path,
 123                                        const char *base_name,
 124                                        lt_dlhandle *handle,
 125                                        lt_dladvise advise);
 126 static  int     find_module           (lt_dlhandle *handle, const char *dir,
 127                                        const char *libdir, const char *dlname,
 128                                        const char *old_name, int installed,
 129                                        lt_dladvise advise);
 130 static  int     has_library_ext       (const char *filename);
 131 static  int     load_deplibs          (lt_dlhandle handle,  char *deplibs);
 132 static  int     trim                  (char **dest, const char *str);
 133 static  int     try_dlopen            (lt_dlhandle *handle,
 134                                        const char *filename, const char *ext,
 135                                        lt_dladvise advise);
 136 static  int     tryall_dlopen         (lt_dlhandle *handle,
 137                                        const char *filename,
 138                                        lt_dladvise padvise,
 139                                        const lt_dlvtable *vtable);
 140 static  int     unload_deplibs        (lt_dlhandle handle);
 141 static  int     lt_argz_insert        (char **pargz, size_t *pargz_len,
 142                                        char *before, const char *entry);
 143 static  int     lt_argz_insertinorder (char **pargz, size_t *pargz_len,
 144                                        const char *entry);
 145 static  int     lt_argz_insertdir     (char **pargz, size_t *pargz_len,
 146                                        const char *dirnam, struct dirent *dp);
 147 static  int     lt_dlpath_insertdir   (char **ppath, char *before,
 148                                        const char *dir);
 149 static  int     list_files_by_dir     (const char *dirnam,
 150                                        char **pargz, size_t *pargz_len);
 151 static  int     file_not_found        (void);
 152 
 153 #ifdef HAVE_LIBDLLOADER
 154 static  int     loader_init_callback  (lt_dlhandle handle);
 155 #endif /* HAVE_LIBDLLOADER */
 156 
 157 static  int     loader_init           (lt_get_vtable *vtable_func,
 158                                        lt_user_data data);
 159 
 160 static  char           *user_search_path= 0;
 161 static  lt_dlhandle     handles = 0;
 162 static  int             initialized     = 0;
 163 
 164 /* Our memory failure callback sets the error message to be passed back
 165    up to the client, so we must be careful to return from mallocation
 166    callers if allocation fails (as this callback returns!!).  */
 167 void
 168 lt__alloc_die_callback (void)
 169 {
 170   LT__SETERROR (NO_MEMORY);
 171 }
 172 
 173 #ifdef HAVE_LIBDLLOADER
 174 /* This function is called to initialise each preloaded module loader,
 175    and hook it into the list of loaders to be used when attempting to
 176    dlopen an application module.  */
 177 static int
 178 loader_init_callback (lt_dlhandle handle)
 179 {
 180   lt_get_vtable *vtable_func = (lt_get_vtable *) lt_dlsym (handle, "get_vtable");
 181   return loader_init (vtable_func, 0);
 182 }
 183 #endif /* HAVE_LIBDLLOADER */
 184 
 185 static int
 186 loader_init (lt_get_vtable *vtable_func, lt_user_data data)
 187 {
 188   const lt_dlvtable *vtable = 0;
 189   int errors = 0;
 190 
 191   if (vtable_func)
 192     {
 193       vtable = (*vtable_func) (data);
 194     }
 195 
 196   /* lt_dlloader_add will LT__SETERROR if it fails.  */
 197   errors += lt_dlloader_add (vtable);
 198 
 199   assert (errors || vtable);
 200 
 201   if ((!errors) && vtable->dlloader_init)
 202     {
 203       if ((*vtable->dlloader_init) (vtable->dlloader_data))
 204         {
 205           LT__SETERROR (INIT_LOADER);
 206           ++errors;
 207         }
 208     }
 209 
 210   return errors;
 211 }
 212 
 213 /* Bootstrap the loader loading with the preopening loader.  */
 214 #define get_vtable              preopen_LTX_get_vtable
 215 #define preloaded_symbols       LT_CONC3(lt_, LTDLOPEN, _LTX_preloaded_symbols)
 216 
 217 LT_BEGIN_C_DECLS
 218 LT_SCOPE const lt_dlvtable *    get_vtable (lt_user_data data);
 219 LT_END_C_DECLS
 220 #ifdef HAVE_LIBDLLOADER
 221 extern LT_DLSYM_CONST lt_dlsymlist preloaded_symbols[];
 222 #endif
 223 
 224 /* Initialize libltdl. */
 225 int
 226 lt_dlinit (void)
 227 {
 228   int   errors  = 0;
 229 
 230   /* Initialize only at first call. */
 231   if (++initialized == 1)
 232     {
 233       lt__alloc_die     = lt__alloc_die_callback;
 234       handles           = 0;
 235       user_search_path  = 0; /* empty search path */
 236 
 237       /* First set up the statically loaded preload module loader, so
 238          we can use it to preopen the other loaders we linked in at
 239          compile time.  */
 240       errors += loader_init (get_vtable, 0);
 241 
 242       /* Now open all the preloaded module loaders, so the application
 243          can use _them_ to lt_dlopen its own modules.  */
 244 #ifdef HAVE_LIBDLLOADER
 245       if (!errors)
 246         {
 247           errors += lt_dlpreload (preloaded_symbols);
 248         }
 249 
 250       if (!errors)
 251         {
 252           errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);
 253         }
 254 #endif /* HAVE_LIBDLLOADER */
 255     }
 256 
 257 #ifdef LT_DEBUG_LOADERS
 258   lt_dlloader_dump();
 259 #endif
 260 
 261   return errors;
 262 }
 263 
 264 int
 265 lt_dlexit (void)
 266 {
 267   /* shut down libltdl */
 268   lt_dlloader *loader   = 0;
 269   lt_dlhandle  handle   = handles;
 270   int          errors   = 0;
 271 
 272   if (!initialized)
 273     {
 274       LT__SETERROR (SHUTDOWN);
 275       ++errors;
 276       goto done;
 277     }
 278 
 279   /* shut down only at last call. */
 280   if (--initialized == 0)
 281     {
 282       int       level;
 283 
 284       while (handles && LT_DLIS_RESIDENT (handles))
 285         {
 286           handles = handles->next;
 287         }
 288 
 289       /* close all modules */
 290       for (level = 1; handle; ++level)
 291         {
 292           lt_dlhandle cur = handles;
 293           int saw_nonresident = 0;
 294 
 295           while (cur)
 296             {
 297               lt_dlhandle tmp = cur;
 298               cur = cur->next;
 299               if (!LT_DLIS_RESIDENT (tmp))
 300                 {
 301                   saw_nonresident = 1;
 302                   if (tmp->info.ref_count <= level)
 303                     {
 304                       if (lt_dlclose (tmp))
 305                         {
 306                           ++errors;
 307                         }
 308                       /* Make sure that the handle pointed to by 'cur' still exists.
 309                          lt_dlclose recursively closes dependent libraries which removes
 310                          them from the linked list.  One of these might be the one
 311                          pointed to by 'cur'.  */
 312                       if (cur)
 313                         {
 314                           for (tmp = handles; tmp; tmp = tmp->next)
 315                             if (tmp == cur)
 316                               break;
 317                           if (! tmp)
 318                             cur = handles;
 319                         }
 320                     }
 321                 }
 322             }
 323           /* done if only resident modules are left */
 324           if (!saw_nonresident)
 325             break;
 326         }
 327 
 328       /* When removing loaders, we can only find out failure by testing
 329          the error string, so avoid a spurious one from an earlier
 330          failed command. */
 331       if (!errors)
 332         LT__SETERRORSTR (0);
 333 
 334       /* close all loaders */
 335       for (loader = (lt_dlloader *) lt_dlloader_next (NULL); loader;)
 336         {
 337           lt_dlloader *next   = (lt_dlloader *) lt_dlloader_next (loader);
 338           lt_dlvtable *vtable = (lt_dlvtable *) lt_dlloader_get (loader);
 339 
 340           if ((vtable = lt_dlloader_remove ((char *) vtable->name)))
 341             {
 342               FREE (vtable);
 343             }
 344           else
 345             {
 346               /* ignore errors due to resident modules */
 347               const char *err;
 348               LT__GETERROR (err);
 349               if (err)
 350                 ++errors;
 351             }
 352 
 353           loader = next;
 354         }
 355 
 356       FREE(user_search_path);
 357     }
 358 
 359  done:
 360   return errors;
 361 }
 362 
 363 
 364 /* Try VTABLE or, if VTABLE is NULL, all available loaders for FILENAME.
 365    If the library is not successfully loaded, return non-zero.  Otherwise,
 366    the dlhandle is stored at the address given in PHANDLE.  */
 367 static int
 368 tryall_dlopen (lt_dlhandle *phandle, const char *filename,
 369                lt_dladvise advise, const lt_dlvtable *vtable)
 370 {
 371   lt_dlhandle   handle          = handles;
 372   const char *  saved_error     = 0;
 373   int           errors          = 0;
 374 
 375 #ifdef LT_DEBUG_LOADERS
 376   fprintf (stderr, "tryall_dlopen (%s, %s)\n",
 377            filename ? filename : "(null)",
 378            vtable ? vtable->name : "(ALL)");
 379 #endif
 380 
 381   LT__GETERROR (saved_error);
 382 
 383   /* check whether the module was already opened */
 384   for (;handle; handle = handle->next)
 385     {
 386       if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */
 387           || (handle->info.filename && filename
 388               && streq (handle->info.filename, filename)))
 389         {
 390           break;
 391         }
 392     }
 393 
 394   if (handle)
 395     {
 396       ++handle->info.ref_count;
 397       *phandle = handle;
 398       goto done;
 399     }
 400 
 401   handle = *phandle;
 402   if (filename)
 403     {
 404       /* Comment out the check of file permissions using access.
 405          This call seems to always return -1 with error EACCES.
 406       */
 407       /* We need to catch missing file errors early so that
 408          file_not_found() can detect what happened.
 409       if (access (filename, R_OK) != 0)
 410         {
 411           LT__SETERROR (FILE_NOT_FOUND);
 412           ++errors;
 413           goto done;
 414         } */
 415 
 416       handle->info.filename = lt__strdup (filename);
 417       if (!handle->info.filename)
 418         {
 419           ++errors;
 420           goto done;
 421         }
 422     }
 423   else
 424     {
 425       handle->info.filename = 0;
 426     }
 427 
 428   {
 429     lt_dlloader loader = lt_dlloader_next (0);
 430     const lt_dlvtable *loader_vtable;
 431 
 432     do
 433       {
 434         if (vtable)
 435           loader_vtable = vtable;
 436         else
 437           loader_vtable = lt_dlloader_get (loader);
 438 
 439 #ifdef LT_DEBUG_LOADERS
 440         fprintf (stderr, "Calling %s->module_open (%s)\n",
 441                  (loader_vtable && loader_vtable->name) ? loader_vtable->name : "(null)",
 442                  filename ? filename : "(null)");
 443 #endif
 444         handle->module = (*loader_vtable->module_open) (loader_vtable->dlloader_data,
 445                                                         filename, advise);
 446 #ifdef LT_DEBUG_LOADERS
 447         fprintf (stderr, "  Result: %s\n",
 448                  handle->module ? "Success" : "Failed");
 449 #endif
 450 
 451         if (handle->module != 0)
 452           {
 453             if (advise)
 454               {
 455                 handle->info.is_resident  = advise->is_resident;
 456                 handle->info.is_symglobal = advise->is_symglobal;
 457                 handle->info.is_symlocal  = advise->is_symlocal;
 458               }
 459             break;
 460           }
 461       }
 462     while (!vtable && (loader = lt_dlloader_next (loader)));
 463 
 464     /* If VTABLE was given but couldn't open the module, or VTABLE wasn't
 465        given but we exhausted all loaders without opening the module, bail
 466        out!  */
 467     if ((vtable && !handle->module)
 468         || (!vtable && !loader))
 469       {
 470         FREE (handle->info.filename);
 471         ++errors;
 472         goto done;
 473       }
 474 
 475     handle->vtable = loader_vtable;
 476   }
 477 
 478   LT__SETERRORSTR (saved_error);
 479 
 480  done:
 481   return errors;
 482 }
 483 
 484 
 485 static int
 486 tryall_dlopen_module (lt_dlhandle *handle, const char *prefix,
 487                       const char *dirname, const char *dlname,
 488                       lt_dladvise advise)
 489 {
 490   int      error        = 0;
 491   char     *filename    = 0;
 492   size_t   filename_len = 0;
 493   size_t   dirname_len  = LT_STRLEN (dirname);
 494 
 495   assert (handle);
 496   assert (dirname);
 497   assert (dlname);
 498 #if defined(LT_DIRSEP_CHAR)
 499   /* Only canonicalized names (i.e. with DIRSEP chars already converted)
 500      should make it into this function:  */
 501   assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
 502 #endif
 503 
 504   if (dirname_len > 0)
 505     if (dirname[dirname_len -1] == '/')
 506       --dirname_len;
 507   filename_len = dirname_len + 1 + LT_STRLEN (dlname);
 508 
 509   /* Allocate memory, and combine DIRNAME and MODULENAME into it.
 510      The PREFIX (if any) is handled below.  */
 511   filename  = MALLOC (char, filename_len + 1);
 512   if (!filename)
 513     return 1;
 514 
 515   sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
 516 
 517   /* Now that we have combined DIRNAME and MODULENAME, if there is
 518      also a PREFIX to contend with, simply recurse with the arguments
 519      shuffled.  Otherwise, attempt to open FILENAME as a module.  */
 520   if (prefix)
 521     {
 522       error += tryall_dlopen_module (handle, (const char *) 0,
 523                                      prefix, filename, advise);
 524     }
 525   else if (tryall_dlopen (handle, filename, advise, 0) != 0)
 526     {
 527       ++error;
 528     }
 529 
 530   FREE (filename);
 531   return error;
 532 }
 533 
 534 static int
 535 find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
 536              const char *dlname,  const char *old_name, int installed,
 537              lt_dladvise advise)
 538 {
 539   /* Try to open the old library first; if it was dlpreopened,
 540      we want the preopened version of it, even if a dlopenable
 541      module is available.  */
 542   if (old_name && tryall_dlopen (handle, old_name,
 543                           advise, lt_dlloader_find ("lt_preopen") ) == 0)
 544     {
 545       return 0;
 546     }
 547 
 548   /* Try to open the dynamic library.  */
 549   if (dlname)
 550     {
 551       /* try to open the installed module */
 552       if (installed && libdir)
 553         {
 554           if (tryall_dlopen_module (handle, (const char *) 0,
 555                                     libdir, dlname, advise) == 0)
 556             return 0;
 557         }
 558 
 559       /* try to open the not-installed module */
 560       if (!installed)
 561         {
 562           if (tryall_dlopen_module (handle, dir, objdir,
 563                                     dlname, advise) == 0)
 564             return 0;
 565         }
 566 
 567       /* maybe it was moved to another directory */
 568       {
 569           if (dir && (tryall_dlopen_module (handle, (const char *) 0,
 570                                             dir, dlname, advise) == 0))
 571             return 0;
 572       }
 573     }
 574 
 575   return 1;
 576 }
 577 
 578 
 579 static int
 580 canonicalize_path (const char *path, char **pcanonical)
 581 {
 582   char *canonical = 0;
 583 
 584   assert (path && *path);
 585   assert (pcanonical);
 586 
 587   canonical = MALLOC (char, 1+ LT_STRLEN (path));
 588   if (!canonical)
 589     return 1;
 590 
 591   {
 592     size_t dest = 0;
 593     size_t src;
 594     for (src = 0; path[src] != LT_EOS_CHAR; ++src)
 595       {
 596         /* Path separators are not copied to the beginning or end of
 597            the destination, or if another separator would follow
 598            immediately.  */
 599         if (path[src] == LT_PATHSEP_CHAR)
 600           {
 601             if ((dest == 0)
 602                 || (path[1+ src] == LT_PATHSEP_CHAR)
 603                 || (path[1+ src] == LT_EOS_CHAR))
 604               continue;
 605           }
 606 
 607         /* Anything other than a directory separator is copied verbatim.  */
 608         if ((path[src] != '/')
 609 #if defined(LT_DIRSEP_CHAR)
 610             && (path[src] != LT_DIRSEP_CHAR)
 611 #endif
 612             )
 613           {
 614             canonical[dest++] = path[src];
 615           }
 616         /* Directory separators are converted and copied only if they are
 617            not at the end of a path -- i.e. before a path separator or
 618            NULL terminator.  */
 619         else if ((path[1+ src] != LT_PATHSEP_CHAR)
 620                  && (path[1+ src] != LT_EOS_CHAR)
 621 #if defined(LT_DIRSEP_CHAR)
 622                  && (path[1+ src] != LT_DIRSEP_CHAR)
 623 #endif
 624                  && (path[1+ src] != '/'))
 625           {
 626             canonical[dest++] = '/';
 627           }
 628       }
 629 
 630     /* Add an end-of-string marker at the end.  */
 631     canonical[dest] = LT_EOS_CHAR;
 632   }
 633 
 634   /* Assign new value.  */
 635   *pcanonical = canonical;
 636 
 637   return 0;
 638 }
 639 
 640 static int
 641 argzize_path (const char *path, char **pargz, size_t *pargz_len)
 642 {
 643   error_t error;
 644 
 645   assert (path);
 646   assert (pargz);
 647   assert (pargz_len);
 648 
 649   if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
 650     {
 651       switch (error)
 652         {
 653         case ENOMEM:
 654           LT__SETERROR (NO_MEMORY);
 655           break;
 656         default:
 657           LT__SETERROR (UNKNOWN);
 658           break;
 659         }
 660 
 661       return 1;
 662     }
 663 
 664   return 0;
 665 }
 666 
 667 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
 668    of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
 669    non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
 670    it is appended to each SEARCH_PATH element before FUNC is called.  */
 671 static int
 672 foreach_dirinpath (const char *search_path, const char *base_name,
 673                    foreach_callback_func *func, void *data1, void *data2)
 674 {
 675   int    result         = 0;
 676   size_t filenamesize   = 0;
 677   size_t lenbase        = LT_STRLEN (base_name);
 678   size_t argz_len       = 0;
 679   char *argz            = 0;
 680   char *filename        = 0;
 681   char *canonical       = 0;
 682 
 683   if (!search_path || !*search_path)
 684     {
 685       LT__SETERROR (FILE_NOT_FOUND);
 686       goto cleanup;
 687     }
 688 
 689   if (canonicalize_path (search_path, &canonical) != 0)
 690     goto cleanup;
 691 
 692   if (argzize_path (canonical, &argz, &argz_len) != 0)
 693     goto cleanup;
 694 
 695   {
 696     char *dir_name = 0;
 697     while ((dir_name = argz_next (argz, argz_len, dir_name)))
 698       {
 699         size_t lendir = LT_STRLEN (dir_name);
 700 
 701         if (1+ lendir + lenbase >= filenamesize)
 702         {
 703           FREE (filename);
 704           filenamesize  = 1+ lendir + 1+ lenbase; /* "/d" + '/' + "f" + '\0' */
 705           filename      = MALLOC (char, filenamesize);
 706           if (!filename)
 707             goto cleanup;
 708         }
 709 
 710         assert (filenamesize > lendir);
 711         strcpy (filename, dir_name);
 712 
 713         if (base_name && *base_name)
 714           {
 715             if (filename[lendir -1] != '/')
 716               filename[lendir++] = '/';
 717             strcpy (filename +lendir, base_name);
 718           }
 719 
 720         if ((result = (*func) (filename, data1, data2)))
 721           {
 722             break;
 723           }
 724       }
 725   }
 726 
 727  cleanup:
 728   FREE (argz);
 729   FREE (canonical);
 730   FREE (filename);
 731 
 732   return result;
 733 }
 734 
 735 /* If FILEPATH can be opened, store the name of the directory component
 736    in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
 737    DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
 738 static int
 739 find_file_callback (char *filename, void *data1, void *data2)
 740 {
 741   char       **pdir     = (char **) data1;
 742   FILE       **pfile    = (FILE **) data2;
 743   int        is_done    = 0;
 744 
 745   assert (filename && *filename);
 746   assert (pdir);
 747   assert (pfile);
 748 
 749   if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
 750     {
 751       char *dirend = strrchr (filename, '/');
 752 
 753       if (dirend > filename)
 754         *dirend   = LT_EOS_CHAR;
 755 
 756       FREE (*pdir);
 757       *pdir   = lt__strdup (filename);
 758       is_done = (*pdir == 0) ? -1 : 1;
 759     }
 760 
 761   return is_done;
 762 }
 763 
 764 static FILE *
 765 find_file (const char *search_path, const char *base_name, char **pdir)
 766 {
 767   FILE *file = 0;
 768 
 769   foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
 770 
 771   return file;
 772 }
 773 
 774 static int
 775 find_handle_callback (char *filename, void *data, void *data2)
 776 {
 777   lt_dlhandle  *phandle         = (lt_dlhandle *) data;
 778   int           notfound        = access (filename, R_OK);
 779   lt_dladvise   advise          = (lt_dladvise) data2;
 780 
 781   /* Bail out if file cannot be read...  */
 782   if (notfound)
 783     return 0;
 784 
 785   /* Try to dlopen the file, but do not continue searching in any
 786      case.  */
 787   if (tryall_dlopen (phandle, filename, advise, 0) != 0)
 788     *phandle = 0;
 789 
 790   return 1;
 791 }
 792 
 793 /* If HANDLE was found return it, otherwise return 0.  If HANDLE was
 794    found but could not be opened, *HANDLE will be set to 0.  */
 795 static lt_dlhandle *
 796 find_handle (const char *search_path, const char *base_name,
 797              lt_dlhandle *phandle, lt_dladvise advise)
 798 {
 799   if (!search_path)
 800     return 0;
 801 
 802   if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
 803                           phandle, advise))
 804     return 0;
 805 
 806   return phandle;
 807 }
 808 
 809 #if !defined(LTDL_DLOPEN_DEPLIBS)
 810 static int
 811 load_deplibs (lt_dlhandle handle, char * LT__UNUSED deplibs)
 812 {
 813   handle->depcount = 0;
 814   return 0;
 815 }
 816 
 817 #else /* defined(LTDL_DLOPEN_DEPLIBS) */
 818 static int
 819 load_deplibs (lt_dlhandle handle, char *deplibs)
 820 {
 821   char  *p, *save_search_path = 0;
 822   int   depcount = 0;
 823   int   i;
 824   char  **names = 0;
 825   int   errors = 0;
 826 
 827   handle->depcount = 0;
 828 
 829   if (!deplibs)
 830     {
 831       return errors;
 832     }
 833   ++errors;
 834 
 835   if (user_search_path)
 836     {
 837       save_search_path = lt__strdup (user_search_path);
 838       if (!save_search_path)
 839         goto cleanup;
 840     }
 841 
 842   /* extract search paths and count deplibs */
 843   p = deplibs;
 844   while (*p)
 845     {
 846       if (!isspace ((unsigned char) *p))
 847         {
 848           char *end = p+1;
 849           while (*end && !isspace((unsigned char) *end))
 850             {
 851               ++end;
 852             }
 853 
 854           if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
 855             {
 856               char save = *end;
 857               *end = 0; /* set a temporary string terminator */
 858               if (lt_dladdsearchdir(p+2))
 859                 {
 860                   goto cleanup;
 861                 }
 862               *end = save;
 863             }
 864           else
 865             {
 866               ++depcount;
 867             }
 868 
 869           p = end;
 870         }
 871       else
 872         {
 873           ++p;
 874         }
 875     }
 876 
 877 
 878   if (!depcount)
 879     {
 880       errors = 0;
 881       goto cleanup;
 882     }
 883 
 884   names = MALLOC (char *, depcount);
 885   if (!names)
 886     goto cleanup;
 887 
 888   /* now only extract the actual deplibs */
 889   depcount = 0;
 890   p = deplibs;
 891   while (*p)
 892     {
 893       if (isspace ((unsigned char) *p))
 894         {
 895           ++p;
 896         }
 897       else
 898         {
 899           char *end = p+1;
 900           while (*end && !isspace ((unsigned char) *end))
 901             {
 902               ++end;
 903             }
 904 
 905           if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
 906             {
 907               char *name;
 908               char save = *end;
 909               *end = 0; /* set a temporary string terminator */
 910               if (strncmp(p, "-l", 2) == 0)
 911                 {
 912                   size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
 913                   name = MALLOC (char, 1+ name_len);
 914                   if (name)
 915                     sprintf (name, "lib%s", p+2);
 916                 }
 917               else
 918                 name = lt__strdup(p);
 919 
 920               if (!name)
 921                 goto cleanup_names;
 922 
 923               names[depcount++] = name;
 924               *end = save;
 925             }
 926           p = end;
 927         }
 928     }
 929 
 930   /* load the deplibs (in reverse order)
 931      At this stage, don't worry if the deplibs do not load correctly,
 932      they may already be statically linked into the loading application
 933      for instance.  There will be a more enlightening error message
 934      later on if the loaded module cannot resolve all of its symbols.  */
 935   if (depcount)
 936     {
 937       lt_dlhandle cur = handle;
 938       int       j = 0;
 939 
 940       cur->deplibs = MALLOC (lt_dlhandle, depcount);
 941       if (!cur->deplibs)
 942         goto cleanup_names;
 943 
 944       for (i = 0; i < depcount; ++i)
 945         {
 946           cur->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
 947           if (cur->deplibs[j])
 948             {
 949               ++j;
 950             }
 951         }
 952 
 953       cur->depcount     = j;    /* Number of successfully loaded deplibs */
 954       errors            = 0;
 955     }
 956 
 957  cleanup_names:
 958   for (i = 0; i < depcount; ++i)
 959     {
 960       FREE (names[i]);
 961     }
 962 
 963  cleanup:
 964   FREE (names);
 965   /* restore the old search path */
 966   if (save_search_path) {
 967     MEMREASSIGN (user_search_path, save_search_path);
 968   }
 969 
 970   return errors;
 971 }
 972 #endif /* defined(LTDL_DLOPEN_DEPLIBS) */
 973 
 974 static int
 975 unload_deplibs (lt_dlhandle handle)
 976 {
 977   int i;
 978   int errors = 0;
 979   lt_dlhandle cur = handle;
 980 
 981   if (cur->depcount)
 982     {
 983       for (i = 0; i < cur->depcount; ++i)
 984         {
 985           if (!LT_DLIS_RESIDENT (cur->deplibs[i]))
 986             {
 987               errors += lt_dlclose (cur->deplibs[i]);
 988             }
 989         }
 990       FREE (cur->deplibs);
 991     }
 992 
 993   return errors;
 994 }
 995 
 996 static int
 997 trim (char **dest, const char *str)
 998 {
 999   /* remove the leading and trailing "'" from str
1000      and store the result in dest */
1001   const char *end   = strrchr (str, '\'');
1002   size_t len        = LT_STRLEN (str);
1003   char *tmp;
1004 
1005   FREE (*dest);
1006 
1007   if (!end || end == str)
1008     return 1;
1009 
1010   if (len > 3 && str[0] == '\'')
1011     {
1012       tmp = MALLOC (char, end - str);
1013       if (!tmp)
1014         return 1;
1015 
1016       memcpy(tmp, &str[1], (end - str) - 1);
1017       tmp[(end - str) - 1] = LT_EOS_CHAR;
1018       *dest = tmp;
1019     }
1020   else
1021     {
1022       *dest = 0;
1023     }
1024 
1025   return 0;
1026 }
1027 
1028 /* Read the .la file FILE. */
1029 static int
1030 parse_dotla_file(FILE *file, char **dlname, char **libdir, char **deplibs,
1031     char **old_name, int *installed)
1032 {
1033   int           errors = 0;
1034   size_t        line_len = LT_FILENAME_MAX;
1035   char *        line = MALLOC (char, line_len);
1036 
1037   if (!line)
1038     {
1039       LT__SETERROR (FILE_NOT_FOUND);
1040       return 1;
1041     }
1042 
1043   while (!feof (file))
1044     {
1045       line[line_len-2] = '\0';
1046       if (!fgets (line, (int) line_len, file))
1047         {
1048           break;
1049         }
1050 
1051       /* Handle the case where we occasionally need to read a line
1052          that is longer than the initial buffer size.
1053          Behave even if the file contains NUL bytes due to corruption. */
1054       while (line[line_len-2] != '\0' && line[line_len-2] != '\n' && !feof (file))
1055         {
1056           line = REALLOC (char, line, line_len *2);
1057           if (!line)
1058             {
1059               ++errors;
1060               goto cleanup;
1061             }
1062           line[line_len * 2 - 2] = '\0';
1063           if (!fgets (&line[line_len -1], (int) line_len +1, file))
1064             {
1065               break;
1066             }
1067           line_len *= 2;
1068         }
1069 
1070       if (line[0] == '\n' || line[0] == '#')
1071         {
1072           continue;
1073         }
1074 
1075 #undef  STR_DLNAME
1076 #define STR_DLNAME      "dlname="
1077       if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
1078         {
1079           errors += trim (dlname, &line[sizeof (STR_DLNAME) - 1]);
1080         }
1081 
1082 #undef  STR_OLD_LIBRARY
1083 #define STR_OLD_LIBRARY "old_library="
1084       else if (strncmp (line, STR_OLD_LIBRARY,
1085             sizeof (STR_OLD_LIBRARY) - 1) == 0)
1086         {
1087           errors += trim (old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
1088         }
1089 
1090       /* Windows native tools do not understand the POSIX paths we store
1091          in libdir. */
1092 #undef  STR_LIBDIR
1093 #define STR_LIBDIR      "libdir="
1094       else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
1095         {
1096           errors += trim (libdir, &line[sizeof(STR_LIBDIR) - 1]);
1097 #ifdef __WINDOWS__
1098           /* Disallow following unix-style paths on MinGW.  */
1099           if (*libdir && (**libdir == '/' || **libdir == '\\'))
1100             **libdir = '\0';
1101 #endif
1102         }
1103 
1104 #undef  STR_DL_DEPLIBS
1105 #define STR_DL_DEPLIBS  "dependency_libs="
1106       else if (strncmp (line, STR_DL_DEPLIBS,
1107             sizeof (STR_DL_DEPLIBS) - 1) == 0)
1108         {
1109           errors += trim (deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
1110         }
1111       else if (streq (line, "installed=yes\n"))
1112         {
1113           *installed = 1;
1114         }
1115       else if (streq (line, "installed=no\n"))
1116         {
1117           *installed = 0;
1118         }
1119 
1120 #undef  STR_LIBRARY_NAMES
1121 #define STR_LIBRARY_NAMES "library_names="
1122       else if (!*dlname && strncmp (line, STR_LIBRARY_NAMES,
1123             sizeof (STR_LIBRARY_NAMES) - 1) == 0)
1124         {
1125           char *last_libname;
1126           errors += trim (dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
1127           if (!errors
1128               && *dlname
1129               && (last_libname = strrchr (*dlname, ' ')) != 0)
1130             {
1131               last_libname = lt__strdup (last_libname + 1);
1132               if (!last_libname)
1133                 {
1134                   ++errors;
1135                   goto cleanup;
1136                 }
1137               MEMREASSIGN (*dlname, last_libname);
1138             }
1139         }
1140 
1141       if (errors)
1142         break;
1143     }
1144 cleanup:
1145   FREE (line);
1146   return errors;
1147 }
1148 
1149 
1150 /* Try to open FILENAME as a module. */
1151 static int
1152 try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
1153             lt_dladvise advise)
1154 {
1155   const char *  saved_error     = 0;
1156   char *        archive_name    = 0;
1157   char *        canonical       = 0;
1158   char *        base_name       = 0;
1159   char *        dir             = 0;
1160   char *        name            = 0;
1161   char *        attempt         = 0;
1162   int           errors          = 0;
1163   lt_dlhandle   newhandle;
1164 
1165   assert (phandle);
1166   assert (*phandle == 0);
1167 
1168 #ifdef LT_DEBUG_LOADERS
1169   fprintf (stderr, "try_dlopen (%s, %s)\n",
1170            filename ? filename : "(null)",
1171            ext ? ext : "(null)");
1172 #endif
1173 
1174   LT__GETERROR (saved_error);
1175 
1176   /* dlopen self? */
1177   if (!filename)
1178     {
1179       *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1180       if (*phandle == 0)
1181         return 1;
1182 
1183       newhandle = *phandle;
1184 
1185       /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
1186       newhandle->info.is_resident = 1;
1187 
1188       if (tryall_dlopen (&newhandle, 0, advise, 0) != 0)
1189         {
1190           FREE (*phandle);
1191           return 1;
1192         }
1193 
1194       goto register_handle;
1195     }
1196 
1197   assert (filename && *filename);
1198 
1199   if (ext)
1200     {
1201       attempt = MALLOC (char, LT_STRLEN (filename) + LT_STRLEN (ext) + 1);
1202       if (!attempt)
1203         return 1;
1204 
1205       sprintf(attempt, "%s%s", filename, ext);
1206     }
1207   else
1208     {
1209       attempt = lt__strdup (filename);
1210       if (!attempt)
1211         return 1;
1212     }
1213 
1214   /* Doing this immediately allows internal functions to safely
1215      assume only canonicalized paths are passed.  */
1216   if (canonicalize_path (attempt, &canonical) != 0)
1217     {
1218       ++errors;
1219       goto cleanup;
1220     }
1221 
1222   /* If the canonical module name is a path (relative or absolute)
1223      then split it into a directory part and a name part.  */
1224   base_name = strrchr (canonical, '/');
1225   if (base_name)
1226     {
1227       size_t dirlen = (1+ base_name) - canonical;
1228 
1229       dir = MALLOC (char, 1+ dirlen);
1230       if (!dir)
1231         {
1232           ++errors;
1233           goto cleanup;
1234         }
1235 
1236       strncpy (dir, canonical, dirlen);
1237       dir[dirlen] = LT_EOS_CHAR;
1238 
1239       ++base_name;
1240     }
1241   else
1242     MEMREASSIGN (base_name, canonical);
1243 
1244   assert (base_name && *base_name);
1245 
1246   ext = strrchr (base_name, '.');
1247   if (!ext)
1248     {
1249       ext = base_name + LT_STRLEN (base_name);
1250     }
1251 
1252   /* extract the module name from the file name */
1253   name = MALLOC (char, ext - base_name + 1);
1254   if (!name)
1255     {
1256       ++errors;
1257       goto cleanup;
1258     }
1259 
1260   /* canonicalize the module name */
1261   {
1262     int i;
1263     for (i = 0; i < ext - base_name; ++i)
1264       {
1265         if (isalnum ((unsigned char)(base_name[i])))
1266           {
1267             name[i] = base_name[i];
1268           }
1269         else
1270           {
1271             name[i] = '_';
1272           }
1273       }
1274     name[ext - base_name] = LT_EOS_CHAR;
1275   }
1276 
1277   /* Before trawling through the filesystem in search of a module,
1278      check whether we are opening a preloaded module.  */
1279   if (!dir)
1280     {
1281       const lt_dlvtable *vtable = lt_dlloader_find ("lt_preopen");
1282 
1283       if (vtable)
1284         {
1285           /* libprefix + name + "." + libext + NULL */
1286           archive_name = MALLOC (char, strlen (libprefix) + LT_STRLEN (name) + strlen (libext) + 2);
1287           *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1288 
1289           if ((*phandle == NULL) || (archive_name == NULL))
1290             {
1291               ++errors;
1292               goto cleanup;
1293             }
1294           newhandle = *phandle;
1295 
1296           /* Preloaded modules are always named according to their old
1297              archive name.  */
1298           if (strncmp(name, "lib", 3) == 0)
1299             {
1300               sprintf (archive_name, "%s%s.%s", libprefix, name + 3, libext);
1301             }
1302           else
1303             {
1304               sprintf (archive_name, "%s.%s", name, libext);
1305             }
1306 
1307           if (tryall_dlopen (&newhandle, archive_name, advise, vtable) == 0)
1308             {
1309               goto register_handle;
1310             }
1311 
1312           /* If we're still here, there was no matching preloaded module,
1313              so put things back as we found them, and continue searching.  */
1314           FREE (*phandle);
1315           newhandle = NULL;
1316         }
1317     }
1318 
1319   /* If we are allowing only preloaded modules, and we didn't find
1320      anything yet, give up on the search here.  */
1321   if (advise && advise->try_preload_only)
1322     {
1323       goto cleanup;
1324     }
1325 
1326   /* Check whether we are opening a libtool module (.la extension).  */
1327   if (ext && streq (ext, archive_ext))
1328     {
1329       /* this seems to be a libtool module */
1330       FILE *    file     = 0;
1331       char *    dlname   = 0;
1332       char *    old_name = 0;
1333       char *    libdir   = 0;
1334       char *    deplibs  = 0;
1335 
1336       /* if we can't find the installed flag, it is probably an
1337          installed libtool archive, produced with an old version
1338          of libtool */
1339       int       installed = 1;
1340 
1341       /* Now try to open the .la file.  If there is no directory name
1342          component, try to find it first in user_search_path and then other
1343          prescribed paths.  Otherwise (or in any case if the module was not
1344          yet found) try opening just the module name as passed.  */
1345       if (!dir)
1346         {
1347           const char *search_path = user_search_path;
1348 
1349           if (search_path)
1350             file = find_file (user_search_path, base_name, &dir);
1351 
1352           if (!file)
1353             {
1354               search_path = getenv (LTDL_SEARCHPATH_VAR);
1355               if (search_path)
1356                 file = find_file (search_path, base_name, &dir);
1357             }
1358 
1359 #if defined(LT_MODULE_PATH_VAR)
1360           if (!file)
1361             {
1362               search_path = getenv (LT_MODULE_PATH_VAR);
1363               if (search_path)
1364                 file = find_file (search_path, base_name, &dir);
1365             }
1366 #endif
1367 #if defined(LT_DLSEARCH_PATH)
1368           if (!file && *sys_dlsearch_path)
1369             {
1370               file = find_file (sys_dlsearch_path, base_name, &dir);
1371             }
1372 #endif
1373         }
1374       else
1375         {
1376           file = fopen (attempt, LT_READTEXT_MODE);
1377         }
1378 
1379       /* If we didn't find the file by now, it really isn't there.  Set
1380          the status flag, and bail out.  */
1381       if (!file)
1382         {
1383           LT__SETERROR (FILE_NOT_FOUND);
1384           ++errors;
1385           goto cleanup;
1386         }
1387 
1388       /* read the .la file */
1389       if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
1390             &old_name, &installed) != 0)
1391         ++errors;
1392 
1393       fclose (file);
1394 
1395       /* allocate the handle */
1396       *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1397       if (*phandle == 0)
1398         ++errors;
1399 
1400       if (errors)
1401         {
1402           FREE (dlname);
1403           FREE (old_name);
1404           FREE (libdir);
1405           FREE (deplibs);
1406           FREE (*phandle);
1407           goto cleanup;
1408         }
1409 
1410       assert (*phandle);
1411 
1412       if (load_deplibs (*phandle, deplibs) == 0)
1413         {
1414           newhandle = *phandle;
1415           /* find_module may replace newhandle */
1416           if (find_module (&newhandle, dir, libdir, dlname, old_name,
1417                            installed, advise))
1418             {
1419               unload_deplibs (*phandle);
1420               ++errors;
1421             }
1422         }
1423       else
1424         {
1425           ++errors;
1426         }
1427 
1428       FREE (dlname);
1429       FREE (old_name);
1430       FREE (libdir);
1431       FREE (deplibs);
1432 
1433       if (errors)
1434         {
1435           FREE (*phandle);
1436           goto cleanup;
1437         }
1438 
1439       if (*phandle != newhandle)
1440         {
1441           unload_deplibs (*phandle);
1442         }
1443     }
1444   else
1445     {
1446       /* not a libtool module */
1447       *phandle = (lt_dlhandle) lt__zalloc (sizeof (struct lt__handle));
1448       if (*phandle == 0)
1449         {
1450           ++errors;
1451           goto cleanup;
1452         }
1453 
1454       newhandle = *phandle;
1455 
1456       /* If the module has no directory name component, try to find it
1457          first in user_search_path and then other prescribed paths.
1458          Otherwise (or in any case if the module was not yet found) try
1459          opening just the module name as passed.  */
1460       if ((dir || (!find_handle (user_search_path, base_name,
1461                                  &newhandle, advise)
1462                    && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
1463                                     &newhandle, advise)
1464 #if defined(LT_MODULE_PATH_VAR)
1465                    && !find_handle (getenv (LT_MODULE_PATH_VAR), base_name,
1466                                     &newhandle, advise)
1467 #endif
1468 #if defined(LT_DLSEARCH_PATH)
1469                    && !find_handle (sys_dlsearch_path, base_name,
1470                                     &newhandle, advise)
1471 #endif
1472                    )))
1473         {
1474           if (tryall_dlopen (&newhandle, attempt, advise, 0) != 0)
1475             {
1476               newhandle = NULL;
1477             }
1478         }
1479 
1480       if (!newhandle)
1481         {
1482           FREE (*phandle);
1483           ++errors;
1484           goto cleanup;
1485         }
1486     }
1487 
1488  register_handle:
1489   MEMREASSIGN (*phandle, newhandle);
1490 
1491   if ((*phandle)->info.ref_count == 0)
1492     {
1493       (*phandle)->info.ref_count        = 1;
1494       MEMREASSIGN ((*phandle)->info.name, name);
1495 
1496       (*phandle)->next  = handles;
1497       handles           = *phandle;
1498     }
1499 
1500   LT__SETERRORSTR (saved_error);
1501 
1502  cleanup:
1503   FREE (dir);
1504   FREE (attempt);
1505   FREE (name);
1506   if (!canonical)               /* was MEMREASSIGNed */
1507     FREE (base_name);
1508   FREE (canonical);
1509   FREE (archive_name);
1510 
1511   return errors;
1512 }
1513 
1514 
1515 /* If the last error message stored was `FILE_NOT_FOUND', then return
1516    non-zero.  */
1517 static int
1518 file_not_found (void)
1519 {
1520   const char *error = 0;
1521 
1522   LT__GETERROR (error);
1523   if (error == LT__STRERROR (FILE_NOT_FOUND))
1524     return 1;
1525 
1526   return 0;
1527 }
1528 
1529 
1530 /* Unless FILENAME already bears a suitable library extension, then
1531    return 0.  */
1532 static int
1533 has_library_ext (const char *filename)
1534 {
1535   const char *  ext     = 0;
1536 
1537   assert (filename);
1538 
1539   ext = strrchr (filename, '.');
1540 
1541   if (ext && ((streq (ext, archive_ext))
1542 #if defined(LT_MODULE_EXT)
1543              || (streq (ext, shlib_ext))
1544 #endif
1545 #if defined(LT_SHARED_EXT)
1546              || (streq (ext, shared_ext))
1547 #endif
1548     ))
1549     {
1550       return 1;
1551     }
1552 
1553   return 0;
1554 }
1555 
1556 
1557 /* Initialise and configure a user lt_dladvise opaque object.  */
1558 
1559 int
1560 lt_dladvise_init (lt_dladvise *padvise)
1561 {
1562   lt_dladvise advise = (lt_dladvise) lt__zalloc (sizeof (struct lt__advise));
1563   *padvise = advise;
1564   return (advise ? 0 : 1);
1565 }
1566 
1567 int
1568 lt_dladvise_destroy (lt_dladvise *padvise)
1569 {
1570   if (padvise)
1571     FREE(*padvise);
1572   return 0;
1573 }
1574 
1575 int
1576 lt_dladvise_ext (lt_dladvise *padvise)
1577 {
1578   assert (padvise && *padvise);
1579   (*padvise)->try_ext = 1;
1580   return 0;
1581 }
1582 
1583 int
1584 lt_dladvise_resident (lt_dladvise *padvise)
1585 {
1586   assert (padvise && *padvise);
1587   (*padvise)->is_resident = 1;
1588   return 0;
1589 }
1590 
1591 int
1592 lt_dladvise_local (lt_dladvise *padvise)
1593 {
1594   assert (padvise && *padvise);
1595   (*padvise)->is_symlocal = 1;
1596   return 0;
1597 }
1598 
1599 int
1600 lt_dladvise_global (lt_dladvise *padvise)
1601 {
1602   assert (padvise && *padvise);
1603   (*padvise)->is_symglobal = 1;
1604   return 0;
1605 }
1606 
1607 int
1608 lt_dladvise_preload (lt_dladvise *padvise)
1609 {
1610   assert (padvise && *padvise);
1611   (*padvise)->try_preload_only = 1;
1612   return 0;
1613 }
1614 
1615 /* Libtool-1.5.x interface for loading a new module named FILENAME.  */
1616 lt_dlhandle
1617 lt_dlopen (const char *filename)
1618 {
1619   return lt_dlopenadvise (filename, NULL);
1620 }
1621 
1622 
1623 /* If FILENAME has an ARCHIVE_EXT or MODULE_EXT extension, try to
1624    open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
1625    and if a file is still not found try again with MODULE_EXT appended
1626    instead.  */
1627 lt_dlhandle
1628 lt_dlopenext (const char *filename)
1629 {
1630   lt_dlhandle   handle  = 0;
1631   lt_dladvise   advise;
1632 
1633   if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise))
1634     handle = lt_dlopenadvise (filename, advise);
1635 
1636   lt_dladvise_destroy (&advise);
1637   return handle;
1638 }
1639 
1640 
1641 lt_dlhandle
1642 lt_dlopenadvise (const char *filename, lt_dladvise advise)
1643 {
1644   lt_dlhandle   handle  = 0;
1645   int           errors  = 0;
1646   const char *  saved_error     = 0;
1647 
1648   LT__GETERROR (saved_error);
1649 
1650   /* Can't have symbols hidden and visible at the same time!  */
1651   if (advise && advise->is_symlocal && advise->is_symglobal)
1652     {
1653       LT__SETERROR (CONFLICTING_FLAGS);
1654       return 0;
1655     }
1656 
1657   if (!filename
1658       || !advise
1659       || !advise->try_ext
1660       || has_library_ext (filename))
1661     {
1662       /* Just incase we missed a code path in try_dlopen() that reports
1663          an error, but forgot to reset handle... */
1664       if (try_dlopen (&handle, filename, NULL, advise) != 0)
1665         return 0;
1666 
1667       return handle;
1668     }
1669   else if (filename && *filename)
1670     {
1671 
1672       /* First try appending ARCHIVE_EXT.  */
1673       errors += try_dlopen (&handle, filename, archive_ext, advise);
1674 
1675       /* If we found FILENAME, stop searching -- whether we were able to
1676          load the file as a module or not.  If the file exists but loading
1677          failed, it is better to return an error message here than to
1678          report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
1679          in the module search path.  */
1680       if (handle || ((errors > 0) && !file_not_found ()))
1681         return handle;
1682 
1683 #if defined(LT_MODULE_EXT)
1684       /* Try appending SHLIB_EXT.   */
1685       LT__SETERRORSTR (saved_error);
1686       errors = try_dlopen (&handle, filename, shlib_ext, advise);
1687 
1688       /* As before, if the file was found but loading failed, return now
1689          with the current error message.  */
1690       if (handle || ((errors > 0) && !file_not_found ()))
1691         return handle;
1692 #endif
1693 
1694 #if defined(LT_SHARED_EXT)
1695       /* Try appending SHARED_EXT.   */
1696       LT__SETERRORSTR (saved_error);
1697       errors = try_dlopen (&handle, filename, shared_ext, advise);
1698 
1699       /* As before, if the file was found but loading failed, return now
1700          with the current error message.  */
1701       if (handle || ((errors > 0) && !file_not_found ()))
1702         return handle;
1703 #endif
1704     }
1705 
1706   /* Still here?  Then we really did fail to locate any of the file
1707      names we tried.  */
1708   LT__SETERROR (FILE_NOT_FOUND);
1709   return 0;
1710 }
1711 
1712 
1713 static int
1714 lt_argz_insert (char **pargz, size_t *pargz_len, char *before,
1715                 const char *entry)
1716 {
1717   error_t error;
1718 
1719   /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
1720      pargz_len, NULL, entry) failed with EINVAL.  */
1721   if (before)
1722     error = argz_insert (pargz, pargz_len, before, entry);
1723   else
1724     error = argz_append (pargz, pargz_len, entry, 1 + strlen (entry));
1725 
1726   if (error)
1727     {
1728       switch (error)
1729         {
1730         case ENOMEM:
1731           LT__SETERROR (NO_MEMORY);
1732           break;
1733         default:
1734           LT__SETERROR (UNKNOWN);
1735           break;
1736         }
1737       return 1;
1738     }
1739 
1740   return 0;
1741 }
1742 
1743 static int
1744 lt_argz_insertinorder (char **pargz, size_t *pargz_len, const char *entry)
1745 {
1746   char *before = 0;
1747 
1748   assert (pargz);
1749   assert (pargz_len);
1750   assert (entry && *entry);
1751 
1752   if (*pargz)
1753     while ((before = argz_next (*pargz, *pargz_len, before)))
1754       {
1755         int cmp = strcmp (entry, before);
1756 
1757         if (cmp < 0)  break;
1758         if (cmp == 0) return 0; /* No duplicates! */
1759       }
1760 
1761   return lt_argz_insert (pargz, pargz_len, before, entry);
1762 }
1763 
1764 static int
1765 lt_argz_insertdir (char **pargz, size_t *pargz_len, const char *dirnam,
1766                    struct dirent *dp)
1767 {
1768   char   *buf       = 0;
1769   size_t buf_len    = 0;
1770   char   *end       = 0;
1771   size_t end_offset = 0;
1772   size_t dir_len    = 0;
1773   int    errors     = 0;
1774 
1775   assert (pargz);
1776   assert (pargz_len);
1777   assert (dp);
1778 
1779   dir_len = LT_STRLEN (dirnam);
1780   end     = dp->d_name + D_NAMLEN(dp);
1781 
1782   /* Ignore version numbers.  */
1783   {
1784     char *p;
1785     for (p = end; p -1 > dp->d_name; --p)
1786       if (strchr (".0123456789", p[-1]) == 0)
1787         break;
1788 
1789     if (*p == '.')
1790       end = p;
1791   }
1792 
1793   /* Ignore filename extension.  */
1794   {
1795     char *p;
1796     for (p = end -1; p > dp->d_name; --p)
1797       if (*p == '.')
1798         {
1799           end = p;
1800           break;
1801         }
1802   }
1803 
1804   /* Prepend the directory name.  */
1805   end_offset    = end - dp->d_name;
1806   buf_len       = dir_len + 1+ end_offset;
1807   buf           = MALLOC (char, 1+ buf_len);
1808   if (!buf)
1809     return ++errors;
1810 
1811   assert (buf);
1812 
1813   strcpy  (buf, dirnam);
1814   strcat  (buf, "/");
1815   strncat (buf, dp->d_name, end_offset);
1816   buf[buf_len] = LT_EOS_CHAR;
1817 
1818   /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
1819   if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
1820     ++errors;
1821 
1822   FREE (buf);
1823 
1824   return errors;
1825 }
1826 
1827 static int
1828 list_files_by_dir (const char *dirnam, char **pargz, size_t *pargz_len)
1829 {
1830   DIR   *dirp     = 0;
1831   int    errors   = 0;
1832 
1833   assert (dirnam && *dirnam);
1834   assert (pargz);
1835   assert (pargz_len);
1836   assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
1837 
1838   dirp = opendir (dirnam);
1839   if (dirp)
1840     {
1841       struct dirent *dp = 0;
1842 
1843       while ((dp = readdir (dirp)))
1844         if (dp->d_name[0] != '.')
1845           if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
1846             {
1847               ++errors;
1848               break;
1849             }
1850 
1851       closedir (dirp);
1852     }
1853   else
1854     ++errors;
1855 
1856   return errors;
1857 }
1858 
1859 
1860 /* If there are any files in DIRNAME, call the function passed in
1861    DATA1 (with the name of each file and DATA2 as arguments).  */
1862 static int
1863 foreachfile_callback (char *dirname, void *data1, void *data2)
1864 {
1865   file_worker_func *func = *(file_worker_func **) data1;
1866 
1867   int     is_done  = 0;
1868   char   *argz     = 0;
1869   size_t  argz_len = 0;
1870 
1871   if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
1872     goto cleanup;
1873   if (!argz)
1874     goto cleanup;
1875 
1876   {
1877     char *filename = 0;
1878     while ((filename = argz_next (argz, argz_len, filename)))
1879       if ((is_done = (*func) (filename, data2)))
1880         break;
1881   }
1882 
1883  cleanup:
1884   FREE (argz);
1885 
1886   return is_done;
1887 }
1888 
1889 
1890 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
1891    with DATA.  The filenames passed to FUNC would be suitable for
1892    passing to lt_dlopenext.  The extensions are stripped so that
1893    individual modules do not generate several entries (e.g. libfoo.la,
1894    libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
1895    then the same directories that lt_dlopen would search are examined.  */
1896 int
1897 lt_dlforeachfile (const char *search_path,
1898                   int (*func) (const char *filename, void *data),
1899                   void *data)
1900 {
1901   int is_done = 0;
1902   file_worker_func **fpptr = &func;
1903 
1904   if (search_path)
1905     {
1906       /* If a specific path was passed, search only the directories
1907          listed in it.  */
1908       is_done = foreach_dirinpath (search_path, 0,
1909                                    foreachfile_callback, fpptr, data);
1910     }
1911   else
1912     {
1913       /* Otherwise search the default paths.  */
1914       is_done = foreach_dirinpath (user_search_path, 0,
1915                                    foreachfile_callback, fpptr, data);
1916       if (!is_done)
1917         {
1918           is_done = foreach_dirinpath (getenv(LTDL_SEARCHPATH_VAR), 0,
1919                                        foreachfile_callback, fpptr, data);
1920         }
1921 
1922 #if defined(LT_MODULE_PATH_VAR)
1923       if (!is_done)
1924         {
1925           is_done = foreach_dirinpath (getenv(LT_MODULE_PATH_VAR), 0,
1926                                        foreachfile_callback, fpptr, data);
1927         }
1928 #endif
1929 #if defined(LT_DLSEARCH_PATH)
1930       if (!is_done && *sys_dlsearch_path)
1931         {
1932           is_done = foreach_dirinpath (sys_dlsearch_path, 0,
1933                                        foreachfile_callback, fpptr, data);
1934         }
1935 #endif
1936     }
1937 
1938   return is_done;
1939 }
1940 
1941 int
1942 lt_dlclose (lt_dlhandle handle)
1943 {
1944   lt_dlhandle cur, last;
1945   int errors = 0;
1946 
1947   /* check whether the handle is valid */
1948   last = cur = handles;
1949   while (cur && handle != cur)
1950     {
1951       last = cur;
1952       cur = cur->next;
1953     }
1954 
1955   if (!cur)
1956     {
1957       LT__SETERROR (INVALID_HANDLE);
1958       ++errors;
1959       goto done;
1960     }
1961 
1962   cur = handle;
1963   cur->info.ref_count--;
1964 
1965   /* Note that even with resident modules, we must track the ref_count
1966      correctly incase the user decides to reset the residency flag
1967      later (even though the API makes no provision for that at the
1968      moment).  */
1969   if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur))
1970     {
1971       lt_user_data data = cur->vtable->dlloader_data;
1972 
1973       if (cur != handles)
1974         {
1975           last->next = cur->next;
1976         }
1977       else
1978         {
1979           handles = cur->next;
1980         }
1981 
1982       errors += cur->vtable->module_close (data, cur->module);
1983       errors += unload_deplibs (handle);
1984 
1985       /* It is up to the callers to free the data itself.  */
1986       FREE (cur->interface_data);
1987 
1988       FREE (cur->info.filename);
1989       FREE (cur->info.name);
1990       FREE (cur);
1991 
1992       goto done;
1993     }
1994 
1995   if (LT_DLIS_RESIDENT (handle))
1996     {
1997       LT__SETERROR (CLOSE_RESIDENT_MODULE);
1998       ++errors;
1999     }
2000 
2001  done:
2002   return errors;
2003 }
2004 
2005 void *
2006 lt_dlsym (lt_dlhandle place, const char *symbol)
2007 {
2008   size_t lensym;
2009   char  lsym[LT_SYMBOL_LENGTH];
2010   char  *sym;
2011   void *address;
2012   lt_user_data data;
2013   lt_dlhandle handle;
2014 
2015   if (!place)
2016     {
2017       LT__SETERROR (INVALID_HANDLE);
2018       return 0;
2019     }
2020 
2021   handle = place;
2022 
2023   if (!symbol)
2024     {
2025       LT__SETERROR (SYMBOL_NOT_FOUND);
2026       return 0;
2027     }
2028 
2029   lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
2030                                         + LT_STRLEN (handle->info.name);
2031 
2032   if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
2033     {
2034       sym = lsym;
2035     }
2036   else
2037     {
2038       sym = MALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
2039       if (!sym)
2040         {
2041           LT__SETERROR (BUFFER_OVERFLOW);
2042           return 0;
2043         }
2044     }
2045 
2046   data = handle->vtable->dlloader_data;
2047   if (handle->info.name)
2048     {
2049       const char *saved_error;
2050 
2051       LT__GETERROR (saved_error);
2052 
2053       /* this is a libtool module */
2054       if (handle->vtable->sym_prefix)
2055         {
2056           strcpy(sym, handle->vtable->sym_prefix);
2057           strcat(sym, handle->info.name);
2058         }
2059       else
2060         {
2061           strcpy(sym, handle->info.name);
2062         }
2063 
2064       strcat(sym, "_LTX_");
2065       strcat(sym, symbol);
2066 
2067       /* try "modulename_LTX_symbol" */
2068       address = handle->vtable->find_sym (data, handle->module, sym);
2069       if (address)
2070         {
2071           if (sym != lsym)
2072             {
2073               FREE (sym);
2074             }
2075           return address;
2076         }
2077       LT__SETERRORSTR (saved_error);
2078     }
2079 
2080   /* otherwise try "symbol" */
2081   if (handle->vtable->sym_prefix)
2082     {
2083       strcpy(sym, handle->vtable->sym_prefix);
2084       strcat(sym, symbol);
2085     }
2086   else
2087     {
2088       strcpy(sym, symbol);
2089     }
2090 
2091   address = handle->vtable->find_sym (data, handle->module, sym);
2092   if (sym != lsym)
2093     {
2094       FREE (sym);
2095     }
2096 
2097   return address;
2098 }
2099 
2100 const char *
2101 lt_dlerror (void)
2102 {
2103   const char *error;
2104 
2105   LT__GETERROR (error);
2106   LT__SETERRORSTR (0);
2107 
2108   return error;
2109 }
2110 
2111 static int
2112 lt_dlpath_insertdir (char **ppath, char *before, const char *dir)
2113 {
2114   int    errors         = 0;
2115   char  *canonical      = 0;
2116   char  *argz           = 0;
2117   size_t argz_len       = 0;
2118 
2119   assert (ppath);
2120   assert (dir && *dir);
2121 
2122   if (canonicalize_path (dir, &canonical) != 0)
2123     {
2124       ++errors;
2125       goto cleanup;
2126     }
2127 
2128   assert (canonical && *canonical);
2129 
2130   /* If *PPATH is empty, set it to DIR.  */
2131   if (*ppath == 0)
2132     {
2133       assert (!before);         /* BEFORE cannot be set without PPATH.  */
2134       assert (dir);             /* Without DIR, don't call this function!  */
2135 
2136       *ppath = lt__strdup (dir);
2137       if (*ppath == 0)
2138         ++errors;
2139 
2140       goto cleanup;
2141     }
2142 
2143   assert (ppath && *ppath);
2144 
2145   if (argzize_path (*ppath, &argz, &argz_len) != 0)
2146     {
2147       ++errors;
2148       goto cleanup;
2149     }
2150 
2151   /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
2152      if *PPATH is already canonicalized, and hence does not change length
2153      with respect to ARGZ.  We canonicalize each entry as it is added to
2154      the search path, and don't call this function with (uncanonicalized)
2155      user paths, so this is a fair assumption.  */
2156   if (before)
2157     {
2158       assert (*ppath <= before);
2159       assert ((int) (before - *ppath) <= (int) strlen (*ppath));
2160 
2161       before = before - *ppath + argz;
2162     }
2163 
2164   if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
2165     {
2166       ++errors;
2167       goto cleanup;
2168     }
2169 
2170   argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
2171   MEMREASSIGN(*ppath, argz);
2172 
2173  cleanup:
2174   FREE (argz);
2175   FREE (canonical);
2176 
2177   return errors;
2178 }
2179 
2180 int
2181 lt_dladdsearchdir (const char *search_dir)
2182 {
2183   int errors = 0;
2184 
2185   if (search_dir && *search_dir)
2186     {
2187       if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
2188         ++errors;
2189     }
2190 
2191   return errors;
2192 }
2193 
2194 int
2195 lt_dlinsertsearchdir (const char *before, const char *search_dir)
2196 {
2197   int errors = 0;
2198 
2199   if (before)
2200     {
2201       if ((before < user_search_path)
2202           || (before >= user_search_path + LT_STRLEN (user_search_path)))
2203         {
2204           LT__SETERROR (INVALID_POSITION);
2205           return 1;
2206         }
2207     }
2208 
2209   if (search_dir && *search_dir)
2210     {
2211       if (lt_dlpath_insertdir (&user_search_path,
2212                                (char *) before, search_dir) != 0)
2213         {
2214           ++errors;
2215         }
2216     }
2217 
2218   return errors;
2219 }
2220 
2221 int
2222 lt_dlsetsearchpath (const char *search_path)
2223 {
2224   int   errors      = 0;
2225 
2226   FREE (user_search_path);
2227 
2228   if (!search_path || !LT_STRLEN (search_path))
2229     {
2230       return errors;
2231     }
2232 
2233   if (canonicalize_path (search_path, &user_search_path) != 0)
2234     ++errors;
2235 
2236   return errors;
2237 }
2238 
2239 const char *
2240 lt_dlgetsearchpath (void)
2241 {
2242   const char *saved_path;
2243 
2244   saved_path = user_search_path;
2245 
2246   return saved_path;
2247 }
2248 
2249 int
2250 lt_dlmakeresident (lt_dlhandle handle)
2251 {
2252   int errors = 0;
2253 
2254   if (!handle)
2255     {
2256       LT__SETERROR (INVALID_HANDLE);
2257       ++errors;
2258     }
2259   else
2260     {
2261       handle->info.is_resident = 1;
2262     }
2263 
2264   return errors;
2265 }
2266 
2267 int
2268 lt_dlisresident (lt_dlhandle handle)
2269 {
2270   if (!handle)
2271     {
2272       LT__SETERROR (INVALID_HANDLE);
2273       return -1;
2274     }
2275 
2276   return LT_DLIS_RESIDENT (handle);
2277 }
2278 
2279 
2280 
2281 /* --- MODULE INFORMATION --- */
2282 
2283 typedef struct {
2284   const char *id_string;
2285   lt_dlhandle_interface *iface;
2286 } lt__interface_id;
2287 
2288 lt_dlinterface_id
2289 lt_dlinterface_register (const char *id_string, lt_dlhandle_interface *iface)
2290 {
2291   lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
2292 
2293   /* If lt__malloc fails, it will LT__SETERROR (NO_MEMORY), which
2294      can then be detected with lt_dlerror() if we return 0.  */
2295   if (interface_id)
2296     {
2297       interface_id->id_string = lt__strdup (id_string);
2298       if (!interface_id->id_string)
2299         FREE (interface_id);
2300       else
2301         interface_id->iface = iface;
2302     }
2303 
2304   return (lt_dlinterface_id) interface_id;
2305 }
2306 
2307 void lt_dlinterface_free (lt_dlinterface_id key)
2308 {
2309   lt__interface_id *interface_id = (lt__interface_id *)key;
2310   FREE (interface_id->id_string);
2311   FREE (interface_id);
2312 }
2313 
2314 void *
2315 lt_dlcaller_set_data (lt_dlinterface_id key, lt_dlhandle handle, void *data)
2316 {
2317   int n_elements = 0;
2318   void *stale = (void *) 0;
2319   lt_dlhandle cur = handle;
2320   int i;
2321 
2322   if (cur->interface_data)
2323     while (cur->interface_data[n_elements].key)
2324       ++n_elements;
2325 
2326   for (i = 0; i < n_elements; ++i)
2327     {
2328       if (cur->interface_data[i].key == key)
2329         {
2330           stale = cur->interface_data[i].data;
2331           break;
2332         }
2333     }
2334 
2335   /* Ensure that there is enough room in this handle's interface_data
2336      array to accept a new element (and an empty end marker).  */
2337   if (i == n_elements)
2338     {
2339       lt_interface_data *temp
2340         = REALLOC (lt_interface_data, cur->interface_data, 2+ n_elements);
2341 
2342       if (!temp)
2343         {
2344           stale = 0;
2345           goto done;
2346         }
2347 
2348       cur->interface_data = temp;
2349 
2350       /* We only need this if we needed to allocate a new interface_data.  */
2351       cur->interface_data[i].key        = key;
2352       cur->interface_data[1+ i].key     = 0;
2353     }
2354 
2355   cur->interface_data[i].data = data;
2356 
2357  done:
2358   return stale;
2359 }
2360 
2361 void *
2362 lt_dlcaller_get_data (lt_dlinterface_id key, lt_dlhandle handle)
2363 {
2364   void *result = (void *) 0;
2365   lt_dlhandle cur = handle;
2366 
2367   /* Locate the index of the element with a matching KEY.  */
2368   if (cur->interface_data)
2369     {
2370       int i;
2371       for (i = 0; cur->interface_data[i].key; ++i)
2372         {
2373           if (cur->interface_data[i].key == key)
2374             {
2375               result = cur->interface_data[i].data;
2376               break;
2377             }
2378         }
2379     }
2380 
2381   return result;
2382 }
2383 
2384 const lt_dlinfo *
2385 lt_dlgetinfo (lt_dlhandle handle)
2386 {
2387   if (!handle)
2388     {
2389       LT__SETERROR (INVALID_HANDLE);
2390       return 0;
2391     }
2392 
2393   return &(handle->info);
2394 }
2395 
2396 
2397 lt_dlhandle
2398 lt_dlhandle_iterate (lt_dlinterface_id iface, lt_dlhandle place)
2399 {
2400   lt_dlhandle handle = place;
2401   lt__interface_id *iterator = (lt__interface_id *) iface;
2402 
2403   assert (iface); /* iface is a required argument */
2404 
2405   if (!handle)
2406     handle = handles;
2407   else
2408     handle = handle->next;
2409 
2410   /* advance while the interface check fails */
2411   while (handle && iterator->iface
2412          && ((*iterator->iface) (handle, iterator->id_string) != 0))
2413     {
2414       handle = handle->next;
2415     }
2416 
2417   return handle;
2418 }
2419 
2420 
2421 lt_dlhandle
2422 lt_dlhandle_fetch (lt_dlinterface_id iface, const char *module_name)
2423 {
2424   lt_dlhandle handle = 0;
2425 
2426   assert (iface); /* iface is a required argument */
2427 
2428   while ((handle = lt_dlhandle_iterate (iface, handle)))
2429     {
2430       lt_dlhandle cur = handle;
2431       if (cur && cur->info.name && streq (cur->info.name, module_name))
2432         break;
2433     }
2434 
2435   return handle;
2436 }
2437 
2438 
2439 int
2440 lt_dlhandle_map (lt_dlinterface_id iface,
2441                  int (*func) (lt_dlhandle handle, void *data), void *data)
2442 {
2443   lt__interface_id *iterator = (lt__interface_id *) iface;
2444   lt_dlhandle cur = handles;
2445 
2446   assert (iface); /* iface is a required argument */
2447 
2448   while (cur)
2449     {
2450       int errorcode = 0;
2451 
2452       /* advance while the interface check fails */
2453       while (cur && iterator->iface
2454              && ((*iterator->iface) (cur, iterator->id_string) != 0))
2455         {
2456           cur = cur->next;
2457         }
2458 
2459       if ((errorcode = (*func) (cur, data)) != 0)
2460         return errorcode;
2461     }
2462 
2463   return 0;
2464 }

/* [previous][next][first][last][top][bottom][index][help] */