Annotation of parser3/src/lib/ltdl/ltdl.c, revision 1.8

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

E-mail: