Annotation of gforth/libltdl/ltdl.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>