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

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