Annotation of sql/sqlite/libltdl/ltdl.c, revision 1.5

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

E-mail: