This source file includes following definitions.
- lt__alloc_die_callback
- loader_init_callback
- loader_init
- lt_dlinit
- lt_dlexit
- tryall_dlopen
- tryall_dlopen_module
- find_module
- canonicalize_path
- argzize_path
- foreach_dirinpath
- find_file_callback
- find_file
- find_handle_callback
- find_handle
- load_deplibs
- load_deplibs
- unload_deplibs
- trim
- parse_dotla_file
- try_dlopen
- file_not_found
- has_library_ext
- lt_dladvise_init
- lt_dladvise_destroy
- lt_dladvise_ext
- lt_dladvise_resident
- lt_dladvise_local
- lt_dladvise_global
- lt_dladvise_preload
- lt_dlopen
- lt_dlopenext
- lt_dlopenadvise
- lt_argz_insert
- lt_argz_insertinorder
- lt_argz_insertdir
- list_files_by_dir
- foreachfile_callback
- lt_dlforeachfile
- lt_dlclose
- lt_dlsym
- lt_dlerror
- lt_dlpath_insertdir
- lt_dladdsearchdir
- lt_dlinsertsearchdir
- lt_dlsetsearchpath
- lt_dlgetsearchpath
- lt_dlmakeresident
- lt_dlisresident
- lt_dlinterface_register
- lt_dlinterface_free
- lt_dlcaller_set_data
- lt_dlcaller_get_data
- lt_dlgetinfo
- lt_dlhandle_iterate
- lt_dlhandle_fetch
- lt_dlhandle_map
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 #include "lt__private.h"
  33 #include "lt_system.h"
  34 #include "lt_dlloader.h"
  35 
  36 
  37 
  38 
  39 
  40 
  41 #undef  LTDL_SEARCHPATH_VAR
  42 #define LTDL_SEARCHPATH_VAR     "LTDL_LIBRARY_PATH"
  43 
  44 
  45 #undef  LT_ARCHIVE_EXT
  46 #define LT_ARCHIVE_EXT  ".la"
  47 
  48 
  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 
  62 #undef  LT_SYMBOL_LENGTH
  63 #define LT_SYMBOL_LENGTH        128
  64 
  65 
  66 #undef  LT_SYMBOL_OVERHEAD
  67 #define LT_SYMBOL_OVERHEAD      5
  68 
  69 
  70 
  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 
  84 
  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 
  96 
  97 
  98 
  99 typedef int     foreach_callback_func (char *filename, void *data1,
 100                                        void *data2);
 101 
 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 
 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 
 165 
 166 
 167 void
 168 lt__alloc_die_callback (void)
     
 169 {
 170   LT__SETERROR (NO_MEMORY);
 171 }
 172 
 173 #ifdef HAVE_LIBDLLOADER
 174 
 175 
 176 
 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 
 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   
 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 
 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 
 225 int
 226 lt_dlinit (void)
     
 227 {
 228   int   errors  = 0;
 229 
 230   
 231   if (++initialized == 1)
 232     {
 233       lt__alloc_die     = lt__alloc_die_callback;
 234       handles           = 0;
 235       user_search_path  = 0; 
 236 
 237       
 238 
 239 
 240       errors += loader_init (get_vtable, 0);
 241 
 242       
 243 
 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 
 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   
 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   
 280   if (--initialized == 0)
 281     {
 282       int       level;
 283 
 284       while (handles && LT_DLIS_RESIDENT (handles))
 285         {
 286           handles = handles->next;
 287         }
 288 
 289       
 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                       
 309 
 310 
 311 
 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           
 324           if (!saw_nonresident)
 325             break;
 326         }
 327 
 328       
 329 
 330 
 331       if (!errors)
 332         LT__SETERRORSTR (0);
 333 
 334       
 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               
 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 
 365 
 366 
 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   
 384   for (;handle; handle = handle->next)
 385     {
 386       if ((handle->info.filename == filename) 
 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       
 405 
 406 
 407       
 408 
 409 
 410 
 411 
 412 
 413 
 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     
 472 
 473 
 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,
     
 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   
 507 
 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   
 517 
 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   
 525 
 526 
 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,
     
 543              const char *dlname,  const char *old_name, int installed,
 544              lt_dladvise advise)
 545 {
 546   
 547 
 548 
 549   if (old_name && tryall_dlopen (handle, old_name,
 550                           advise, lt_dlloader_find ("lt_preopen") ) == 0)
 551     {
 552       return 0;
 553     }
 554 
 555   
 556   if (dlname)
 557     {
 558       
 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       
 567       if (!installed)
 568         {
 569           if (tryall_dlopen_module (handle, dir, objdir,
 570                                     dlname, advise) == 0)
 571             return 0;
 572         }
 573 
 574       
 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)
     
 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         
 604 
 605 
 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         
 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         
 624 
 625 
 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     
 638     canonical[dest] = LT_EOS_CHAR;
 639   }
 640 
 641   
 642   *pcanonical = canonical;
 643 
 644   return 0;
 645 }
 646 
 647 static int
 648 argzize_path (const char *path, char **pargz, size_t *pargz_len)
     
 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 
 675 
 676 
 677 
 678 static int
 679 foreach_dirinpath (const char *search_path, const char *base_name,
     
 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; 
 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 
 743 
 744 
 745 static int
 746 find_file_callback (char *filename, void *data1, void *data2)
     
 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)
     
 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)
     
 783 {
 784   lt_dlhandle  *phandle         = (lt_dlhandle *) data;
 785   int           notfound        = access (filename, R_OK);
 786   lt_dladvise   advise          = (lt_dladvise) data2;
 787 
 788   
 789   if (notfound)
 790     return 0;
 791 
 792   
 793 
 794   if (tryall_dlopen (phandle, filename, advise, 0) != 0)
 795     *phandle = 0;
 796 
 797   return 1;
 798 }
 799 
 800 
 801 
 802 static lt_dlhandle *
 803 find_handle (const char *search_path, const char *base_name,
     
 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)
     
 819 {
 820   handle->depcount = 0;
 821   return 0;
 822 }
 823 
 824 #else 
 825 static int
 826 load_deplibs (lt_dlhandle handle, char *deplibs)
     
 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   
 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; 
 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   
 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; 
 917               if (strncmp(p, "-l", 2) == 0)
 918                 {
 919                   size_t name_len = 3+  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   
 938 
 939 
 940 
 941 
 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;    
 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   
 973   if (save_search_path) {
 974     MEMREASSIGN (user_search_path, save_search_path);
 975   }
 976 
 977   return errors;
 978 }
 979 #endif 
 980 
 981 static int
 982 unload_deplibs (lt_dlhandle handle)
     
 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)
     
1005 {
1006   
1007 
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 
1036 static int
1037 parse_dotla_file(FILE *file, char **dlname, char **libdir, char **deplibs,
     
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       
1059 
1060 
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       
1098 
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           
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 
1158 static int
1159 try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
     
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   
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       
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   
1222 
1223   if (canonicalize_path (attempt, &canonical) != 0)
1224     {
1225       ++errors;
1226       goto cleanup;
1227     }
1228 
1229   
1230 
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   
1260   name = MALLOC (char, ext - base_name + 1);
1261   if (!name)
1262     {
1263       ++errors;
1264       goto cleanup;
1265     }
1266 
1267   
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   
1285 
1286   if (!dir)
1287     {
1288       const lt_dlvtable *vtable = lt_dlloader_find ("lt_preopen");
1289 
1290       if (vtable)
1291         {
1292           
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           
1304 
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           
1320 
1321           FREE (*phandle);
1322           newhandle = NULL;
1323         }
1324     }
1325 
1326   
1327 
1328   if (advise && advise->try_preload_only)
1329     {
1330       goto cleanup;
1331     }
1332 
1333   
1334   if (ext && STREQ (ext, archive_ext))
1335     {
1336       
1337       FILE *    file     = 0;
1338       char *    dlname   = 0;
1339       char *    old_name = 0;
1340       char *    libdir   = 0;
1341       char *    deplibs  = 0;
1342 
1343       
1344 
1345 
1346       int       installed = 1;
1347 
1348       
1349 
1350 
1351 
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       
1387 
1388       if (!file)
1389         {
1390           LT__SETERROR (FILE_NOT_FOUND);
1391           ++errors;
1392           goto cleanup;
1393         }
1394 
1395       
1396       if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
1397             &old_name, &installed) != 0)
1398         ++errors;
1399 
1400       fclose (file);
1401 
1402       
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           
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       
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       
1464 
1465 
1466 
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)               
1514     FREE (base_name);
1515   FREE (canonical);
1516   FREE (archive_name);
1517 
1518   return errors;
1519 }
1520 
1521 
1522 
1523 
1524 static int
1525 file_not_found (void)
     
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 
1538 
1539 static int
1540 has_library_ext (const char *filename)
     
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 
1565 
1566 int
1567 lt_dladvise_init (lt_dladvise *padvise)
     
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)
     
1576 {
1577   if (padvise)
1578     FREE(*padvise);
1579   return 0;
1580 }
1581 
1582 int
1583 lt_dladvise_ext (lt_dladvise *padvise)
     
1584 {
1585   assert (padvise && *padvise);
1586   (*padvise)->try_ext = 1;
1587   return 0;
1588 }
1589 
1590 int
1591 lt_dladvise_resident (lt_dladvise *padvise)
     
1592 {
1593   assert (padvise && *padvise);
1594   (*padvise)->is_resident = 1;
1595   return 0;
1596 }
1597 
1598 int
1599 lt_dladvise_local (lt_dladvise *padvise)
     
1600 {
1601   assert (padvise && *padvise);
1602   (*padvise)->is_symlocal = 1;
1603   return 0;
1604 }
1605 
1606 int
1607 lt_dladvise_global (lt_dladvise *padvise)
     
1608 {
1609   assert (padvise && *padvise);
1610   (*padvise)->is_symglobal = 1;
1611   return 0;
1612 }
1613 
1614 int
1615 lt_dladvise_preload (lt_dladvise *padvise)
     
1616 {
1617   assert (padvise && *padvise);
1618   (*padvise)->try_preload_only = 1;
1619   return 0;
1620 }
1621 
1622 
1623 lt_dlhandle
1624 lt_dlopen (const char *filename)
     
1625 {
1626   return lt_dlopenadvise (filename, NULL);
1627 }
1628 
1629 
1630 
1631 
1632 
1633 
1634 lt_dlhandle
1635 lt_dlopenext (const char *filename)
     
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)
     
1650 {
1651   lt_dlhandle   handle  = 0;
1652   int           errors  = 0;
1653   const char *  saved_error     = 0;
1654 
1655   LT__GETERROR (saved_error);
1656 
1657   
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       
1670 
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       
1680       errors += try_dlopen (&handle, filename, archive_ext, advise);
1681 
1682       
1683 
1684 
1685 
1686 
1687       if (handle || ((errors > 0) && !file_not_found ()))
1688         return handle;
1689 
1690 #if defined LT_MODULE_EXT
1691       
1692       LT__SETERRORSTR (saved_error);
1693       errors = try_dlopen (&handle, filename, shlib_ext, advise);
1694 
1695       
1696 
1697       if (handle || ((errors > 0) && !file_not_found ()))
1698         return handle;
1699 #endif
1700 
1701 #if defined LT_SHARED_EXT
1702       
1703       LT__SETERRORSTR (saved_error);
1704       errors = try_dlopen (&handle, filename, shared_ext, advise);
1705 
1706       
1707 
1708       if (handle || ((errors > 0) && !file_not_found ()))
1709         return handle;
1710 #endif
1711     }
1712 
1713   
1714 
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,
     
1722                 const char *entry)
1723 {
1724   error_t error;
1725 
1726   
1727 
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)
     
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; 
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,
     
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   
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   
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   
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   
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)
     
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 
1868 
1869 static int
1870 foreachfile_callback (char *dirname, void *data1, void *data2)
     
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 
1898 
1899 
1900 
1901 
1902 
1903 int
1904 lt_dlforeachfile (const char *search_path,
     
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       
1914 
1915       is_done = foreach_dirinpath (search_path, 0,
1916                                    foreachfile_callback, fpptr, data);
1917     }
1918   else
1919     {
1920       
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)
     
1950 {
1951   lt_dlhandle cur, last;
1952   int errors = 0;
1953 
1954   
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   
1973 
1974 
1975 
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       
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)
     
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       
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       
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   
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)
     
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)
     
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   
2138   if (*ppath == 0)
2139     {
2140       assert (!before);         
2141       assert (dir);             
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   
2159 
2160 
2161 
2162 
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)
     
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)
     
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)
     
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)
     
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)
     
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)
     
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 
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)
     
2297 {
2298   lt__interface_id *interface_id = (lt__interface_id *) lt__malloc (sizeof *interface_id);
2299 
2300   
2301 
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)
     
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)
     
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   
2343 
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       
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)
     
2370 {
2371   void *result = (void *) 0;
2372   lt_dlhandle cur = handle;
2373 
2374   
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)
     
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)
     
2406 {
2407   lt_dlhandle handle = place;
2408   lt__interface_id *iterator = (lt__interface_id *) iface;
2409 
2410   assert (iface); 
2411 
2412   if (!handle)
2413     handle = handles;
2414   else
2415     handle = handle->next;
2416 
2417   
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)
     
2430 {
2431   lt_dlhandle handle = 0;
2432 
2433   assert (iface); 
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,
     
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); 
2454 
2455   while (cur)
2456     {
2457       int errorcode = 0;
2458 
2459       
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 }