Annotation of sql/pgsql/libltdl/ltdl.c, revision 1.4

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

E-mail: