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

1.1       paf         1: /* ltdl.c -- system independent dlopen wrapper
1.2     ! paf         2:    Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
1.1       paf         3:    Originally by Thomas Tanner <tanner@ffii.org>
                      4:    This file is part of GNU Libtool.
                      5: 
                      6: This library is free software; you can redistribute it and/or
1.2     ! paf         7: modify it under the terms of the GNU Lesser General Public
1.1       paf         8: License as published by the Free Software Foundation; either
                      9: version 2 of the License, or (at your option) any later version.
                     10: 
1.2     ! paf        11: As a special exception to the GNU Lesser General Public License,
        !            12: if you distribute this file as part of a program or library that
        !            13: is built using GNU libtool, you may include it under the same
1.1       paf        14: distribution terms that you use for the rest of that program.
                     15: 
                     16: This library is distributed in the hope that it will be useful,
                     17: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     18: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1.2     ! paf        19: Lesser General Public License for more details.
1.1       paf        20: 
1.2     ! paf        21: You should have received a copy of the GNU Lesser General Public
1.1       paf        22: License along with this library; if not, write to the Free Software
                     23: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
                     24: 02111-1307  USA
1.2     ! paf        25: 
1.1       paf        26: */
                     27: 
1.2     ! paf        28: #if HAVE_CONFIG_H
        !            29: #  include <config.h>
        !            30: #endif
        !            31: 
        !            32: #if HAVE_UNISTD_H
        !            33: #  include <unistd.h>
        !            34: #endif
1.1       paf        35: 
1.2     ! paf        36: #if HAVE_STDIO_H
        !            37: #  include <stdio.h>
        !            38: #endif
1.1       paf        39: 
1.2     ! paf        40: #if HAVE_STDLIB_H
        !            41: #  include <stdlib.h>
1.1       paf        42: #endif
                     43: 
1.2     ! paf        44: #if HAVE_STRING_H
        !            45: #  include <string.h>
        !            46: #else
        !            47: #  if HAVE_STRINGS_H
        !            48: #    include <strings.h>
        !            49: #  endif
1.1       paf        50: #endif
                     51: 
                     52: #if HAVE_CTYPE_H
1.2     ! paf        53: #  include <ctype.h>
1.1       paf        54: #endif
                     55: 
                     56: #if HAVE_MALLOC_H
1.2     ! paf        57: #  include <malloc.h>
1.1       paf        58: #endif
                     59: 
                     60: #if HAVE_MEMORY_H
1.2     ! paf        61: #  include <memory.h>
        !            62: #endif
        !            63: 
        !            64: #if HAVE_ERRNO_H
        !            65: #  include <errno.h>
        !            66: #endif
        !            67: 
        !            68: #if HAVE_DIRENT_H
        !            69: #  include <dirent.h>
        !            70: #  define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
        !            71: #else
        !            72: #  define dirent direct
        !            73: #  define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
        !            74: #  if HAVE_SYS_NDIR_H
        !            75: #    include <sys/ndir.h>
        !            76: #  endif
        !            77: #  if HAVE_SYS_DIR_H
        !            78: #    include <sys/dir.h>
        !            79: #  endif
        !            80: #  if HAVE_NDIR_H
        !            81: #    include <ndir.h>
        !            82: #  endif
1.1       paf        83: #endif
                     84: 
1.2     ! paf        85: #if HAVE_ARGZ_H
        !            86: #  include <argz.h>
1.1       paf        87: #endif
                     88: 
1.2     ! paf        89: #if HAVE_ASSERT_H
        !            90: #  include <assert.h>
        !            91: #else
        !            92: #  define assert(arg)  ((void) 0)
1.1       paf        93: #endif
                     94: 
                     95: #include "ltdl.h"
                     96: 
1.2     ! paf        97: #if WITH_DMALLOC
        !            98: #  include <dmalloc.h>
        !            99: #endif
        !           100: 
        !           101: 
        !           102: 
        !           103: 
        !           104: /* --- WINDOWS SUPPORT --- */
        !           105: 
        !           106: 
        !           107: #ifdef DLL_EXPORT
        !           108: #  define LT_GLOBAL_DATA       __declspec(dllexport)
        !           109: #else
        !           110: #  define LT_GLOBAL_DATA
1.1       paf       111: #endif
                    112: 
                    113: /* fopen() mode flags for reading a text file */
1.2     ! paf       114: #undef LT_READTEXT_MODE
        !           115: #ifdef __WINDOWS__
        !           116: #  define LT_READTEXT_MODE "rt"
1.1       paf       117: #else
1.2     ! paf       118: #  define LT_READTEXT_MODE "r"
        !           119: #endif
        !           120: 
        !           121: 
        !           122: 
        !           123: 
        !           124: /* --- MANIFEST CONSTANTS --- */
        !           125: 
        !           126: 
        !           127: /* Standard libltdl search path environment variable name  */
        !           128: #undef  LTDL_SEARCHPATH_VAR
        !           129: #define LTDL_SEARCHPATH_VAR    "LTDL_LIBRARY_PATH"
        !           130: 
        !           131: /* Standard libtool archive file extension.  */
        !           132: #undef  LTDL_ARCHIVE_EXT
        !           133: #define LTDL_ARCHIVE_EXT       ".la"
        !           134: 
        !           135: /* max. filename length */
        !           136: #ifndef LT_FILENAME_MAX
        !           137: #  define LT_FILENAME_MAX      1024
1.1       paf       138: #endif
                    139: 
                    140: /* This is the maximum symbol size that won't require malloc/free */
1.2     ! paf       141: #undef LT_SYMBOL_LENGTH
        !           142: #define LT_SYMBOL_LENGTH       128
1.1       paf       143: 
                    144: /* This accounts for the _LTX_ separator */
1.2     ! paf       145: #undef LT_SYMBOL_OVERHEAD
        !           146: #define LT_SYMBOL_OVERHEAD     5
        !           147: 
        !           148: 
        !           149: 
        !           150: 
        !           151: /* --- MEMORY HANDLING --- */
        !           152: 
        !           153: 
        !           154: /* These are the functions used internally.  In addition to making
        !           155:    use of the associated function pointers above, they also perform
        !           156:    error handling.  */
        !           157: static char   *lt_estrdup      LT_PARAMS((const char *str));
        !           158: static lt_ptr lt_emalloc       LT_PARAMS((size_t size));
        !           159: static lt_ptr lt_erealloc      LT_PARAMS((lt_ptr addr, size_t size));
        !           160: 
        !           161: static lt_ptr rpl_realloc      LT_PARAMS((lt_ptr ptr, size_t size));
        !           162: 
        !           163: /* These are the pointers that can be changed by the caller:  */
        !           164: LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc)   LT_PARAMS((size_t size))
        !           165:                        = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
        !           166: LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc)  LT_PARAMS((lt_ptr ptr, size_t size))
        !           167:                        = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
        !           168: LT_GLOBAL_DATA void   (*lt_dlfree)     LT_PARAMS((lt_ptr ptr))
        !           169:                        = (void (*) LT_PARAMS((lt_ptr))) free;
        !           170: 
        !           171: /* The following macros reduce the amount of typing needed to cast
        !           172:    assigned memory.  */
        !           173: #if WITH_DMALLOC
        !           174: 
        !           175: #define LT_DLMALLOC(tp, n)     ((tp *) xmalloc ((n) * sizeof(tp)))
        !           176: #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
        !           177: #define LT_DLFREE(p)                                           \
        !           178:        LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
        !           179: 
        !           180: #define LT_EMALLOC(tp, n)      ((tp *) xmalloc ((n) * sizeof(tp)))
        !           181: #define LT_EREALLOC(tp, p, n)  ((tp *) xrealloc ((p), (n) * sizeof(tp)))
        !           182: 
        !           183: #else
        !           184: 
        !           185: #define LT_DLMALLOC(tp, n)     ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
        !           186: #define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
        !           187: #define LT_DLFREE(p)                                           \
        !           188:        LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
        !           189: 
        !           190: #define LT_EMALLOC(tp, n)      ((tp *) lt_emalloc ((n) * sizeof(tp)))
        !           191: #define LT_EREALLOC(tp, p, n)  ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
1.1       paf       192: 
                    193: #endif
                    194: 
1.2     ! paf       195: #define LT_DLMEM_REASSIGN(p, q)                        LT_STMT_START { \
        !           196:        if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; }   \
        !           197:                                                } LT_STMT_END
        !           198: 
        !           199: 
        !           200: /* --- REPLACEMENT FUNCTIONS --- */
        !           201: 
1.1       paf       202: 
                    203: #undef strdup
1.2     ! paf       204: #define strdup rpl_strdup
1.1       paf       205: 
1.2     ! paf       206: static char *strdup LT_PARAMS((const char *str));
        !           207: 
        !           208: static char *
1.1       paf       209: strdup(str)
1.2     ! paf       210:      const char *str;
1.1       paf       211: {
1.2     ! paf       212:   char *tmp = NULL;
        !           213: 
        !           214:   if (str)
        !           215:     {
        !           216:       tmp = LT_DLMALLOC (char, 1+ strlen (str));
        !           217:       if (tmp)
        !           218:        {
        !           219:          strcpy(tmp, str);
        !           220:        }
        !           221:     }
1.1       paf       222: 
1.2     ! paf       223:   return tmp;
1.1       paf       224: }
                    225: 
                    226: 
1.2     ! paf       227: #if ! HAVE_STRCMP
        !           228: 
        !           229: #undef strcmp
        !           230: #define strcmp rpl_strcmp
        !           231: 
        !           232: static int strcmp LT_PARAMS((const char *str1, const char *str2));
        !           233: 
        !           234: static int
        !           235: strcmp (str1, str2)
        !           236:      const char *str1;
        !           237:      const char *str2;
        !           238: {
        !           239:   if (str1 == str2)
        !           240:     return 0;
        !           241:   if (str1 == NULL)
        !           242:     return -1;
        !           243:   if (str2 == NULL)
        !           244:     return 1;
        !           245: 
        !           246:   for (;*str1 && *str2; ++str1, ++str2)
        !           247:     {
        !           248:       if (*str1 != *str2)
        !           249:        break;
        !           250:     }
        !           251: 
        !           252:   return (int)(*str1 - *str2);
        !           253: }
        !           254: #endif
        !           255: 
1.1       paf       256: 
1.2     ! paf       257: #if ! HAVE_STRCHR
1.1       paf       258: 
1.2     ! paf       259: #  if HAVE_INDEX
        !           260: #    define strchr index
        !           261: #  else
        !           262: #    define strchr rpl_strchr
1.1       paf       263: 
1.2     ! paf       264: static const char *strchr LT_PARAMS((const char *str, int ch));
1.1       paf       265: 
1.2     ! paf       266: static const char*
1.1       paf       267: strchr(str, ch)
1.2     ! paf       268:      const char *str;
        !           269:      int ch;
1.1       paf       270: {
1.2     ! paf       271:   const char *p;
1.1       paf       272: 
1.2     ! paf       273:   for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
        !           274:     /*NOWORK*/;
1.1       paf       275: 
1.2     ! paf       276:   return (*p == (char)ch) ? p : 0;
1.1       paf       277: }
                    278: 
1.2     ! paf       279: #  endif
        !           280: #endif /* !HAVE_STRCHR */
1.1       paf       281: 
                    282: 
                    283: #if ! HAVE_STRRCHR
                    284: 
1.2     ! paf       285: #  if HAVE_RINDEX
        !           286: #    define strrchr rindex
        !           287: #  else
        !           288: #    define strrchr rpl_strrchr
1.1       paf       289: 
1.2     ! paf       290: static const char *strrchr LT_PARAMS((const char *str, int ch));
1.1       paf       291: 
1.2     ! paf       292: static const char*
1.1       paf       293: strrchr(str, ch)
1.2     ! paf       294:      const char *str;
        !           295:      int ch;
1.1       paf       296: {
1.2     ! paf       297:   const char *p, *q = NULL;
1.1       paf       298: 
1.2     ! paf       299:   for (p = str; *p != LT_EOS_CHAR; ++p)
        !           300:     {
        !           301:       if (*p == (char) ch)
        !           302:        {
        !           303:          q = p;
        !           304:        }
        !           305:     }
1.1       paf       306: 
1.2     ! paf       307:   return q;
1.1       paf       308: }
                    309: 
                    310: # endif
                    311: #endif
                    312: 
1.2     ! paf       313: /* NOTE:  Neither bcopy nor the memcpy implementation below can
        !           314:           reliably handle copying in overlapping areas of memory.  Use
        !           315:           memmove (for which there is a fallback implmentation below)
        !           316:          if you need that behaviour.  */
        !           317: #if ! HAVE_MEMCPY
1.1       paf       318: 
1.2     ! paf       319: #  if HAVE_BCOPY
        !           320: #    define memcpy(dest, src, size)    bcopy (src, dest, size)
        !           321: #  else
        !           322: #    define memcpy rpl_memcpy
1.1       paf       323: 
1.2     ! paf       324: static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
1.1       paf       325: 
1.2     ! paf       326: static lt_ptr
        !           327: memcpy (dest, src, size)
        !           328:      lt_ptr dest;
        !           329:      const lt_ptr src;
        !           330:      size_t size;
        !           331: {
        !           332:   size_t i = 0;
1.1       paf       333: 
1.2     ! paf       334:   for (i = 0; i < size; ++i)
        !           335:     {
        !           336:       dest[i] = src[i];
        !           337:     }
1.1       paf       338: 
1.2     ! paf       339:   return dest;
1.1       paf       340: }
                    341: 
1.2     ! paf       342: #  endif /* !HAVE_BCOPY */
        !           343: #endif   /* !HAVE_MEMCPY */
        !           344: 
        !           345: #if ! HAVE_MEMMOVE
        !           346: #  define memmove rpl_memmove
        !           347: 
        !           348: static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
        !           349: 
        !           350: static lt_ptr
        !           351: memmove (dest, src, size)
        !           352:      lt_ptr dest;
        !           353:      const lt_ptr src;
        !           354:      size_t size;
1.1       paf       355: {
1.2     ! paf       356:   size_t i;
        !           357: 
        !           358:   if (dest < src)
        !           359:     for (i = 0; i < size; ++i)
        !           360:       {
        !           361:        dest[i] = src[i];
        !           362:       }
        !           363:   else if (dest > src)
        !           364:     for (i = size -1; i >= 0; --i)
        !           365:       {
        !           366:        dest[i] = src[i];
        !           367:       }
        !           368: 
        !           369:   return dest;
1.1       paf       370: }
                    371: 
1.2     ! paf       372: #endif /* !HAVE_MEMMOVE */
        !           373: 
        !           374: 
        !           375: /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
        !           376:     ``realloc is not entirely portable''
        !           377:    In any case we want to use the allocator supplied by the user without
        !           378:    burdening them with an lt_dlrealloc function pointer to maintain.
        !           379:    Instead implement our own version (with known boundary conditions)
        !           380:    using lt_dlmalloc and lt_dlfree. */
        !           381: 
        !           382: #undef realloc
        !           383: #define realloc rpl_realloc
        !           384: 
        !           385: static lt_ptr
        !           386: realloc (ptr, size)
        !           387:      lt_ptr ptr;
        !           388:      size_t size;
1.1       paf       389: {
1.2     ! paf       390:   if (size == 0)
        !           391:     {
        !           392:       /* For zero or less bytes, free the original memory */
        !           393:       if (ptr != NULL)
        !           394:        {
        !           395:          lt_dlfree (ptr);
1.1       paf       396:        }
                    397: 
1.2     ! paf       398:       return (lt_ptr) 0;
        !           399:     }
        !           400:   else if (ptr == NULL)
        !           401:     {
        !           402:       /* Allow reallocation of a NULL pointer.  */
        !           403:       return lt_dlmalloc (size);
        !           404:     }
        !           405:   else
        !           406:     {
        !           407:       /* Allocate a new block, copy and free the old block.  */
        !           408:       lt_ptr mem = lt_dlmalloc (size);
        !           409: 
        !           410:       if (mem)
        !           411:        {
        !           412:          memcpy (mem, ptr, size);
        !           413:          lt_dlfree (ptr);
1.1       paf       414:        }
                    415: 
1.2     ! paf       416:       /* Note that the contents of PTR are not damaged if there is
        !           417:         insufficient memory to realloc.  */
        !           418:       return mem;
        !           419:     }
1.1       paf       420: }
                    421: 
                    422: 
1.2     ! paf       423: #if ! HAVE_ARGZ_APPEND
        !           424: #  define argz_append rpl_argz_append
1.1       paf       425: 
1.2     ! paf       426: static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
        !           427:                                        const char *buf, size_t buf_len));
1.1       paf       428: 
1.2     ! paf       429: static error_t
        !           430: argz_append (pargz, pargz_len, buf, buf_len)
        !           431:      char **pargz;
        !           432:      size_t *pargz_len;
        !           433:      const char *buf;
        !           434:      size_t buf_len;
        !           435: {
        !           436:   size_t argz_len;
        !           437:   char  *argz;
1.1       paf       438: 
1.2     ! paf       439:   assert (pargz);
        !           440:   assert (pargz_len);
        !           441:   assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
1.1       paf       442: 
1.2     ! paf       443:   /* If nothing needs to be appended, no more work is required.  */
        !           444:   if (buf_len == 0)
        !           445:     return 0;
1.1       paf       446: 
1.2     ! paf       447:   /* Ensure there is enough room to append BUF_LEN.  */
        !           448:   argz_len = *pargz_len + buf_len;
        !           449:   argz = LT_DLREALLOC (char, *pargz, argz_len);
        !           450:   if (!argz)
        !           451:     return ENOMEM;
1.1       paf       452: 
1.2     ! paf       453:   /* Copy characters from BUF after terminating '\0' in ARGZ.  */
        !           454:   memcpy (argz + *pargz_len, buf, buf_len);
1.1       paf       455: 
1.2     ! paf       456:   /* Assign new values.  */
        !           457:   *pargz = argz;
        !           458:   *pargz_len = argz_len;
1.1       paf       459: 
1.2     ! paf       460:   return 0;
1.1       paf       461: }
1.2     ! paf       462: #endif /* !HAVE_ARGZ_APPEND */
1.1       paf       463: 
1.2     ! paf       464: 
        !           465: #if ! HAVE_ARGZ_CREATE_SEP
        !           466: #  define argz_create_sep rpl_argz_create_sep
        !           467: 
        !           468: static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
        !           469:                                            char **pargz, size_t *pargz_len));
        !           470: 
        !           471: static error_t
        !           472: argz_create_sep (str, delim, pargz, pargz_len)
        !           473:      const char *str;
        !           474:      int delim;
        !           475:      char **pargz;
        !           476:      size_t *pargz_len;
1.1       paf       477: {
1.2     ! paf       478:   size_t argz_len;
        !           479:   char *argz = NULL;
        !           480: 
        !           481:   assert (str);
        !           482:   assert (pargz);
        !           483:   assert (pargz_len);
        !           484: 
        !           485:   /* Make a copy of STR, but replacing each occurence of
        !           486:      DELIM with '\0'.  */
        !           487:   argz_len = 1+ LT_STRLEN (str);
        !           488:   if (argz_len)
        !           489:     {
        !           490:       const char *p;
        !           491:       char *q;
        !           492: 
        !           493:       argz = LT_DLMALLOC (char, argz_len);
        !           494:       if (!argz)
        !           495:        return ENOMEM;
1.1       paf       496: 
1.2     ! paf       497:       for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
        !           498:        {
        !           499:          if (*p == delim)
        !           500:            {
        !           501:              /* Ignore leading delimiters, and fold consecutive
        !           502:                 delimiters in STR into a single '\0' in ARGZ.  */
        !           503:              if ((q > argz) && (q[-1] != LT_EOS_CHAR))
        !           504:                *q++ = LT_EOS_CHAR;
        !           505:              else
        !           506:                --argz_len;
        !           507:            }
        !           508:          else
        !           509:            *q++ = *p;
1.1       paf       510:        }
1.2     ! paf       511:       /* Copy terminating LT_EOS_CHAR.  */
        !           512:       *q = *p;
        !           513:     }
        !           514: 
        !           515:   /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory.  */
        !           516:   if (!argz_len)
        !           517:     LT_DLFREE (argz);
        !           518: 
        !           519:   /* Assign new values.  */
        !           520:   *pargz = argz;
        !           521:   *pargz_len = argz_len;
        !           522: 
        !           523:   return 0;
1.1       paf       524: }
1.2     ! paf       525: #endif /* !HAVE_ARGZ_CREATE_SEP */
        !           526: 
        !           527: 
        !           528: #if ! HAVE_ARGZ_INSERT
        !           529: #  define argz_insert rpl_argz_insert
1.1       paf       530: 
1.2     ! paf       531: static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
        !           532:                                        char *before, const char *entry));
        !           533: 
        !           534: static error_t
        !           535: argz_insert (pargz, pargz_len, before, entry)
        !           536:      char **pargz;
        !           537:      size_t *pargz_len;
        !           538:      char *before;
        !           539:      const char *entry;
1.1       paf       540: {
1.2     ! paf       541:   assert (pargz);
        !           542:   assert (pargz_len);
        !           543:   assert (entry && *entry);
1.1       paf       544: 
1.2     ! paf       545:   /* No BEFORE address indicates ENTRY should be inserted after the
        !           546:      current last element.  */
        !           547:   if (!before)
        !           548:     return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
1.1       paf       549: 
1.2     ! paf       550:   /* This probably indicates a programmer error, but to preserve
        !           551:      semantics, scan back to the start of an entry if BEFORE points
        !           552:      into the middle of it.  */
        !           553:   while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR))
        !           554:     --before;
1.1       paf       555: 
1.2     ! paf       556:   {
        !           557:     size_t entry_len   = 1+ LT_STRLEN (entry);
        !           558:     size_t argz_len    = *pargz_len + entry_len;
        !           559:     size_t offset      = before - *pargz;
        !           560:     char   *argz       = LT_DLREALLOC (char, *pargz, argz_len);
1.1       paf       561: 
1.2     ! paf       562:     if (!argz)
        !           563:       return ENOMEM;
1.1       paf       564: 
1.2     ! paf       565:     /* Make BEFORE point to the equivalent offset in ARGZ that it
        !           566:        used to have in *PARGZ incase realloc() moved the block.  */
        !           567:     before = argz + offset;
1.1       paf       568: 
1.2     ! paf       569:     /* Move the ARGZ entries starting at BEFORE up into the new
        !           570:        space at the end -- making room to copy ENTRY into the
        !           571:        resulting gap.  */
        !           572:     memmove (before + entry_len, before, *pargz_len - offset);
        !           573:     memcpy  (before, entry, entry_len);
1.1       paf       574: 
1.2     ! paf       575:     /* Assign new values.  */
        !           576:     *pargz = argz;
        !           577:     *pargz_len = argz_len;
        !           578:   }
1.1       paf       579: 
1.2     ! paf       580:   return 0;
1.1       paf       581: }
1.2     ! paf       582: #endif /* !HAVE_ARGZ_INSERT */
1.1       paf       583: 
1.2     ! paf       584: 
        !           585: #if ! HAVE_ARGZ_NEXT
        !           586: #  define argz_next rpl_argz_next
        !           587: 
        !           588: static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
        !           589:                                    const char *entry));
        !           590: 
        !           591: static char *
        !           592: argz_next (argz, argz_len, entry)
        !           593:      char *argz;
        !           594:      size_t argz_len;
        !           595:      const char *entry;
1.1       paf       596: {
1.2     ! paf       597:   assert ((argz && argz_len) || (!argz && !argz_len));
        !           598: 
        !           599:   if (entry)
        !           600:     {
        !           601:       /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
        !           602:         within the ARGZ vector.  */
        !           603:       assert ((!argz && !argz_len)
        !           604:              || ((argz <= entry) && (entry < (argz + argz_len))));
        !           605: 
        !           606:       /* Move to the char immediately after the terminating
        !           607:         '\0' of ENTRY.  */
        !           608:       entry = 1+ strchr (entry, LT_EOS_CHAR);
        !           609: 
        !           610:       /* Return either the new ENTRY, or else NULL if ARGZ is
        !           611:         exhausted.  */
        !           612:       return (entry >= argz + argz_len) ? 0 : (char *) entry;
        !           613:     }
        !           614:   else
        !           615:     {
        !           616:       /* This should probably be flagged as a programmer error,
        !           617:         since starting an argz_next loop with the iterator set
        !           618:         to ARGZ is safer.  To preserve semantics, handle the NULL
        !           619:         case by returning the start of ARGZ (if any).  */
        !           620:       if (argz_len > 0)
        !           621:        return argz;
        !           622:       else
1.1       paf       623:        return 0;
1.2     ! paf       624:     }
1.1       paf       625: }
1.2     ! paf       626: #endif /* !HAVE_ARGZ_NEXT */
        !           627: 
1.1       paf       628: 
                    629: 
1.2     ! paf       630: #if ! HAVE_ARGZ_STRINGIFY
        !           631: #  define argz_stringify rpl_argz_stringify
        !           632: 
        !           633: static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
        !           634:                                       int sep));
        !           635: 
        !           636: static void
        !           637: argz_stringify (argz, argz_len, sep)
        !           638:      char *argz;
        !           639:      size_t argz_len;
        !           640:      int sep;
1.1       paf       641: {
1.2     ! paf       642:   assert ((argz && argz_len) || (!argz && !argz_len));
        !           643: 
        !           644:   if (sep)
        !           645:     {
        !           646:       --argz_len;              /* don't stringify the terminating EOS */
        !           647:       while (--argz_len > 0)
        !           648:        {
        !           649:          if (argz[argz_len] == LT_EOS_CHAR)
        !           650:            argz[argz_len] = sep;
1.1       paf       651:        }
1.2     ! paf       652:     }
1.1       paf       653: }
1.2     ! paf       654: #endif /* !HAVE_ARGZ_STRINGIFY */
        !           655: 
        !           656: 
        !           657: 
        !           658: 
        !           659: /* --- TYPE DEFINITIONS -- */
1.1       paf       660: 
                    661: 
1.2     ! paf       662: /* This type is used for the array of caller data sets in each handler. */
        !           663: typedef struct {
        !           664:   lt_dlcaller_id       key;
        !           665:   lt_ptr               data;
        !           666: } lt_caller_data;
1.1       paf       667: 
                    668: 
                    669: 
1.2     ! paf       670: 
        !           671: /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
1.1       paf       672: 
                    673: 
1.2     ! paf       674: /* Extract the diagnostic strings from the error table macro in the same
        !           675:    order as the enumerated indices in ltdl.h. */
1.1       paf       676: 
1.2     ! paf       677: static const char *lt_dlerror_strings[] =
        !           678:   {
        !           679: #define LT_ERROR(name, diagnostic)     (diagnostic),
        !           680:     lt_dlerror_table
        !           681: #undef LT_ERROR
1.1       paf       682: 
1.2     ! paf       683:     0
        !           684:   };
1.1       paf       685: 
1.2     ! paf       686: /* This structure is used for the list of registered loaders. */
        !           687: struct lt_dlloader {
        !           688:   struct lt_dlloader   *next;
        !           689:   const char          *loader_name;    /* identifying name for each loader */
        !           690:   const char          *sym_prefix;     /* prefix for symbols */
        !           691:   lt_module_open       *module_open;
        !           692:   lt_module_close      *module_close;
        !           693:   lt_find_sym         *find_sym;
        !           694:   lt_dlloader_exit     *dlloader_exit;
        !           695:   lt_user_data         dlloader_data;
        !           696: };
1.1       paf       697: 
1.2     ! paf       698: struct lt_dlhandle_struct {
        !           699:   struct lt_dlhandle_struct   *next;
        !           700:   lt_dlloader         *loader;         /* dlopening interface */
        !           701:   lt_dlinfo            info;
        !           702:   int                  depcount;       /* number of dependencies */
        !           703:   lt_dlhandle         *deplibs;        /* dependencies */
        !           704:   lt_module            module;         /* system module handle */
        !           705:   lt_ptr               system;         /* system specific data */
        !           706:   lt_caller_data       *caller_data;   /* per caller associated data */
        !           707:   int                  flags;          /* various boolean stats */
        !           708: };
1.1       paf       709: 
1.2     ! paf       710: /* Various boolean flags can be stored in the flags field of an
        !           711:    lt_dlhandle_struct... */
        !           712: #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
        !           713: #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
1.1       paf       714: 
1.2     ! paf       715: #define LT_DLRESIDENT_FLAG         (0x01 << 0)
        !           716: /* ...add more flags here... */
1.1       paf       717: 
1.2     ! paf       718: #define LT_DLIS_RESIDENT(handle)    LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
1.1       paf       719: 
                    720: 
1.2     ! paf       721: #define LT_DLSTRERROR(name)    lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
1.1       paf       722: 
1.2     ! paf       723: static const char      objdir[]                = LTDL_OBJDIR;
        !           724: static const char      archive_ext[]           = LTDL_ARCHIVE_EXT;
        !           725: #ifdef LTDL_SHLIB_EXT
        !           726: static const char      shlib_ext[]             = LTDL_SHLIB_EXT;
        !           727: #endif
        !           728: #ifdef LTDL_SYSSEARCHPATH
        !           729: static const char      sys_search_path[]       = LTDL_SYSSEARCHPATH;
1.1       paf       730: #endif
                    731: 
                    732: 
                    733: 
1.2     ! paf       734: 
        !           735: /* --- MUTEX LOCKING --- */
        !           736: 
        !           737: 
        !           738: /* Macros to make it easier to run the lock functions only if they have
        !           739:    been registered.  The reason for the complicated lock macro is to
        !           740:    ensure that the stored error message from the last error is not
        !           741:    accidentally erased if the current function doesn't generate an
        !           742:    error of its own.  */
        !           743: #define LT_DLMUTEX_LOCK()                      LT_STMT_START { \
        !           744:        if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)();    \
        !           745:                                                } LT_STMT_END
        !           746: #define LT_DLMUTEX_UNLOCK()                    LT_STMT_START { \
        !           747:        if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
        !           748:                                                } LT_STMT_END
        !           749: #define LT_DLMUTEX_SETERROR(errormsg)          LT_STMT_START { \
        !           750:        if (lt_dlmutex_seterror_func)                           \
        !           751:                (*lt_dlmutex_seterror_func) (errormsg);         \
        !           752:        else    lt_dllast_error = (errormsg);   } LT_STMT_END
        !           753: #define LT_DLMUTEX_GETERROR(errormsg)          LT_STMT_START { \
        !           754:        if (lt_dlmutex_seterror_func)                           \
        !           755:                (errormsg) = (*lt_dlmutex_geterror_func) ();    \
        !           756:        else    (errormsg) = lt_dllast_error;   } LT_STMT_END
        !           757: 
        !           758: /* The mutex functions stored here are global, and are necessarily the
        !           759:    same for all threads that wish to share access to libltdl.  */
        !           760: static lt_dlmutex_lock     *lt_dlmutex_lock_func     = NULL;
        !           761: static lt_dlmutex_unlock   *lt_dlmutex_unlock_func   = NULL;
        !           762: static lt_dlmutex_seterror *lt_dlmutex_seterror_func = NULL;
        !           763: static lt_dlmutex_geterror *lt_dlmutex_geterror_func = NULL;
        !           764: static const char          *lt_dllast_error          = NULL;
        !           765: 
        !           766: 
        !           767: /* Either set or reset the mutex functions.  Either all the arguments must
        !           768:    be valid functions, or else all can be NULL to turn off locking entirely.
        !           769:    The registered functions should be manipulating a static global lock
        !           770:    from the lock() and unlock() callbacks, which needs to be reentrant.  */
        !           771: int
        !           772: lt_dlmutex_register (lock, unlock, seterror, geterror)
        !           773:      lt_dlmutex_lock *lock;
        !           774:      lt_dlmutex_unlock *unlock;
        !           775:      lt_dlmutex_seterror *seterror;
        !           776:      lt_dlmutex_geterror *geterror;
        !           777: {
        !           778:   lt_dlmutex_unlock *old_unlock = unlock;
        !           779:   int               errors     = 0;
1.1       paf       780: 
1.2     ! paf       781:   /* Lock using the old lock() callback, if any.  */
        !           782:   LT_DLMUTEX_LOCK ();
1.1       paf       783: 
1.2     ! paf       784:   if ((lock && unlock && seterror && geterror)
        !           785:       || !(lock || unlock || seterror || geterror))
        !           786:     {
        !           787:       lt_dlmutex_lock_func     = lock;
        !           788:       lt_dlmutex_unlock_func   = unlock;
        !           789:       lt_dlmutex_geterror_func = geterror;
        !           790:     }
        !           791:   else
        !           792:     {
        !           793:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
        !           794:       ++errors;
        !           795:     }
1.1       paf       796: 
1.2     ! paf       797:   /* Use the old unlock() callback we saved earlier, if any.  Otherwise
        !           798:      record any errors using internal storage.  */
        !           799:   if (old_unlock)
        !           800:     (*old_unlock) ();
1.1       paf       801: 
1.2     ! paf       802:   /* Return the number of errors encountered during the execution of
        !           803:      this function.  */
        !           804:   return errors;
1.1       paf       805: }
                    806: 
                    807: 
                    808: 
1.2     ! paf       809: 
        !           810: /* --- ERROR HANDLING --- */
1.1       paf       811: 
                    812: 
1.2     ! paf       813: static const char    **user_error_strings      = NULL;
        !           814: static int             errorcount              = LT_ERROR_MAX;
1.1       paf       815: 
1.2     ! paf       816: int
        !           817: lt_dladderror (diagnostic)
        !           818:      const char *diagnostic;
        !           819: {
        !           820:   int          errindex = 0;
        !           821:   int          result   = -1;
        !           822:   const char  **temp     = NULL;
        !           823: 
        !           824:   assert (diagnostic);
        !           825: 
        !           826:   LT_DLMUTEX_LOCK ();
        !           827: 
        !           828:   errindex = errorcount - LT_ERROR_MAX;
        !           829:   temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
        !           830:   if (temp)
        !           831:     {
        !           832:       user_error_strings               = temp;
        !           833:       user_error_strings[errindex]     = diagnostic;
        !           834:       result                           = errorcount++;
        !           835:     }
        !           836: 
        !           837:   LT_DLMUTEX_UNLOCK ();
        !           838: 
        !           839:   return result;
        !           840: }
        !           841: 
        !           842: int
        !           843: lt_dlseterror (errindex)
        !           844:      int errindex;
        !           845: {
        !           846:   int          errors   = 0;
        !           847: 
        !           848:   LT_DLMUTEX_LOCK ();
        !           849: 
        !           850:   if (errindex >= errorcount || errindex < 0)
        !           851:     {
        !           852:       /* Ack!  Error setting the error message! */
        !           853:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
        !           854:       ++errors;
        !           855:     }
        !           856:   else if (errindex < LT_ERROR_MAX)
        !           857:     {
        !           858:       /* No error setting the error message! */
        !           859:       LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
        !           860:     }
        !           861:   else
        !           862:     {
        !           863:       /* No error setting the error message! */
        !           864:       LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
        !           865:     }
        !           866: 
        !           867:   LT_DLMUTEX_UNLOCK ();
        !           868: 
        !           869:   return errors;
        !           870: }
        !           871: 
        !           872: static lt_ptr
        !           873: lt_emalloc (size)
        !           874:      size_t size;
        !           875: {
        !           876:   lt_ptr mem = lt_dlmalloc (size);
        !           877:   if (size && !mem)
        !           878:     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
        !           879:   return mem;
        !           880: }
        !           881: 
        !           882: static lt_ptr
        !           883: lt_erealloc (addr, size)
        !           884:      lt_ptr addr;
        !           885:      size_t size;
        !           886: {
        !           887:   lt_ptr mem = realloc (addr, size);
        !           888:   if (size && !mem)
        !           889:     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
        !           890:   return mem;
        !           891: }
        !           892: 
        !           893: static char *
        !           894: lt_estrdup (str)
        !           895:      const char *str;
        !           896: {
        !           897:   char *copy = strdup (str);
        !           898:   if (LT_STRLEN (str) && !copy)
        !           899:     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
        !           900:   return copy;
        !           901: }
        !           902: 
        !           903: 
        !           904: 
        !           905: 
        !           906: /* --- DLOPEN() INTERFACE LOADER --- */
        !           907: 
        !           908: 
        !           909: /* The Cygwin dlopen implementation prints a spurious error message to
        !           910:    stderr if its call to LoadLibrary() fails for any reason.  We can
        !           911:    mitigate this by not using the Cygwin implementation, and falling
        !           912:    back to our own LoadLibrary() wrapper. */
        !           913: #if HAVE_LIBDL && !defined(__CYGWIN__)
        !           914: 
        !           915: /* dynamic linking with dlopen/dlsym */
        !           916: 
        !           917: #if HAVE_DLFCN_H
        !           918: #  include <dlfcn.h>
        !           919: #endif
        !           920: 
        !           921: #if HAVE_SYS_DL_H
        !           922: #  include <sys/dl.h>
        !           923: #endif
        !           924: 
        !           925: #ifdef RTLD_GLOBAL
        !           926: #  define LT_GLOBAL            RTLD_GLOBAL
        !           927: #else
        !           928: #  ifdef DL_GLOBAL
        !           929: #    define LT_GLOBAL          DL_GLOBAL
        !           930: #  endif
        !           931: #endif /* !RTLD_GLOBAL */
        !           932: #ifndef LT_GLOBAL
        !           933: #  define LT_GLOBAL            0
        !           934: #endif /* !LT_GLOBAL */
        !           935: 
        !           936: /* We may have to define LT_LAZY_OR_NOW in the command line if we
        !           937:    find out it does not work in some platform. */
        !           938: #ifndef LT_LAZY_OR_NOW
        !           939: #  ifdef RTLD_LAZY
        !           940: #    define LT_LAZY_OR_NOW     RTLD_LAZY
        !           941: #  else
        !           942: #    ifdef DL_LAZY
        !           943: #      define LT_LAZY_OR_NOW   DL_LAZY
        !           944: #    endif
        !           945: #  endif /* !RTLD_LAZY */
        !           946: #endif
        !           947: #ifndef LT_LAZY_OR_NOW
        !           948: #  ifdef RTLD_NOW
        !           949: #    define LT_LAZY_OR_NOW     RTLD_NOW
        !           950: #  else
        !           951: #    ifdef DL_NOW
        !           952: #      define LT_LAZY_OR_NOW   DL_NOW
        !           953: #    endif
        !           954: #  endif /* !RTLD_NOW */
        !           955: #endif
        !           956: #ifndef LT_LAZY_OR_NOW
        !           957: #  define LT_LAZY_OR_NOW       0
        !           958: #endif /* !LT_LAZY_OR_NOW */
        !           959: 
        !           960: #if HAVE_DLERROR
        !           961: #  define DLERROR(arg) dlerror ()
        !           962: #else
        !           963: #  define DLERROR(arg) LT_DLSTRERROR (arg)
        !           964: #endif
        !           965: 
        !           966: static lt_module
        !           967: sys_dl_open (loader_data, filename)
        !           968:      lt_user_data loader_data;
        !           969:      const char *filename;
        !           970: {
        !           971:   lt_module   module   = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
        !           972: 
        !           973:   if (!module)
        !           974:     {
        !           975:       LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
        !           976:     }
        !           977: 
        !           978:   return module;
        !           979: }
        !           980: 
        !           981: static int
        !           982: sys_dl_close (loader_data, module)
        !           983:      lt_user_data loader_data;
        !           984:      lt_module module;
        !           985: {
        !           986:   int errors = 0;
        !           987: 
        !           988:   if (dlclose (module) != 0)
        !           989:     {
        !           990:       LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
        !           991:       ++errors;
        !           992:     }
        !           993: 
        !           994:   return errors;
        !           995: }
        !           996: 
        !           997: static lt_ptr
        !           998: sys_dl_sym (loader_data, module, symbol)
        !           999:      lt_user_data loader_data;
        !          1000:      lt_module module;
        !          1001:      const char *symbol;
        !          1002: {
        !          1003:   lt_ptr address = dlsym (module, symbol);
        !          1004: 
        !          1005:   if (!address)
        !          1006:     {
        !          1007:       LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
        !          1008:     }
        !          1009: 
        !          1010:   return address;
        !          1011: }
        !          1012: 
        !          1013: static struct lt_user_dlloader sys_dl =
        !          1014:   {
        !          1015: #  ifdef NEED_USCORE
        !          1016:     "_",
        !          1017: #  else
        !          1018:     0,
        !          1019: #  endif
        !          1020:     sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
        !          1021: 
        !          1022: 
        !          1023: #endif /* HAVE_LIBDL */
        !          1024: 
        !          1025: 
        !          1026: 
        !          1027: /* --- SHL_LOAD() INTERFACE LOADER --- */
        !          1028: 
        !          1029: #if HAVE_SHL_LOAD
        !          1030: 
        !          1031: /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
        !          1032: 
        !          1033: #ifdef HAVE_DL_H
        !          1034: #  include <dl.h>
        !          1035: #endif
        !          1036: 
        !          1037: /* some flags are missing on some systems, so we provide
        !          1038:  * harmless defaults.
        !          1039:  *
        !          1040:  * Mandatory:
        !          1041:  * BIND_IMMEDIATE  - Resolve symbol references when the library is loaded.
        !          1042:  * BIND_DEFERRED   - Delay code symbol resolution until actual reference.
        !          1043:  *
        !          1044:  * Optionally:
        !          1045:  * BIND_FIRST     - Place the library at the head of the symbol search
        !          1046:  *                  order.
        !          1047:  * BIND_NONFATAL   - The default BIND_IMMEDIATE behavior is to treat all
        !          1048:  *                  unsatisfied symbols as fatal.  This flag allows
        !          1049:  *                  binding of unsatisfied code symbols to be deferred
        !          1050:  *                  until use.
        !          1051:  *                  [Perl: For certain libraries, like DCE, deferred
        !          1052:  *                  binding often causes run time problems. Adding
        !          1053:  *                  BIND_NONFATAL to BIND_IMMEDIATE still allows
        !          1054:  *                  unresolved references in situations like this.]
        !          1055:  * BIND_NOSTART           - Do not call the initializer for the shared library
        !          1056:  *                  when the library is loaded, nor on a future call to
        !          1057:  *                  shl_unload().
        !          1058:  * BIND_VERBOSE           - Print verbose messages concerning possible
        !          1059:  *                  unsatisfied symbols.
        !          1060:  *
        !          1061:  * hp9000s700/hp9000s800:
        !          1062:  * BIND_RESTRICTED - Restrict symbols visible by the library to those
        !          1063:  *                  present at library load time.
        !          1064:  * DYNAMIC_PATH           - Allow the loader to dynamically search for the
        !          1065:  *                  library specified by the path argument.
        !          1066:  */
        !          1067: 
        !          1068: #ifndef        DYNAMIC_PATH
        !          1069: #  define DYNAMIC_PATH         0
        !          1070: #endif
        !          1071: #ifndef        BIND_RESTRICTED
        !          1072: #  define BIND_RESTRICTED      0
        !          1073: #endif
        !          1074: 
        !          1075: #define        LT_BIND_FLAGS   (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
        !          1076: 
        !          1077: static lt_module
        !          1078: sys_shl_open (loader_data, filename)
        !          1079:      lt_user_data loader_data;
        !          1080:      const char *filename;
        !          1081: {
        !          1082:   static shl_t self = (shl_t) 0;
        !          1083:   lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
        !          1084: 
        !          1085:   /* Since searching for a symbol against a NULL module handle will also
        !          1086:      look in everything else that was already loaded and exported with
        !          1087:      the -E compiler flag, we always cache a handle saved before any
        !          1088:      modules are loaded.  */
        !          1089:   if (!self)
        !          1090:     {
        !          1091:       lt_ptr address;
        !          1092:       shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
        !          1093:     }
        !          1094: 
        !          1095:   if (!filename)
        !          1096:     {
        !          1097:       module = self;
        !          1098:     }
        !          1099:   else
        !          1100:     {
        !          1101:       module = shl_load (filename, LT_BIND_FLAGS, 0L);
        !          1102: 
        !          1103:       if (!module)
        !          1104:        {
        !          1105:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
        !          1106:        }
        !          1107:     }
        !          1108: 
        !          1109:   return module;
        !          1110: }
        !          1111: 
        !          1112: static int
        !          1113: sys_shl_close (loader_data, module)
        !          1114:      lt_user_data loader_data;
        !          1115:      lt_module module;
        !          1116: {
        !          1117:   int errors = 0;
        !          1118: 
        !          1119:   if (module && (shl_unload ((shl_t) (module)) != 0))
        !          1120:     {
        !          1121:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
        !          1122:       ++errors;
        !          1123:     }
        !          1124: 
        !          1125:   return errors;
        !          1126: }
        !          1127: 
        !          1128: static lt_ptr
        !          1129: sys_shl_sym (loader_data, module, symbol)
        !          1130:      lt_user_data loader_data;
        !          1131:      lt_module module;
        !          1132:      const char *symbol;
        !          1133: {
        !          1134:   lt_ptr address = NULL;
        !          1135: 
        !          1136:   /* sys_shl_open should never return a NULL module handle */
        !          1137:   if (module == (lt_module) 0)
        !          1138:   {
        !          1139:     LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
        !          1140:   }
        !          1141:   else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
        !          1142:     {
        !          1143:       if (!address)
        !          1144:        {
        !          1145:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
        !          1146:        }
        !          1147:     }
        !          1148: 
        !          1149:   return address;
        !          1150: }
        !          1151: 
        !          1152: static struct lt_user_dlloader sys_shl = {
        !          1153:   0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
        !          1154: };
        !          1155: 
        !          1156: #endif /* HAVE_SHL_LOAD */
        !          1157: 
        !          1158: 
        !          1159: 
        !          1160: 
        !          1161: /* --- LOADLIBRARY() INTERFACE LOADER --- */
        !          1162: 
        !          1163: #ifdef __WINDOWS__
        !          1164: 
        !          1165: /* dynamic linking for Win32 */
        !          1166: 
        !          1167: #include <windows.h>
        !          1168: 
        !          1169: /* Forward declaration; required to implement handle search below. */
        !          1170: static lt_dlhandle handles;
        !          1171: 
        !          1172: static lt_module
        !          1173: sys_wll_open (loader_data, filename)
        !          1174:      lt_user_data loader_data;
        !          1175:      const char *filename;
        !          1176: {
        !          1177:   lt_dlhandle  cur;
        !          1178:   lt_module    module     = NULL;
        !          1179:   const char   *errormsg   = NULL;
        !          1180:   char        *searchname = NULL;
        !          1181:   char        *ext;
        !          1182:   char         self_name_buf[MAX_PATH];
        !          1183: 
        !          1184:   if (!filename)
        !          1185:     {
        !          1186:       /* Get the name of main module */
        !          1187:       *self_name_buf = '\0';
        !          1188:       GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
        !          1189:       filename = ext = self_name_buf;
        !          1190:     }
        !          1191:   else
        !          1192:     {
        !          1193:       ext = strrchr (filename, '.');
        !          1194:     }
        !          1195: 
        !          1196:   if (ext)
        !          1197:     {
        !          1198:       /* FILENAME already has an extension. */
        !          1199:       searchname = lt_estrdup (filename);
        !          1200:     }
        !          1201:   else
        !          1202:     {
        !          1203:       /* Append a `.' to stop Windows from adding an
        !          1204:         implicit `.dll' extension. */
        !          1205:       searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
        !          1206:       if (searchname)
        !          1207:        sprintf (searchname, "%s.", filename);
        !          1208:     }
        !          1209:   if (!searchname)
        !          1210:     return 0;
        !          1211: 
        !          1212: #if __CYGWIN__
        !          1213:   {
        !          1214:     char wpath[MAX_PATH];
        !          1215:     cygwin_conv_to_full_win32_path(searchname, wpath);
        !          1216:     module = LoadLibrary(wpath);
        !          1217:   }
        !          1218: #else
        !          1219:   module = LoadLibrary (searchname);
        !          1220: #endif
        !          1221:   LT_DLFREE (searchname);
        !          1222: 
        !          1223:   /* libltdl expects this function to fail if it is unable
        !          1224:      to physically load the library.  Sadly, LoadLibrary
        !          1225:      will search the loaded libraries for a match and return
        !          1226:      one of them if the path search load fails.
        !          1227: 
        !          1228:      We check whether LoadLibrary is returning a handle to
        !          1229:      an already loaded module, and simulate failure if we
        !          1230:      find one. */
        !          1231:   LT_DLMUTEX_LOCK ();
        !          1232:   cur = handles;
        !          1233:   while (cur)
        !          1234:     {
        !          1235:       if (!cur->module)
        !          1236:        {
        !          1237:          cur = NULL;
        !          1238:          break;
        !          1239:        }
        !          1240: 
        !          1241:       if (cur->module == module)
        !          1242:        {
        !          1243:          break;
        !          1244:        }
        !          1245: 
        !          1246:       cur = cur->next;
        !          1247:   }
        !          1248:   LT_DLMUTEX_UNLOCK ();
        !          1249: 
        !          1250:   if (cur || !module)
        !          1251:     {
        !          1252:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
        !          1253:       module = NULL;
        !          1254:     }
        !          1255: 
        !          1256:   return module;
        !          1257: }
        !          1258: 
        !          1259: static int
        !          1260: sys_wll_close (loader_data, module)
        !          1261:      lt_user_data loader_data;
        !          1262:      lt_module module;
        !          1263: {
        !          1264:   int        errors   = 0;
        !          1265: 
        !          1266:   if (FreeLibrary(module) == 0)
        !          1267:     {
        !          1268:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
        !          1269:       ++errors;
        !          1270:     }
        !          1271: 
        !          1272:   return errors;
        !          1273: }
        !          1274: 
        !          1275: static lt_ptr
        !          1276: sys_wll_sym (loader_data, module, symbol)
        !          1277:      lt_user_data loader_data;
        !          1278:      lt_module module;
        !          1279:      const char *symbol;
        !          1280: {
        !          1281:   lt_ptr      address  = GetProcAddress (module, symbol);
        !          1282: 
        !          1283:   if (!address)
        !          1284:     {
        !          1285:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
        !          1286:     }
        !          1287: 
        !          1288:   return address;
        !          1289: }
        !          1290: 
        !          1291: static struct lt_user_dlloader sys_wll = {
        !          1292:   0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
        !          1293: };
        !          1294: 
        !          1295: #endif /* __WINDOWS__ */
        !          1296: 
        !          1297: 
        !          1298: 
        !          1299: 
        !          1300: /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
        !          1301: 
        !          1302: 
        !          1303: #ifdef __BEOS__
        !          1304: 
        !          1305: /* dynamic linking for BeOS */
        !          1306: 
        !          1307: #include <kernel/image.h>
        !          1308: 
        !          1309: static lt_module
        !          1310: sys_bedl_open (loader_data, filename)
        !          1311:      lt_user_data loader_data;
        !          1312:      const char *filename;
        !          1313: {
        !          1314:   image_id image = 0;
        !          1315: 
        !          1316:   if (filename)
        !          1317:     {
        !          1318:       image = load_add_on (filename);
        !          1319:     }
        !          1320:   else
        !          1321:     {
        !          1322:       image_info info;
        !          1323:       int32 cookie = 0;
        !          1324:       if (get_next_image_info (0, &cookie, &info) == B_OK)
        !          1325:        image = load_add_on (info.name);
        !          1326:     }
        !          1327: 
        !          1328:   if (image <= 0)
        !          1329:     {
        !          1330:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
        !          1331:       image = 0;
        !          1332:     }
        !          1333: 
        !          1334:   return (lt_module) image;
        !          1335: }
        !          1336: 
        !          1337: static int
        !          1338: sys_bedl_close (loader_data, module)
        !          1339:      lt_user_data loader_data;
        !          1340:      lt_module module;
        !          1341: {
        !          1342:   int errors = 0;
        !          1343: 
        !          1344:   if (unload_add_on ((image_id) module) != B_OK)
        !          1345:     {
        !          1346:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
        !          1347:       ++errors;
        !          1348:     }
        !          1349: 
        !          1350:   return errors;
        !          1351: }
        !          1352: 
        !          1353: static lt_ptr
        !          1354: sys_bedl_sym (loader_data, module, symbol)
        !          1355:      lt_user_data loader_data;
        !          1356:      lt_module module;
        !          1357:      const char *symbol;
        !          1358: {
        !          1359:   lt_ptr address = NULL;
        !          1360:   image_id image = (image_id) module;
        !          1361: 
        !          1362:   if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
        !          1363:     {
        !          1364:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
        !          1365:       address = NULL;
        !          1366:     }
        !          1367: 
        !          1368:   return address;
        !          1369: }
        !          1370: 
        !          1371: static struct lt_user_dlloader sys_bedl = {
        !          1372:   0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
        !          1373: };
        !          1374: 
        !          1375: #endif /* __BEOS__ */
        !          1376: 
        !          1377: 
        !          1378: 
        !          1379: 
        !          1380: /* --- DLD_LINK() INTERFACE LOADER --- */
        !          1381: 
        !          1382: 
        !          1383: #if HAVE_DLD
        !          1384: 
        !          1385: /* dynamic linking with dld */
        !          1386: 
        !          1387: #if HAVE_DLD_H
        !          1388: #include <dld.h>
        !          1389: #endif
        !          1390: 
        !          1391: static lt_module
        !          1392: sys_dld_open (loader_data, filename)
        !          1393:      lt_user_data loader_data;
        !          1394:      const char *filename;
        !          1395: {
        !          1396:   lt_module module = strdup (filename);
        !          1397: 
        !          1398:   if (dld_link (filename) != 0)
        !          1399:     {
        !          1400:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
        !          1401:       LT_DLFREE (module);
        !          1402:       module = NULL;
        !          1403:     }
        !          1404: 
        !          1405:   return module;
        !          1406: }
        !          1407: 
        !          1408: static int
        !          1409: sys_dld_close (loader_data, module)
        !          1410:      lt_user_data loader_data;
        !          1411:      lt_module module;
        !          1412: {
        !          1413:   int errors = 0;
        !          1414: 
        !          1415:   if (dld_unlink_by_file ((char*)(module), 1) != 0)
        !          1416:     {
        !          1417:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
        !          1418:       ++errors;
        !          1419:     }
        !          1420:   else
        !          1421:     {
        !          1422:       LT_DLFREE (module);
        !          1423:     }
        !          1424: 
        !          1425:   return errors;
        !          1426: }
        !          1427: 
        !          1428: static lt_ptr
        !          1429: sys_dld_sym (loader_data, module, symbol)
        !          1430:      lt_user_data loader_data;
        !          1431:      lt_module module;
        !          1432:      const char *symbol;
        !          1433: {
        !          1434:   lt_ptr address = dld_get_func (symbol);
        !          1435: 
        !          1436:   if (!address)
        !          1437:     {
        !          1438:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
        !          1439:     }
        !          1440: 
        !          1441:   return address;
        !          1442: }
        !          1443: 
        !          1444: static struct lt_user_dlloader sys_dld = {
        !          1445:   0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
        !          1446: };
        !          1447: 
        !          1448: #endif /* HAVE_DLD */
        !          1449: 
        !          1450: 
        !          1451: 
        !          1452: 
        !          1453: /* --- DLPREOPEN() INTERFACE LOADER --- */
        !          1454: 
        !          1455: 
        !          1456: /* emulate dynamic linking using preloaded_symbols */
        !          1457: 
        !          1458: typedef struct lt_dlsymlists_t
        !          1459: {
        !          1460:   struct lt_dlsymlists_t       *next;
        !          1461:   const lt_dlsymlist          *syms;
        !          1462: } lt_dlsymlists_t;
        !          1463: 
        !          1464: static const lt_dlsymlist     *default_preloaded_symbols       = NULL;
        !          1465: static lt_dlsymlists_t        *preloaded_symbols               = NULL;
        !          1466: 
        !          1467: static int
        !          1468: presym_init (loader_data)
        !          1469:      lt_user_data loader_data;
        !          1470: {
        !          1471:   int errors = 0;
        !          1472: 
        !          1473:   LT_DLMUTEX_LOCK ();
        !          1474: 
        !          1475:   preloaded_symbols = NULL;
        !          1476:   if (default_preloaded_symbols)
        !          1477:     {
        !          1478:       errors = lt_dlpreload (default_preloaded_symbols);
        !          1479:     }
        !          1480: 
        !          1481:   LT_DLMUTEX_UNLOCK ();
        !          1482: 
        !          1483:   return errors;
        !          1484: }
        !          1485: 
        !          1486: static int
        !          1487: presym_free_symlists ()
        !          1488: {
        !          1489:   lt_dlsymlists_t *lists;
        !          1490: 
        !          1491:   LT_DLMUTEX_LOCK ();
        !          1492: 
        !          1493:   lists = preloaded_symbols;
        !          1494:   while (lists)
        !          1495:     {
        !          1496:       lt_dlsymlists_t  *tmp = lists;
        !          1497: 
        !          1498:       lists = lists->next;
        !          1499:       LT_DLFREE (tmp);
        !          1500:     }
        !          1501:   preloaded_symbols = NULL;
        !          1502: 
        !          1503:   LT_DLMUTEX_UNLOCK ();
        !          1504: 
        !          1505:   return 0;
        !          1506: }
        !          1507: 
        !          1508: static int
        !          1509: presym_exit (loader_data)
        !          1510:      lt_user_data loader_data;
        !          1511: {
        !          1512:   presym_free_symlists ();
        !          1513:   return 0;
        !          1514: }
        !          1515: 
        !          1516: static int
        !          1517: presym_add_symlist (preloaded)
        !          1518:      const lt_dlsymlist *preloaded;
        !          1519: {
        !          1520:   lt_dlsymlists_t *tmp;
        !          1521:   lt_dlsymlists_t *lists;
        !          1522:   int             errors   = 0;
        !          1523: 
        !          1524:   LT_DLMUTEX_LOCK ();
        !          1525: 
        !          1526:   lists = preloaded_symbols;
        !          1527:   while (lists)
        !          1528:     {
        !          1529:       if (lists->syms == preloaded)
        !          1530:        {
        !          1531:          goto done;
        !          1532:        }
        !          1533:       lists = lists->next;
        !          1534:     }
        !          1535: 
        !          1536:   tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
        !          1537:   if (tmp)
        !          1538:     {
        !          1539:       memset (tmp, 0, sizeof(lt_dlsymlists_t));
        !          1540:       tmp->syms = preloaded;
        !          1541:       tmp->next = preloaded_symbols;
        !          1542:       preloaded_symbols = tmp;
        !          1543:     }
        !          1544:   else
        !          1545:     {
        !          1546:       ++errors;
        !          1547:     }
        !          1548: 
        !          1549:  done:
        !          1550:   LT_DLMUTEX_UNLOCK ();
        !          1551:   return errors;
        !          1552: }
        !          1553: 
        !          1554: static lt_module
        !          1555: presym_open (loader_data, filename)
        !          1556:      lt_user_data loader_data;
        !          1557:      const char *filename;
        !          1558: {
        !          1559:   lt_dlsymlists_t *lists;
        !          1560:   lt_module       module = (lt_module) 0;
        !          1561: 
        !          1562:   LT_DLMUTEX_LOCK ();
        !          1563:   lists = preloaded_symbols;
        !          1564: 
        !          1565:   if (!lists)
        !          1566:     {
        !          1567:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
        !          1568:       goto done;
        !          1569:     }
        !          1570: 
        !          1571:   /* Can't use NULL as the reflective symbol header, as NULL is
        !          1572:      used to mark the end of the entire symbol list.  Self-dlpreopened
        !          1573:      symbols follow this magic number, chosen to be an unlikely
        !          1574:      clash with a real module name.  */
        !          1575:   if (!filename)
        !          1576:     {
        !          1577:       filename = "@PROGRAM@";
        !          1578:     }
        !          1579: 
        !          1580:   while (lists)
        !          1581:     {
        !          1582:       const lt_dlsymlist *syms = lists->syms;
        !          1583: 
        !          1584:       while (syms->name)
        !          1585:        {
        !          1586:          if (!syms->address && strcmp(syms->name, filename) == 0)
        !          1587:            {
        !          1588:              module = (lt_module) syms;
        !          1589:              goto done;
        !          1590:            }
        !          1591:          ++syms;
        !          1592:        }
        !          1593: 
        !          1594:       lists = lists->next;
        !          1595:     }
        !          1596: 
        !          1597:   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
        !          1598: 
        !          1599:  done:
        !          1600:   LT_DLMUTEX_UNLOCK ();
        !          1601:   return module;
        !          1602: }
        !          1603: 
        !          1604: static int
        !          1605: presym_close (loader_data, module)
        !          1606:      lt_user_data loader_data;
        !          1607:      lt_module module;
        !          1608: {
        !          1609:   /* Just to silence gcc -Wall */
        !          1610:   module = NULL;
        !          1611:   return 0;
        !          1612: }
        !          1613: 
        !          1614: static lt_ptr
        !          1615: presym_sym (loader_data, module, symbol)
        !          1616:      lt_user_data loader_data;
        !          1617:      lt_module module;
        !          1618:      const char *symbol;
        !          1619: {
        !          1620:   lt_dlsymlist *syms = (lt_dlsymlist*) module;
        !          1621: 
        !          1622:   ++syms;
        !          1623:   while (syms->address)
        !          1624:     {
        !          1625:       if (strcmp(syms->name, symbol) == 0)
        !          1626:        {
        !          1627:          return syms->address;
        !          1628:        }
        !          1629: 
        !          1630:     ++syms;
        !          1631:   }
        !          1632: 
        !          1633:   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
        !          1634: 
        !          1635:   return 0;
        !          1636: }
        !          1637: 
        !          1638: static struct lt_user_dlloader presym = {
        !          1639:   0, presym_open, presym_close, presym_sym, presym_exit, 0
        !          1640: };
        !          1641: 
        !          1642: 
        !          1643: 
        !          1644: 
        !          1645: 
        !          1646: /* --- DYNAMIC MODULE LOADING --- */
        !          1647: 
        !          1648: 
        !          1649: /* The type of a function used at each iteration of  foreach_dirinpath().  */
        !          1650: typedef int    foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
        !          1651:                                                 lt_ptr data2));
        !          1652: 
        !          1653: static int     foreach_dirinpath     LT_PARAMS((const char *search_path,
        !          1654:                                                 const char *base_name,
        !          1655:                                                 foreach_callback_func *func,
        !          1656:                                                 lt_ptr data1, lt_ptr data2));
        !          1657: 
        !          1658: static int     find_file_callback    LT_PARAMS((char *filename, lt_ptr data,
        !          1659:                                                 lt_ptr ignored));
        !          1660: static int     find_handle_callback  LT_PARAMS((char *filename, lt_ptr data,
        !          1661:                                                 lt_ptr ignored));
        !          1662: static int     foreachfile_callback  LT_PARAMS((char *filename, lt_ptr data1,
        !          1663:                                                 lt_ptr data2));
        !          1664: 
        !          1665: 
        !          1666: static int     canonicalize_path     LT_PARAMS((const char *path,
        !          1667:                                                 char **pcanonical));
        !          1668: static int     argzize_path          LT_PARAMS((const char *path,
        !          1669:                                                 char **pargz,
        !          1670:                                                 size_t *pargz_len));
        !          1671: static FILE   *find_file             LT_PARAMS((const char *search_path,
        !          1672:                                                 const char *base_name,
        !          1673:                                                 char **pdir));
        !          1674: static lt_dlhandle *find_handle      LT_PARAMS((const char *search_path,
        !          1675:                                                 const char *base_name,
        !          1676:                                                 lt_dlhandle *handle));
        !          1677: static int     find_module           LT_PARAMS((lt_dlhandle *handle,
        !          1678:                                                 const char *dir,
        !          1679:                                                 const char *libdir,
        !          1680:                                                 const char *dlname,
        !          1681:                                                 const char *old_name,
        !          1682:                                                 int installed));
        !          1683: static int     free_vars             LT_PARAMS((char *dlname, char *oldname,
        !          1684:                                                 char *libdir, char *deplibs));
        !          1685: static int     load_deplibs          LT_PARAMS((lt_dlhandle handle,
        !          1686:                                                 char *deplibs));
        !          1687: static int     trim                  LT_PARAMS((char **dest,
        !          1688:                                                 const char *str));
        !          1689: static int     try_dlopen            LT_PARAMS((lt_dlhandle *handle,
        !          1690:                                                 const char *filename));
        !          1691: static int     tryall_dlopen         LT_PARAMS((lt_dlhandle *handle,
        !          1692:                                                 const char *filename));
        !          1693: static int     unload_deplibs        LT_PARAMS((lt_dlhandle handle));
        !          1694: static int     lt_argz_insert        LT_PARAMS((char **pargz,
        !          1695:                                                 size_t *pargz_len,
        !          1696:                                                 char *before,
        !          1697:                                                 const char *entry));
        !          1698: static int     lt_argz_insertinorder LT_PARAMS((char **pargz,
        !          1699:                                                 size_t *pargz_len,
        !          1700:                                                 const char *entry));
        !          1701: static int     lt_argz_insertdir     LT_PARAMS((char **pargz,
        !          1702:                                                 size_t *pargz_len,
        !          1703:                                                 const char *dirnam,
        !          1704:                                                 struct dirent *dp));
        !          1705: static int     lt_dlpath_insertdir   LT_PARAMS((char **ppath,
        !          1706:                                                 char *before,
        !          1707:                                                 const char *dir));
        !          1708: static int     list_files_by_dir     LT_PARAMS((const char *dirnam,
        !          1709:                                                 char **pargz,
        !          1710:                                                 size_t *pargz_len));
        !          1711: static int     file_not_found        LT_PARAMS((void));
        !          1712: 
        !          1713: static char           *user_search_path= NULL;
        !          1714: static lt_dlloader    *loaders         = NULL;
        !          1715: static lt_dlhandle     handles         = NULL;
        !          1716: static int             initialized     = 0;
        !          1717: 
        !          1718: /* Initialize libltdl. */
        !          1719: int
        !          1720: lt_dlinit ()
        !          1721: {
        !          1722:   int        errors   = 0;
        !          1723: 
        !          1724:   LT_DLMUTEX_LOCK ();
        !          1725: 
        !          1726:   /* Initialize only at first call. */
        !          1727:   if (++initialized == 1)
        !          1728:     {
        !          1729:       handles = NULL;
        !          1730:       user_search_path = NULL; /* empty search path */
        !          1731: 
        !          1732: #if HAVE_LIBDL && !defined(__CYGWIN__)
        !          1733:       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
        !          1734: #endif
        !          1735: #if HAVE_SHL_LOAD
        !          1736:       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
        !          1737: #endif
        !          1738: #ifdef __WINDOWS__
        !          1739:       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
        !          1740: #endif
        !          1741: #ifdef __BEOS__
        !          1742:       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
        !          1743: #endif
        !          1744: #if HAVE_DLD
        !          1745:       errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
        !          1746: #endif
        !          1747:       errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
        !          1748: 
        !          1749:       if (presym_init (presym.dlloader_data))
        !          1750:        {
        !          1751:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
        !          1752:          ++errors;
        !          1753:        }
        !          1754:       else if (errors != 0)
        !          1755:        {
        !          1756:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
        !          1757:          ++errors;
        !          1758:        }
        !          1759:     }
        !          1760: 
        !          1761:   LT_DLMUTEX_UNLOCK ();
        !          1762: 
        !          1763:   return errors;
        !          1764: }
        !          1765: 
        !          1766: int
        !          1767: lt_dlpreload (preloaded)
        !          1768:      const lt_dlsymlist *preloaded;
        !          1769: {
        !          1770:   int errors = 0;
        !          1771: 
        !          1772:   if (preloaded)
        !          1773:     {
        !          1774:       errors = presym_add_symlist (preloaded);
        !          1775:     }
        !          1776:   else
        !          1777:     {
        !          1778:       presym_free_symlists();
        !          1779: 
        !          1780:       LT_DLMUTEX_LOCK ();
        !          1781:       if (default_preloaded_symbols)
        !          1782:        {
        !          1783:          errors = lt_dlpreload (default_preloaded_symbols);
        !          1784:        }
        !          1785:       LT_DLMUTEX_UNLOCK ();
        !          1786:     }
        !          1787: 
        !          1788:   return errors;
        !          1789: }
        !          1790: 
        !          1791: int
        !          1792: lt_dlpreload_default (preloaded)
        !          1793:      const lt_dlsymlist *preloaded;
        !          1794: {
        !          1795:   LT_DLMUTEX_LOCK ();
        !          1796:   default_preloaded_symbols = preloaded;
        !          1797:   LT_DLMUTEX_UNLOCK ();
        !          1798:   return 0;
        !          1799: }
        !          1800: 
        !          1801: int
        !          1802: lt_dlexit ()
        !          1803: {
        !          1804:   /* shut down libltdl */
        !          1805:   lt_dlloader *loader;
        !          1806:   int         errors   = 0;
        !          1807: 
        !          1808:   LT_DLMUTEX_LOCK ();
        !          1809:   loader = loaders;
        !          1810: 
        !          1811:   if (!initialized)
        !          1812:     {
        !          1813:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
        !          1814:       ++errors;
        !          1815:       goto done;
        !          1816:     }
        !          1817: 
        !          1818:   /* shut down only at last call. */
        !          1819:   if (--initialized == 0)
        !          1820:     {
        !          1821:       int      level;
        !          1822: 
        !          1823:       while (handles && LT_DLIS_RESIDENT (handles))
        !          1824:        {
        !          1825:          handles = handles->next;
        !          1826:        }
        !          1827: 
        !          1828:       /* close all modules */
        !          1829:       for (level = 1; handles; ++level)
        !          1830:        {
        !          1831:          lt_dlhandle cur = handles;
        !          1832:          int saw_nonresident = 0;
        !          1833: 
        !          1834:          while (cur)
        !          1835:            {
        !          1836:              lt_dlhandle tmp = cur;
        !          1837:              cur = cur->next;
        !          1838:              if (!LT_DLIS_RESIDENT (tmp))
        !          1839:                saw_nonresident = 1;
        !          1840:              if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
        !          1841:                {
        !          1842:                  if (lt_dlclose (tmp))
        !          1843:                    {
        !          1844:                      ++errors;
        !          1845:                    }
        !          1846:                }
        !          1847:            }
        !          1848:          /* done if only resident modules are left */
        !          1849:          if (!saw_nonresident)
        !          1850:            break;
        !          1851:        }
        !          1852: 
        !          1853:       /* close all loaders */
        !          1854:       while (loader)
        !          1855:        {
        !          1856:          lt_dlloader *next = loader->next;
        !          1857:          lt_user_data data = loader->dlloader_data;
        !          1858:          if (loader->dlloader_exit && loader->dlloader_exit (data))
        !          1859:            {
        !          1860:              ++errors;
        !          1861:            }
        !          1862: 
        !          1863:          LT_DLMEM_REASSIGN (loader, next);
        !          1864:        }
        !          1865:       loaders = NULL;
        !          1866:     }
        !          1867: 
        !          1868:  done:
        !          1869:   LT_DLMUTEX_UNLOCK ();
        !          1870:   return errors;
        !          1871: }
        !          1872: 
        !          1873: static int
        !          1874: tryall_dlopen (handle, filename)
        !          1875:      lt_dlhandle *handle;
        !          1876:      const char *filename;
        !          1877: {
        !          1878:   lt_dlhandle   cur;
        !          1879:   lt_dlloader   *loader;
        !          1880:   const char   *saved_error;
        !          1881:   int           errors         = 0;
        !          1882: 
        !          1883:   LT_DLMUTEX_GETERROR (saved_error);
        !          1884:   LT_DLMUTEX_LOCK ();
        !          1885: 
        !          1886:   cur   = handles;
        !          1887:   loader = loaders;
        !          1888: 
        !          1889:   /* check whether the module was already opened */
        !          1890:   while (cur)
        !          1891:     {
        !          1892:       /* try to dlopen the program itself? */
        !          1893:       if (!cur->info.filename && !filename)
        !          1894:        {
        !          1895:          break;
        !          1896:        }
        !          1897: 
        !          1898:       if (cur->info.filename && filename
        !          1899:          && strcmp (cur->info.filename, filename) == 0)
        !          1900:        {
        !          1901:          break;
        !          1902:        }
        !          1903: 
        !          1904:       cur = cur->next;
        !          1905:     }
        !          1906: 
        !          1907:   if (cur)
        !          1908:     {
        !          1909:       ++cur->info.ref_count;
        !          1910:       *handle = cur;
        !          1911:       goto done;
        !          1912:     }
        !          1913: 
        !          1914:   cur = *handle;
        !          1915:   if (filename)
        !          1916:     {
        !          1917:       cur->info.filename = lt_estrdup (filename);
        !          1918:       if (!cur->info.filename)
        !          1919:        {
        !          1920:          ++errors;
        !          1921:          goto done;
        !          1922:        }
        !          1923:     }
        !          1924:   else
        !          1925:     {
        !          1926:       cur->info.filename = NULL;
        !          1927:     }
        !          1928: 
        !          1929:   while (loader)
        !          1930:     {
        !          1931:       lt_user_data data = loader->dlloader_data;
        !          1932: 
        !          1933:       cur->module = loader->module_open (data, filename);
        !          1934: 
        !          1935:       if (cur->module != NULL)
        !          1936:        {
        !          1937:          break;
        !          1938:        }
        !          1939:       loader = loader->next;
        !          1940:     }
        !          1941: 
        !          1942:   if (!loader)
        !          1943:     {
        !          1944:       LT_DLFREE (cur->info.filename);
        !          1945:       ++errors;
        !          1946:       goto done;
        !          1947:     }
        !          1948: 
        !          1949:   cur->loader  = loader;
        !          1950:   LT_DLMUTEX_SETERROR (saved_error);
        !          1951: 
        !          1952:  done:
        !          1953:   LT_DLMUTEX_UNLOCK ();
        !          1954: 
        !          1955:   return errors;
        !          1956: }
        !          1957: 
        !          1958: static int
        !          1959: tryall_dlopen_module (handle, prefix, dirname, dlname)
        !          1960:      lt_dlhandle *handle;
        !          1961:      const char *prefix;
        !          1962:      const char *dirname;
        !          1963:      const char *dlname;
        !          1964: {
        !          1965:   int      error       = 0;
        !          1966:   char     *filename   = NULL;
        !          1967:   size_t   filename_len        = 0;
        !          1968:   size_t   dirname_len = LT_STRLEN (dirname);
        !          1969: 
        !          1970:   assert (handle);
        !          1971:   assert (dirname);
        !          1972:   assert (dlname);
        !          1973: #ifdef LT_DIRSEP_CHAR
        !          1974:   /* Only canonicalized names (i.e. with DIRSEP chars already converted)
        !          1975:      should make it into this function:  */
        !          1976:   assert (strchr (dirname, LT_DIRSEP_CHAR) == NULL);
        !          1977: #endif
        !          1978: 
        !          1979:   if (dirname[dirname_len -1] == '/')
        !          1980:     --dirname_len;
        !          1981:   filename_len = dirname_len + 1 + LT_STRLEN (dlname);
        !          1982: 
        !          1983:   /* Allocate memory, and combine DIRNAME and MODULENAME into it.
        !          1984:      The PREFIX (if any) is handled below.  */
        !          1985:   filename  = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
        !          1986:   if (!filename)
        !          1987:     return 1;
        !          1988: 
        !          1989:   sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
        !          1990: 
        !          1991:   /* Now that we have combined DIRNAME and MODULENAME, if there is
        !          1992:      also a PREFIX to contend with, simply recurse with the arguments
        !          1993:      shuffled.  Otherwise, attempt to open FILENAME as a module.  */
        !          1994:   if (prefix)
        !          1995:     {
        !          1996:       error += tryall_dlopen_module (handle,
        !          1997:                                     (const char *) 0, prefix, filename);
        !          1998:     }
        !          1999:   else if (tryall_dlopen (handle, filename) != 0)
        !          2000:     {
        !          2001:       ++error;
        !          2002:     }
        !          2003: 
        !          2004:   LT_DLFREE (filename);
        !          2005:   return error;
        !          2006: }
        !          2007: 
        !          2008: static int
        !          2009: find_module (handle, dir, libdir, dlname, old_name, installed)
        !          2010:      lt_dlhandle *handle;
        !          2011:      const char *dir;
        !          2012:      const char *libdir;
        !          2013:      const char *dlname;
        !          2014:      const char *old_name;
        !          2015:      int installed;
        !          2016: {
        !          2017:   /* Try to open the old library first; if it was dlpreopened,
        !          2018:      we want the preopened version of it, even if a dlopenable
        !          2019:      module is available.  */
        !          2020:   if (old_name && tryall_dlopen (handle, old_name) == 0)
        !          2021:     {
        !          2022:       return 0;
        !          2023:     }
        !          2024: 
        !          2025:   /* Try to open the dynamic library.  */
        !          2026:   if (dlname)
        !          2027:     {
        !          2028:       /* try to open the installed module */
        !          2029:       if (installed && libdir)
        !          2030:        {
        !          2031:          if (tryall_dlopen_module (handle,
        !          2032:                                    (const char *) 0, libdir, dlname) == 0)
        !          2033:            return 0;
        !          2034:        }
        !          2035: 
        !          2036:       /* try to open the not-installed module */
        !          2037:       if (!installed)
        !          2038:        {
        !          2039:          if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
        !          2040:            return 0;
        !          2041:        }
        !          2042: 
        !          2043:       /* maybe it was moved to another directory */
        !          2044:       {
        !          2045:          if (tryall_dlopen_module (handle,
        !          2046:                                    (const char *) 0, dir, dlname) == 0)
        !          2047:            return 0;
        !          2048:       }
        !          2049:     }
        !          2050: 
        !          2051:   return 1;
        !          2052: }
        !          2053: 
        !          2054: 
        !          2055: static int
        !          2056: canonicalize_path (path, pcanonical)
        !          2057:      const char *path;
        !          2058:      char **pcanonical;
        !          2059: {
        !          2060:   char *canonical = NULL;
        !          2061: 
        !          2062:   assert (path && *path);
        !          2063:   assert (pcanonical);
        !          2064: 
        !          2065:   canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
        !          2066:   if (!canonical)
        !          2067:     return 1;
        !          2068: 
        !          2069:   {
        !          2070:     size_t dest = 0;
        !          2071:     size_t src;
        !          2072:     for (src = 0; path[src] != LT_EOS_CHAR; ++src)
        !          2073:       {
        !          2074:        /* Path separators are not copied to the beginning or end of
        !          2075:           the destination, or if another separator would follow
        !          2076:           immediately.  */
        !          2077:        if (path[src] == LT_PATHSEP_CHAR)
        !          2078:          {
        !          2079:            if ((dest == 0)
        !          2080:                || (path[1+ src] == LT_PATHSEP_CHAR)
        !          2081:                || (path[1+ src] == LT_EOS_CHAR))
        !          2082:              continue;
        !          2083:          }
        !          2084: 
        !          2085:        /* Anything other than a directory separator is copied verbatim.  */
        !          2086:        if ((path[src] != '/')
        !          2087: #ifdef LT_DIRSEP_CHAR
        !          2088:            && (path[src] != LT_DIRSEP_CHAR)
        !          2089: #endif
        !          2090:            )
        !          2091:          {
        !          2092:            canonical[dest++] = path[src];
        !          2093:          }
        !          2094:        /* Directory separators are converted and copied only if they are
        !          2095:           not at the end of a path -- i.e. before a path separator or
        !          2096:           NULL terminator.  */
        !          2097:        else if ((path[1+ src] != LT_PATHSEP_CHAR)
        !          2098:                 && (path[1+ src] != LT_EOS_CHAR)
        !          2099: #ifdef LT_DIRSEP_CHAR
        !          2100:                 && (path[1+ src] != LT_DIRSEP_CHAR)
        !          2101: #endif
        !          2102:                 && (path[1+ src] != '/'))
        !          2103:          {
        !          2104:            canonical[dest++] = '/';
        !          2105:          }
        !          2106:       }
        !          2107: 
        !          2108:     /* Add an end-of-string marker at the end.  */
        !          2109:     canonical[dest] = LT_EOS_CHAR;
        !          2110:   }
        !          2111: 
        !          2112:   /* Assign new value.  */
        !          2113:   *pcanonical = canonical;
        !          2114: 
        !          2115:   return 0;
        !          2116: }
        !          2117: 
        !          2118: static int
        !          2119: argzize_path (path, pargz, pargz_len)
        !          2120:      const char *path;
        !          2121:      char **pargz;
        !          2122:      size_t *pargz_len;
        !          2123: {
        !          2124:   error_t error;
        !          2125: 
        !          2126:   assert (path);
        !          2127:   assert (pargz);
        !          2128:   assert (pargz_len);
        !          2129: 
        !          2130:   if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
        !          2131:     {
        !          2132:       switch (error)
        !          2133:        {
        !          2134:        case ENOMEM:
        !          2135:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
        !          2136:          break;
        !          2137:        default:
        !          2138:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
        !          2139:          break;
        !          2140:        }
        !          2141: 
        !          2142:       return 1;
        !          2143:     }
        !          2144: 
        !          2145:   return 0;
        !          2146: }
        !          2147: 
        !          2148: /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
        !          2149:    of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
        !          2150:    non-zero or all elements are exhausted.  If BASE_NAME is non-NULL,
        !          2151:    it is appended to each SEARCH_PATH element before FUNC is called.  */
        !          2152: static int
        !          2153: foreach_dirinpath (search_path, base_name, func, data1, data2)
        !          2154:      const char *search_path;
        !          2155:      const char *base_name;
        !          2156:      foreach_callback_func *func;
        !          2157:      lt_ptr data1;
        !          2158:      lt_ptr data2;
        !          2159: {
        !          2160:   int   result         = 0;
        !          2161:   int   filenamesize   = 0;
        !          2162:   size_t lenbase       = LT_STRLEN (base_name);
        !          2163:   size_t argz_len      = 0;
        !          2164:   char *argz           = NULL;
        !          2165:   char *filename       = NULL;
        !          2166:   char *canonical      = NULL;
        !          2167: 
        !          2168:   LT_DLMUTEX_LOCK ();
        !          2169: 
        !          2170:   if (!search_path || !*search_path)
        !          2171:     {
        !          2172:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
        !          2173:       goto cleanup;
        !          2174:     }
        !          2175: 
        !          2176:   if (canonicalize_path (search_path, &canonical) != 0)
        !          2177:     goto cleanup;
        !          2178: 
        !          2179:   if (argzize_path (canonical, &argz, &argz_len) != 0)
        !          2180:     goto cleanup;
        !          2181: 
        !          2182:   {
        !          2183:     char *dir_name = NULL;
        !          2184:     while ((dir_name = argz_next (argz, argz_len, dir_name)))
        !          2185:       {
        !          2186:        size_t lendir = LT_STRLEN (dir_name);
        !          2187: 
        !          2188:        if (lendir +1 +lenbase >= filenamesize)
        !          2189:        {
        !          2190:          LT_DLFREE (filename);
        !          2191:          filenamesize  = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
        !          2192:          filename      = LT_EMALLOC (char, filenamesize);
        !          2193:          if (!filename)
        !          2194:            goto cleanup;
        !          2195:        }
        !          2196: 
        !          2197:        assert (filenamesize > lendir);
        !          2198:        strcpy (filename, dir_name);
        !          2199: 
        !          2200:        if (base_name && *base_name)
        !          2201:          {
        !          2202:            if (filename[lendir -1] != '/')
        !          2203:              filename[lendir++] = '/';
        !          2204:            strcpy (filename +lendir, base_name);
        !          2205:          }
        !          2206: 
        !          2207:        if ((result = (*func) (filename, data1, data2)))
        !          2208:          {
        !          2209:            break;
        !          2210:          }
        !          2211:       }
        !          2212:   }
        !          2213: 
        !          2214:  cleanup:
        !          2215:   LT_DLFREE (argz);
        !          2216:   LT_DLFREE (canonical);
        !          2217:   LT_DLFREE (filename);
        !          2218: 
        !          2219:   LT_DLMUTEX_UNLOCK ();
        !          2220: 
        !          2221:   return result;
        !          2222: }
        !          2223: 
        !          2224: /* If FILEPATH can be opened, store the name of the directory component
        !          2225:    in DATA1, and the opened FILE* structure address in DATA2.  Otherwise
        !          2226:    DATA1 is unchanged, but DATA2 is set to a pointer to NULL.  */
        !          2227: static int
        !          2228: find_file_callback (filename, data1, data2)
        !          2229:      char *filename;
        !          2230:      lt_ptr data1;
        !          2231:      lt_ptr data2;
        !          2232: {
        !          2233:   char      **pdir     = (char **) data1;
        !          2234:   FILE      **pfile    = (FILE **) data2;
        !          2235:   int       is_done    = 0;
        !          2236: 
        !          2237:   assert (filename && *filename);
        !          2238:   assert (pdir);
        !          2239:   assert (pfile);
        !          2240: 
        !          2241:   if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
        !          2242:     {
        !          2243:       char *dirend = strrchr (filename, '/');
        !          2244: 
        !          2245:       if (dirend > filename)
        !          2246:        *dirend   = LT_EOS_CHAR;
        !          2247: 
        !          2248:       LT_DLFREE (*pdir);
        !          2249:       *pdir   = lt_estrdup (filename);
        !          2250:       is_done = (*pdir == NULL) ? -1 : 1;
        !          2251:     }
        !          2252: 
        !          2253:   return is_done;
        !          2254: }
        !          2255: 
        !          2256: static FILE *
        !          2257: find_file (search_path, base_name, pdir)
        !          2258:      const char *search_path;
        !          2259:      const char *base_name;
        !          2260:      char **pdir;
        !          2261: {
        !          2262:   FILE *file = NULL;
        !          2263: 
        !          2264:   foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
        !          2265: 
        !          2266:   return file;
        !          2267: }
        !          2268: 
        !          2269: static int
        !          2270: find_handle_callback (filename, data, ignored)
        !          2271:      char *filename;
        !          2272:      lt_ptr data;
        !          2273:      lt_ptr ignored;
        !          2274: {
        !          2275:   lt_dlhandle  *handle         = (lt_dlhandle *) data;
        !          2276:   int          notfound        = access (filename, R_OK);
        !          2277: 
        !          2278:   /* Bail out if file cannot be read...  */
        !          2279:   if (notfound)
        !          2280:     return 0;
        !          2281: 
        !          2282:   /* Try to dlopen the file, but do not continue searching in any
        !          2283:      case.  */
        !          2284:   if (tryall_dlopen (handle, filename) != 0)
        !          2285:     *handle = NULL;
        !          2286: 
        !          2287:   return 1;
        !          2288: }
        !          2289: 
        !          2290: /* If HANDLE was found return it, otherwise return 0.  If HANDLE was
        !          2291:    found but could not be opened, *HANDLE will be set to 0.  */
        !          2292: static lt_dlhandle *
        !          2293: find_handle (search_path, base_name, handle)
        !          2294:      const char *search_path;
        !          2295:      const char *base_name;
        !          2296:      lt_dlhandle *handle;
        !          2297: {
        !          2298:   if (!search_path)
        !          2299:     return 0;
        !          2300: 
        !          2301:   if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
        !          2302:                          handle, 0))
        !          2303:     return 0;
        !          2304: 
        !          2305:   return handle;
        !          2306: }
        !          2307: 
        !          2308: static int
        !          2309: load_deplibs (handle, deplibs)
        !          2310:      lt_dlhandle handle;
        !          2311:      char *deplibs;
        !          2312: {
        !          2313: #if LTDL_DLOPEN_DEPLIBS
        !          2314:   char *p, *save_search_path = NULL;
        !          2315:   int   depcount = 0;
        !          2316:   int  i;
        !          2317:   char **names = NULL;
        !          2318: #endif
        !          2319:   int  errors = 0;
        !          2320: 
        !          2321:   handle->depcount = 0;
        !          2322: 
        !          2323: #if LTDL_DLOPEN_DEPLIBS
        !          2324:   if (!deplibs)
        !          2325:     {
        !          2326:       return errors;
        !          2327:     }
        !          2328:   ++errors;
        !          2329: 
        !          2330:   LT_DLMUTEX_LOCK ();
        !          2331:   if (user_search_path)
        !          2332:     {
        !          2333:       save_search_path = lt_estrdup (user_search_path);
        !          2334:       if (!save_search_path)
        !          2335:        goto cleanup;
        !          2336:     }
        !          2337: 
        !          2338:   /* extract search paths and count deplibs */
        !          2339:   p = deplibs;
        !          2340:   while (*p)
        !          2341:     {
        !          2342:       if (!isspace ((int) *p))
        !          2343:        {
        !          2344:          char *end = p+1;
        !          2345:          while (*end && !isspace((int) *end))
        !          2346:            {
        !          2347:              ++end;
        !          2348:            }
        !          2349: 
        !          2350:          if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
        !          2351:            {
        !          2352:              char save = *end;
        !          2353:              *end = '\0'; /* set a temporary string terminator */
        !          2354:              if (lt_dladdsearchdir(p+2))
        !          2355:                {
        !          2356:                  goto cleanup;
        !          2357:                }
        !          2358:              *end = save;
        !          2359:            }
        !          2360:          else
        !          2361:            {
        !          2362:              ++depcount;
        !          2363:            }
        !          2364: 
        !          2365:          p = end;
        !          2366:        }
        !          2367:       else
        !          2368:        {
        !          2369:          ++p;
        !          2370:        }
        !          2371:     }
        !          2372: 
        !          2373:   /* restore the old search path */
        !          2374:   LT_DLFREE (user_search_path);
        !          2375:   user_search_path = save_search_path;
        !          2376: 
        !          2377:   LT_DLMUTEX_UNLOCK ();
        !          2378: 
        !          2379:   if (!depcount)
        !          2380:     {
        !          2381:       errors = 0;
        !          2382:       goto cleanup;
        !          2383:     }
        !          2384: 
        !          2385:   names = LT_EMALLOC (char *, depcount * sizeof (char*));
        !          2386:   if (!names)
        !          2387:     goto cleanup;
        !          2388: 
        !          2389:   /* now only extract the actual deplibs */
        !          2390:   depcount = 0;
        !          2391:   p = deplibs;
        !          2392:   while (*p)
        !          2393:     {
        !          2394:       if (isspace ((int) *p))
        !          2395:        {
        !          2396:          ++p;
        !          2397:        }
        !          2398:       else
        !          2399:        {
        !          2400:          char *end = p+1;
        !          2401:          while (*end && !isspace ((int) *end))
        !          2402:            {
        !          2403:              ++end;
        !          2404:            }
        !          2405: 
        !          2406:          if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
        !          2407:            {
        !          2408:              char *name;
        !          2409:              char save = *end;
        !          2410:              *end = '\0'; /* set a temporary string terminator */
        !          2411:              if (strncmp(p, "-l", 2) == 0)
        !          2412:                {
        !          2413:                  size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
        !          2414:                  name = LT_EMALLOC (char, 1+ name_len);
        !          2415:                  if (name)
        !          2416:                    sprintf (name, "lib%s", p+2);
        !          2417:                }
        !          2418:              else
        !          2419:                name = lt_estrdup(p);
        !          2420: 
        !          2421:              if (!name)
        !          2422:                goto cleanup_names;
        !          2423: 
        !          2424:              names[depcount++] = name;
        !          2425:              *end = save;
        !          2426:            }
        !          2427:          p = end;
        !          2428:        }
        !          2429:     }
        !          2430: 
        !          2431:   /* load the deplibs (in reverse order)
        !          2432:      At this stage, don't worry if the deplibs do not load correctly,
        !          2433:      they may already be statically linked into the loading application
        !          2434:      for instance.  There will be a more enlightening error message
        !          2435:      later on if the loaded module cannot resolve all of its symbols.  */
        !          2436:   if (depcount)
        !          2437:     {
        !          2438:       int      j = 0;
        !          2439: 
        !          2440:       handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
        !          2441:       if (!handle->deplibs)
        !          2442:        goto cleanup;
        !          2443: 
        !          2444:       for (i = 0; i < depcount; ++i)
        !          2445:        {
        !          2446:          handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
        !          2447:          if (handle->deplibs[j])
        !          2448:            {
        !          2449:              ++j;
        !          2450:            }
        !          2451:        }
        !          2452: 
        !          2453:       handle->depcount = j;    /* Number of successfully loaded deplibs */
        !          2454:       errors           = 0;
        !          2455:     }
        !          2456: 
        !          2457:  cleanup_names:
        !          2458:   for (i = 0; i < depcount; ++i)
        !          2459:     {
        !          2460:       LT_DLFREE (names[i]);
        !          2461:     }
        !          2462: 
        !          2463:  cleanup:
        !          2464:   LT_DLFREE (names);
        !          2465: #endif
        !          2466: 
        !          2467:   return errors;
        !          2468: }
        !          2469: 
        !          2470: static int
        !          2471: unload_deplibs (handle)
        !          2472:      lt_dlhandle handle;
        !          2473: {
        !          2474:   int i;
        !          2475:   int errors = 0;
        !          2476: 
        !          2477:   if (handle->depcount)
        !          2478:     {
        !          2479:       for (i = 0; i < handle->depcount; ++i)
        !          2480:        {
        !          2481:          if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
        !          2482:            {
        !          2483:              errors += lt_dlclose (handle->deplibs[i]);
        !          2484:            }
        !          2485:        }
        !          2486:     }
        !          2487: 
        !          2488:   return errors;
        !          2489: }
        !          2490: 
        !          2491: static int
        !          2492: trim (dest, str)
        !          2493:      char **dest;
        !          2494:      const char *str;
        !          2495: {
        !          2496:   /* remove the leading and trailing "'" from str
        !          2497:      and store the result in dest */
        !          2498:   const char *end   = strrchr (str, '\'');
        !          2499:   size_t len       = LT_STRLEN (str);
        !          2500:   char *tmp;
        !          2501: 
        !          2502:   LT_DLFREE (*dest);
        !          2503: 
        !          2504:   if (len > 3 && str[0] == '\'')
        !          2505:     {
        !          2506:       tmp = LT_EMALLOC (char, end - str);
        !          2507:       if (!tmp)
        !          2508:        return 1;
        !          2509: 
        !          2510:       strncpy(tmp, &str[1], (end - str) - 1);
        !          2511:       tmp[len-3] = LT_EOS_CHAR;
        !          2512:       *dest = tmp;
        !          2513:     }
        !          2514:   else
        !          2515:     {
        !          2516:       *dest = NULL;
        !          2517:     }
        !          2518: 
        !          2519:   return 0;
        !          2520: }
        !          2521: 
        !          2522: static int
        !          2523: free_vars (dlname, oldname, libdir, deplibs)
        !          2524:      char *dlname;
        !          2525:      char *oldname;
        !          2526:      char *libdir;
        !          2527:      char *deplibs;
        !          2528: {
        !          2529:   LT_DLFREE (dlname);
        !          2530:   LT_DLFREE (oldname);
        !          2531:   LT_DLFREE (libdir);
        !          2532:   LT_DLFREE (deplibs);
        !          2533: 
        !          2534:   return 0;
        !          2535: }
        !          2536: 
        !          2537: static int
        !          2538: try_dlopen (phandle, filename)
        !          2539:      lt_dlhandle *phandle;
        !          2540:      const char *filename;
        !          2541: {
        !          2542:   const char * ext             = NULL;
        !          2543:   const char * saved_error     = NULL;
        !          2544:   char *       canonical       = NULL;
        !          2545:   char *       base_name       = NULL;
        !          2546:   char *       dir             = NULL;
        !          2547:   char *       name            = NULL;
        !          2548:   int          errors          = 0;
        !          2549:   lt_dlhandle  newhandle;
        !          2550: 
        !          2551:   assert (phandle);
        !          2552:   assert (*phandle == NULL);
        !          2553: 
        !          2554:   LT_DLMUTEX_GETERROR (saved_error);
        !          2555: 
        !          2556:   /* dlopen self? */
        !          2557:   if (!filename)
        !          2558:     {
        !          2559:       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
        !          2560:       if (*phandle == NULL)
        !          2561:        return 1;
        !          2562: 
        !          2563:       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
        !          2564:       newhandle        = *phandle;
        !          2565: 
        !          2566:       /* lt_dlclose()ing yourself is very bad!  Disallow it.  */
        !          2567:       LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
        !          2568: 
        !          2569:       if (tryall_dlopen (&newhandle, 0) != 0)
        !          2570:        {
        !          2571:          LT_DLFREE (*phandle);
        !          2572:          return 1;
        !          2573:        }
        !          2574: 
        !          2575:       goto register_handle;
        !          2576:     }
        !          2577: 
        !          2578:   assert (filename && *filename);
        !          2579: 
        !          2580:   /* Doing this immediately allows internal functions to safely
        !          2581:      assume only canonicalized paths are passed.  */
        !          2582:   if (canonicalize_path (filename, &canonical) != 0)
        !          2583:     {
        !          2584:       ++errors;
        !          2585:       goto cleanup;
        !          2586:     }
        !          2587: 
        !          2588:   /* If the canonical module name is a path (relative or absolute)
        !          2589:      then split it into a directory part and a name part.  */
        !          2590:   base_name = strrchr (canonical, '/');
        !          2591:   if (base_name)
        !          2592:     {
        !          2593:       size_t dirlen = (1+ base_name) - canonical;
        !          2594: 
        !          2595:       dir = LT_EMALLOC (char, 1+ dirlen);
        !          2596:       if (!dir)
        !          2597:        {
        !          2598:          ++errors;
        !          2599:          goto cleanup;
        !          2600:        }
        !          2601: 
        !          2602:       strncpy (dir, canonical, dirlen);
        !          2603:       dir[dirlen] = LT_EOS_CHAR;
        !          2604: 
        !          2605:       ++base_name;
        !          2606:     }
        !          2607:   else
        !          2608:     LT_DLMEM_REASSIGN (base_name, canonical);
        !          2609: 
        !          2610:   assert (base_name && *base_name);
        !          2611: 
        !          2612:   /* Check whether we are opening a libtool module (.la extension).  */
        !          2613:   ext = strrchr (base_name, '.');
        !          2614:   if (ext && strcmp (ext, archive_ext) == 0)
        !          2615:     {
        !          2616:       /* this seems to be a libtool module */
        !          2617:       FILE *   file     = NULL;
        !          2618:       char *   dlname   = NULL;
        !          2619:       char *   old_name = NULL;
        !          2620:       char *   libdir   = NULL;
        !          2621:       char *   deplibs  = NULL;
        !          2622:       char *    line    = NULL;
        !          2623:       size_t   line_len;
        !          2624: 
        !          2625:       /* if we can't find the installed flag, it is probably an
        !          2626:         installed libtool archive, produced with an old version
        !          2627:         of libtool */
        !          2628:       int      installed = 1;
        !          2629: 
        !          2630:       /* extract the module name from the file name */
        !          2631:       name = LT_EMALLOC (char, ext - base_name + 1);
        !          2632:       if (!name)
        !          2633:        {
        !          2634:          ++errors;
        !          2635:          goto cleanup;
        !          2636:        }
        !          2637: 
        !          2638:       /* canonicalize the module name */
        !          2639:       {
        !          2640:         size_t i;
        !          2641:         for (i = 0; i < ext - base_name; ++i)
        !          2642:          {
        !          2643:            if (isalnum ((int)(base_name[i])))
        !          2644:              {
        !          2645:                name[i] = base_name[i];
        !          2646:              }
        !          2647:            else
        !          2648:              {
        !          2649:                name[i] = '_';
        !          2650:              }
        !          2651:          }
        !          2652:         name[ext - base_name] = LT_EOS_CHAR;
        !          2653:       }
        !          2654: 
        !          2655:       /* Now try to open the .la file.  If there is no directory name
        !          2656:          component, try to find it first in user_search_path and then other
        !          2657:          prescribed paths.  Otherwise (or in any case if the module was not
        !          2658:          yet found) try opening just the module name as passed.  */
        !          2659:       if (!dir)
        !          2660:        {
        !          2661:          const char *search_path;
        !          2662: 
        !          2663:          LT_DLMUTEX_LOCK ();
        !          2664:          search_path = user_search_path;
        !          2665:          if (search_path)
        !          2666:            file = find_file (user_search_path, base_name, &dir);
        !          2667:          LT_DLMUTEX_UNLOCK ();
        !          2668: 
        !          2669:          if (!file)
        !          2670:            {
        !          2671:              search_path = getenv (LTDL_SEARCHPATH_VAR);
        !          2672:              if (search_path)
        !          2673:                file = find_file (search_path, base_name, &dir);
        !          2674:            }
        !          2675: 
        !          2676: #ifdef LTDL_SHLIBPATH_VAR
        !          2677:          if (!file)
        !          2678:            {
        !          2679:              search_path = getenv (LTDL_SHLIBPATH_VAR);
        !          2680:              if (search_path)
        !          2681:                file = find_file (search_path, base_name, &dir);
        !          2682:            }
        !          2683: #endif
        !          2684: #ifdef LTDL_SYSSEARCHPATH
        !          2685:          if (!file && sys_search_path)
        !          2686:            {
        !          2687:              file = find_file (sys_search_path, base_name, &dir);
        !          2688:            }
        !          2689: #endif
        !          2690:        }
        !          2691:       if (!file)
        !          2692:        {
        !          2693:          file = fopen (filename, LT_READTEXT_MODE);
        !          2694:        }
        !          2695: 
        !          2696:       /* If we didn't find the file by now, it really isn't there.  Set
        !          2697:         the status flag, and bail out.  */
        !          2698:       if (!file)
        !          2699:        {
        !          2700:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
        !          2701:          ++errors;
        !          2702:          goto cleanup;
        !          2703:        }
        !          2704: 
        !          2705:       line_len = LT_FILENAME_MAX;
        !          2706:       line = LT_EMALLOC (char, line_len);
        !          2707:       if (!line)
        !          2708:        {
        !          2709:          fclose (file);
        !          2710:          ++errors;
        !          2711:          goto cleanup;
        !          2712:        }
        !          2713: 
        !          2714:       /* read the .la file */
        !          2715:       while (!feof (file))
        !          2716:        {
        !          2717:          if (!fgets (line, (int) line_len, file))
        !          2718:            {
        !          2719:              break;
        !          2720:            }
        !          2721: 
        !          2722:          /* Handle the case where we occasionally need to read a line
        !          2723:             that is longer than the initial buffer size.  */
        !          2724:          while (line[LT_STRLEN(line) -1] != '\n')
        !          2725:            {
        !          2726:              line = LT_DLREALLOC (char, line, line_len *2);
        !          2727:              if (!fgets (&line[line_len -1], (int) line_len +1, file))
        !          2728:                {
        !          2729:                  break;
        !          2730:                }
        !          2731:              line_len *= 2;
        !          2732:            }
        !          2733: 
        !          2734:          if (line[0] == '\n' || line[0] == '#')
        !          2735:            {
        !          2736:              continue;
        !          2737:            }
        !          2738: 
        !          2739: #undef  STR_DLNAME
        !          2740: #define STR_DLNAME     "dlname="
        !          2741:          if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
        !          2742:            {
        !          2743:              errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
        !          2744:            }
        !          2745: 
        !          2746: #undef  STR_OLD_LIBRARY
        !          2747: #define STR_OLD_LIBRARY        "old_library="
        !          2748:          else if (strncmp (line, STR_OLD_LIBRARY,
        !          2749:                            sizeof (STR_OLD_LIBRARY) - 1) == 0)
        !          2750:            {
        !          2751:              errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
        !          2752:            }
        !          2753: #undef  STR_LIBDIR
        !          2754: #define STR_LIBDIR     "libdir="
        !          2755:          else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
        !          2756:            {
        !          2757:              errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
        !          2758:            }
        !          2759: 
        !          2760: #undef  STR_DL_DEPLIBS
        !          2761: #define STR_DL_DEPLIBS "dependency_libs="
        !          2762:          else if (strncmp (line, STR_DL_DEPLIBS,
        !          2763:                            sizeof (STR_DL_DEPLIBS) - 1) == 0)
        !          2764:            {
        !          2765:              errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
        !          2766:            }
        !          2767:          else if (strcmp (line, "installed=yes\n") == 0)
        !          2768:            {
        !          2769:              installed = 1;
        !          2770:            }
        !          2771:          else if (strcmp (line, "installed=no\n") == 0)
        !          2772:            {
        !          2773:              installed = 0;
        !          2774:            }
        !          2775: 
        !          2776: #undef  STR_LIBRARY_NAMES
        !          2777: #define STR_LIBRARY_NAMES "library_names="
        !          2778:          else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
        !          2779:                                        sizeof (STR_LIBRARY_NAMES) - 1) == 0)
        !          2780:            {
        !          2781:              char *last_libname;
        !          2782:              errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
        !          2783:              if (!errors
        !          2784:                  && dlname
        !          2785:                  && (last_libname = strrchr (dlname, ' ')) != NULL)
        !          2786:                {
        !          2787:                  last_libname = lt_estrdup (last_libname + 1);
        !          2788:                  if (!last_libname)
        !          2789:                    {
        !          2790:                      ++errors;
        !          2791:                      goto cleanup;
        !          2792:                    }
        !          2793:                  LT_DLMEM_REASSIGN (dlname, last_libname);
        !          2794:                }
        !          2795:            }
        !          2796: 
        !          2797:          if (errors)
        !          2798:            break;
        !          2799:        }
        !          2800: 
        !          2801:       fclose (file);
        !          2802:       LT_DLFREE (line);
        !          2803: 
        !          2804:       /* allocate the handle */
        !          2805:       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
        !          2806:       if (*phandle == NULL)
        !          2807:        ++errors;
        !          2808: 
        !          2809:       if (errors)
        !          2810:        {
        !          2811:          free_vars (dlname, old_name, libdir, deplibs);
        !          2812:          LT_DLFREE (*phandle);
        !          2813:          goto cleanup;
        !          2814:        }
        !          2815: 
        !          2816:       assert (*phandle);
        !          2817: 
        !          2818:       memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
        !          2819:       if (load_deplibs (*phandle, deplibs) == 0)
        !          2820:        {
        !          2821:          newhandle = *phandle;
        !          2822:          /* find_module may replace newhandle */
        !          2823:          if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
        !          2824:            {
        !          2825:              unload_deplibs (*phandle);
        !          2826:              ++errors;
        !          2827:            }
        !          2828:        }
        !          2829:       else
        !          2830:        {
        !          2831:          ++errors;
        !          2832:        }
        !          2833: 
        !          2834:       free_vars (dlname, old_name, libdir, deplibs);
        !          2835:       if (errors)
        !          2836:        {
        !          2837:          LT_DLFREE (*phandle);
        !          2838:          goto cleanup;
        !          2839:        }
        !          2840: 
        !          2841:       if (*phandle != newhandle)
        !          2842:        {
        !          2843:          unload_deplibs (*phandle);
        !          2844:        }
        !          2845:     }
        !          2846:   else
        !          2847:     {
        !          2848:       /* not a libtool module */
        !          2849:       *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
        !          2850:       if (*phandle == NULL)
        !          2851:        {
        !          2852:          ++errors;
        !          2853:          goto cleanup;
        !          2854:        }
        !          2855: 
        !          2856:       memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
        !          2857:       newhandle = *phandle;
        !          2858: 
        !          2859:       /* If the module has no directory name component, try to find it
        !          2860:         first in user_search_path and then other prescribed paths.
        !          2861:         Otherwise (or in any case if the module was not yet found) try
        !          2862:         opening just the module name as passed.  */
        !          2863:       if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
        !          2864:                   && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
        !          2865:                                    &newhandle)
        !          2866: #ifdef LTDL_SHLIBPATH_VAR
        !          2867:                   && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
        !          2868:                                    &newhandle)
        !          2869: #endif
        !          2870: #ifdef LTDL_SYSSEARCHPATH
        !          2871:                   && !find_handle (sys_search_path, base_name, &newhandle)
        !          2872: #endif
        !          2873:                   )))
        !          2874:        {
        !          2875:           if (tryall_dlopen (&newhandle, filename) != 0)
        !          2876:             {
        !          2877:               newhandle = NULL;
        !          2878:             }
        !          2879:        }
        !          2880: 
        !          2881:       if (!newhandle)
        !          2882:        {
        !          2883:          LT_DLFREE (*phandle);
        !          2884:          ++errors;
        !          2885:          goto cleanup;
        !          2886:        }
        !          2887:     }
        !          2888: 
        !          2889:  register_handle:
        !          2890:   LT_DLMEM_REASSIGN (*phandle, newhandle);
        !          2891: 
        !          2892:   if ((*phandle)->info.ref_count == 0)
        !          2893:     {
        !          2894:       (*phandle)->info.ref_count       = 1;
        !          2895:       LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
        !          2896: 
        !          2897:       LT_DLMUTEX_LOCK ();
        !          2898:       (*phandle)->next         = handles;
        !          2899:       handles                  = *phandle;
        !          2900:       LT_DLMUTEX_UNLOCK ();
        !          2901:     }
        !          2902: 
        !          2903:   LT_DLMUTEX_SETERROR (saved_error);
        !          2904: 
        !          2905:  cleanup:
        !          2906:   LT_DLFREE (dir);
        !          2907:   LT_DLFREE (name);
        !          2908:   LT_DLFREE (canonical);
        !          2909: 
        !          2910:   return errors;
        !          2911: }
        !          2912: 
        !          2913: lt_dlhandle
        !          2914: lt_dlopen (filename)
        !          2915:      const char *filename;
        !          2916: {
        !          2917:   lt_dlhandle handle = NULL;
1.1       paf      2918: 
1.2     ! paf      2919:   /* Just incase we missed a code path in try_dlopen() that reports
        !          2920:      an error, but forgets to reset handle... */
        !          2921:   if (try_dlopen (&handle, filename) != 0)
        !          2922:     return 0;
        !          2923: 
        !          2924:   return handle;
        !          2925: }
        !          2926: 
        !          2927: /* If the last error messge store was `FILE_NOT_FOUND', then return
        !          2928:    non-zero.  */
1.1       paf      2929: static int
1.2     ! paf      2930: file_not_found ()
        !          2931: {
        !          2932:   const char *error = NULL;
        !          2933: 
        !          2934:   LT_DLMUTEX_GETERROR (error);
        !          2935:   if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
        !          2936:     return 1;
        !          2937: 
        !          2938:   return 0;
        !          2939: }
        !          2940: 
        !          2941: /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
        !          2942:    open the FILENAME as passed.  Otherwise try appending ARCHIVE_EXT,
        !          2943:    and if a file is still not found try again with SHLIB_EXT appended
        !          2944:    instead.  */
        !          2945: lt_dlhandle
        !          2946: lt_dlopenext (filename)
        !          2947:      const char *filename;
1.1       paf      2948: {
1.2     ! paf      2949:   lt_dlhandle  handle          = NULL;
        !          2950:   char *       tmp             = NULL;
        !          2951:   char *       ext             = NULL;
        !          2952:   size_t       len;
        !          2953:   int          errors          = 0;
        !          2954: 
        !          2955:   if (!filename)
        !          2956:     {
        !          2957:       return lt_dlopen (filename);
        !          2958:     }
        !          2959: 
        !          2960:   assert (filename);
        !          2961: 
        !          2962:   len = LT_STRLEN (filename);
        !          2963:   ext = strrchr (filename, '.');
        !          2964: 
        !          2965:   /* If FILENAME already bears a suitable extension, there is no need
        !          2966:      to try appending additional extensions.  */
        !          2967:   if (ext && ((strcmp (ext, archive_ext) == 0)
        !          2968: #ifdef LTDL_SHLIB_EXT
        !          2969:              || (strcmp (ext, shlib_ext) == 0)
        !          2970: #endif
        !          2971:       ))
        !          2972:     {
        !          2973:       return lt_dlopen (filename);
        !          2974:     }
        !          2975: 
        !          2976:   /* First try appending ARCHIVE_EXT.  */
        !          2977:   tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
        !          2978:   if (!tmp)
        !          2979:     return 0;
        !          2980: 
        !          2981:   strcpy (tmp, filename);
        !          2982:   strcat (tmp, archive_ext);
        !          2983:   errors = try_dlopen (&handle, tmp);
        !          2984: 
        !          2985:   /* If we found FILENAME, stop searching -- whether we were able to
        !          2986:      load the file as a module or not.  If the file exists but loading
        !          2987:      failed, it is better to return an error message here than to
        !          2988:      report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
        !          2989:      in the module search path.  */
        !          2990:   if (handle || ((errors > 0) && file_not_found ()))
        !          2991:     {
        !          2992:       LT_DLFREE (tmp);
        !          2993:       return handle;
        !          2994:     }
        !          2995: 
        !          2996: #ifdef LTDL_SHLIB_EXT
        !          2997:   /* Try appending SHLIB_EXT.   */
        !          2998:   if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
        !          2999:     {
        !          3000:       LT_DLFREE (tmp);
        !          3001:       tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
        !          3002:       if (!tmp)
1.1       paf      3003:        return 0;
1.2     ! paf      3004: 
        !          3005:       strcpy (tmp, filename);
        !          3006:     }
        !          3007:   else
        !          3008:     {
        !          3009:       tmp[len] = LT_EOS_CHAR;
        !          3010:     }
        !          3011: 
        !          3012:   strcat(tmp, shlib_ext);
        !          3013:   errors = try_dlopen (&handle, tmp);
        !          3014: 
        !          3015:   /* As before, if the file was found but loading failed, return now
        !          3016:      with the current error message.  */
        !          3017:   if (handle || ((errors > 0) && file_not_found ()))
        !          3018:     {
        !          3019:       LT_DLFREE (tmp);
        !          3020:       return handle;
        !          3021:     }
        !          3022: #endif
        !          3023: 
        !          3024:   /* Still here?  Then we really did fail to locate any of the file
        !          3025:      names we tried.  */
        !          3026:   LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
        !          3027:   LT_DLFREE (tmp);
        !          3028:   return 0;
1.1       paf      3029: }
                   3030: 
1.2     ! paf      3031: 
1.1       paf      3032: static int
1.2     ! paf      3033: lt_argz_insert (pargz, pargz_len, before, entry)
        !          3034:      char **pargz;
        !          3035:      size_t *pargz_len;
        !          3036:      char *before;
        !          3037:      const char *entry;
1.1       paf      3038: {
1.2     ! paf      3039:   error_t error;
        !          3040: 
        !          3041:   if ((error = argz_insert (pargz, pargz_len, before, entry)))
        !          3042:     {
        !          3043:       switch (error)
        !          3044:        {
        !          3045:        case ENOMEM:
        !          3046:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
        !          3047:          break;
        !          3048:        default:
        !          3049:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
        !          3050:          break;
1.1       paf      3051:        }
1.2     ! paf      3052:       return 1;
        !          3053:     }
        !          3054: 
        !          3055:   return 0;
1.1       paf      3056: }
                   3057: 
                   3058: static int
1.2     ! paf      3059: lt_argz_insertinorder (pargz, pargz_len, entry)
        !          3060:      char **pargz;
        !          3061:      size_t *pargz_len;
        !          3062:      const char *entry;
1.1       paf      3063: {
1.2     ! paf      3064:   char *before = NULL;
        !          3065: 
        !          3066:   assert (pargz);
        !          3067:   assert (pargz_len);
        !          3068:   assert (entry && *entry);
        !          3069: 
        !          3070:   if (*pargz)
        !          3071:     while ((before = argz_next (*pargz, *pargz_len, before)))
        !          3072:       {
        !          3073:        int cmp = strcmp (entry, before);
        !          3074: 
        !          3075:        if (cmp < 0)  break;
        !          3076:        if (cmp == 0) return 0; /* No duplicates! */
        !          3077:       }
        !          3078: 
        !          3079:   return lt_argz_insert (pargz, pargz_len, before, entry);
1.1       paf      3080: }
                   3081: 
                   3082: static int
1.2     ! paf      3083: lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
        !          3084:      char **pargz;
        !          3085:      size_t *pargz_len;
        !          3086:      const char *dirnam;
        !          3087:      struct dirent *dp;
1.1       paf      3088: {
1.2     ! paf      3089:   char   *buf      = NULL;
        !          3090:   size_t buf_len    = 0;
        !          3091:   char   *end      = NULL;
        !          3092:   size_t end_offset = 0;
        !          3093:   size_t dir_len    = 0;
        !          3094:   int    errors            = 0;
        !          3095: 
        !          3096:   assert (pargz);
        !          3097:   assert (pargz_len);
        !          3098:   assert (dp);
        !          3099: 
        !          3100:   dir_len = LT_STRLEN (dirnam);
        !          3101:   end     = dp->d_name + LT_D_NAMLEN(dp);
        !          3102: 
        !          3103:   /* Ignore version numbers.  */
        !          3104:   {
        !          3105:     char *p;
        !          3106:     for (p = end; p -1 > dp->d_name; --p)
        !          3107:       if (strchr (".0123456789", p[-1]) == 0)
        !          3108:        break;
        !          3109: 
        !          3110:     if (*p == '.')
        !          3111:       end = p;
        !          3112:   }
        !          3113: 
        !          3114:   /* Ignore filename extension.  */
        !          3115:   {
        !          3116:     char *p;
        !          3117:     for (p = end -1; p > dp->d_name; --p)
        !          3118:       if (*p == '.')
        !          3119:        {
        !          3120:          end = p;
        !          3121:          break;
1.1       paf      3122:        }
1.2     ! paf      3123:   }
        !          3124: 
        !          3125:   /* Prepend the directory name.  */
        !          3126:   end_offset   = end - dp->d_name;
        !          3127:   buf_len      = dir_len + 1+ end_offset;
        !          3128:   buf          = LT_EMALLOC (char, 1+ buf_len);
        !          3129:   if (!buf)
        !          3130:     return ++errors;
        !          3131: 
        !          3132:   assert (buf);
        !          3133: 
        !          3134:   strcpy  (buf, dirnam);
        !          3135:   strcat  (buf, "/");
        !          3136:   strncat (buf, dp->d_name, end_offset);
        !          3137:   buf[buf_len] = LT_EOS_CHAR;
        !          3138: 
        !          3139:   /* Try to insert (in order) into ARGZ/ARGZ_LEN.  */
        !          3140:   if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
        !          3141:     ++errors;
        !          3142: 
        !          3143:   LT_DLFREE (buf);
        !          3144: 
        !          3145:   return errors;
1.1       paf      3146: }
                   3147: 
                   3148: static int
1.2     ! paf      3149: list_files_by_dir (dirnam, pargz, pargz_len)
        !          3150:      const char *dirnam;
        !          3151:      char **pargz;
        !          3152:      size_t *pargz_len;
        !          3153: {
        !          3154:   DIR  *dirp     = NULL;
        !          3155:   int    errors          = 0;
        !          3156: 
        !          3157:   assert (dirnam && *dirnam);
        !          3158:   assert (pargz);
        !          3159:   assert (pargz_len);
        !          3160:   assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
        !          3161: 
        !          3162:   dirp = opendir (dirnam);
        !          3163:   if (dirp)
        !          3164:     {
        !          3165:       struct dirent *dp        = NULL;
        !          3166: 
        !          3167:       while ((dp = readdir (dirp)))
        !          3168:        if (dp->d_name[0] != '.')
        !          3169:          if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
        !          3170:            {
        !          3171:              ++errors;
        !          3172:              break;
        !          3173:            }
        !          3174: 
        !          3175:       closedir (dirp);
        !          3176:     }
        !          3177:   else
        !          3178:     ++errors;
        !          3179: 
        !          3180:   return errors;
1.1       paf      3181: }
                   3182: 
1.2     ! paf      3183: 
        !          3184: /* If there are any files in DIRNAME, call the function passed in
        !          3185:    DATA1 (with the name of each file and DATA2 as arguments).  */
1.1       paf      3186: static int
1.2     ! paf      3187: foreachfile_callback (dirname, data1, data2)
        !          3188:      char *dirname;
        !          3189:      lt_ptr data1;
        !          3190:      lt_ptr data2;
1.1       paf      3191: {
1.2     ! paf      3192:   int (*func) LT_PARAMS((const char *filename, lt_ptr data))
        !          3193:        = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
        !          3194: 
        !          3195:   int    is_done  = 0;
        !          3196:   char   *argz     = NULL;
        !          3197:   size_t  argz_len = 0;
        !          3198: 
        !          3199:   if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
        !          3200:     goto cleanup;
        !          3201:   if (!argz)
        !          3202:     goto cleanup;
        !          3203: 
        !          3204:   {
        !          3205:     char *filename = NULL;
        !          3206:     while ((filename = argz_next (argz, argz_len, filename)))
        !          3207:       if ((is_done = (*func) (filename, data2)))
        !          3208:        break;
        !          3209:   }
        !          3210: 
        !          3211:  cleanup:
        !          3212:   LT_DLFREE (argz);
        !          3213: 
        !          3214:   return is_done;
1.1       paf      3215: }
                   3216: 
1.2     ! paf      3217: 
        !          3218: /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
        !          3219:    with DATA.  The filenames passed to FUNC would be suitable for
        !          3220:    passing to lt_dlopenext.  The extensions are stripped so that
        !          3221:    individual modules do not generate several entries (e.g. libfoo.la,
        !          3222:    libfoo.so, libfoo.so.1, libfoo.so.1.0.0).  If SEARCH_PATH is NULL,
        !          3223:    then the same directories that lt_dlopen would search are examined.  */
        !          3224: int
        !          3225: lt_dlforeachfile (search_path, func, data)
        !          3226:      const char *search_path;
        !          3227:      int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
        !          3228:      lt_ptr data;
        !          3229: {
        !          3230:   int is_done = 0;
        !          3231: 
        !          3232:   if (search_path)
        !          3233:     {
        !          3234:       /* If a specific path was passed, search only the directories
        !          3235:         listed in it.  */
        !          3236:       is_done = foreach_dirinpath (search_path, 0,
        !          3237:                                   foreachfile_callback, func, data);
        !          3238:     }
        !          3239:   else
        !          3240:     {
        !          3241:       /* Otherwise search the default paths.  */
        !          3242:       is_done = foreach_dirinpath (user_search_path, 0,
        !          3243:                                   foreachfile_callback, func, data);
        !          3244:       if (!is_done)
        !          3245:        {
        !          3246:          is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
        !          3247:                                       foreachfile_callback, func, data);
1.1       paf      3248:        }
                   3249: 
1.2     ! paf      3250: #ifdef LTDL_SHLIBPATH_VAR
        !          3251:       if (!is_done)
        !          3252:        {
        !          3253:          is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
        !          3254:                                       foreachfile_callback, func, data);
        !          3255:        }
        !          3256: #endif
        !          3257: #ifdef LTDL_SYSSEARCHPATH
        !          3258:       if (!is_done)
        !          3259:        {
        !          3260:          is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
        !          3261:                                       foreachfile_callback, func, data);
        !          3262:        }
        !          3263: #endif
        !          3264:     }
1.1       paf      3265: 
1.2     ! paf      3266:   return is_done;
        !          3267: }
1.1       paf      3268: 
                   3269: int
1.2     ! paf      3270: lt_dlclose (handle)
        !          3271:      lt_dlhandle handle;
1.1       paf      3272: {
1.2     ! paf      3273:   lt_dlhandle cur, last;
        !          3274:   int errors = 0;
        !          3275: 
        !          3276:   LT_DLMUTEX_LOCK ();
        !          3277: 
        !          3278:   /* check whether the handle is valid */
        !          3279:   last = cur = handles;
        !          3280:   while (cur && handle != cur)
        !          3281:     {
        !          3282:       last = cur;
        !          3283:       cur = cur->next;
        !          3284:     }
        !          3285: 
        !          3286:   if (!cur)
        !          3287:     {
        !          3288:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
        !          3289:       ++errors;
        !          3290:       goto done;
        !          3291:     }
        !          3292: 
        !          3293:   handle->info.ref_count--;
        !          3294: 
        !          3295:   /* Note that even with resident modules, we must track the ref_count
        !          3296:      correctly incase the user decides to reset the residency flag
        !          3297:      later (even though the API makes no provision for that at the
        !          3298:      moment).  */
        !          3299:   if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
        !          3300:     {
        !          3301:       lt_user_data data = handle->loader->dlloader_data;
        !          3302: 
        !          3303:       if (handle != handles)
        !          3304:        {
        !          3305:          last->next = handle->next;
1.1       paf      3306:        }
1.2     ! paf      3307:       else
        !          3308:        {
        !          3309:          handles = handle->next;
1.1       paf      3310:        }
1.2     ! paf      3311: 
        !          3312:       errors += handle->loader->module_close (data, handle->module);
        !          3313:       errors += unload_deplibs(handle);
        !          3314: 
        !          3315:       /* It is up to the callers to free the data itself.  */
        !          3316:       LT_DLFREE (handle->caller_data);
        !          3317: 
        !          3318:       LT_DLFREE (handle->info.filename);
        !          3319:       LT_DLFREE (handle->info.name);
        !          3320:       LT_DLFREE (handle);
        !          3321: 
        !          3322:       goto done;
        !          3323:     }
        !          3324: 
        !          3325:   if (LT_DLIS_RESIDENT (handle))
        !          3326:     {
        !          3327:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
        !          3328:       ++errors;
        !          3329:     }
        !          3330: 
        !          3331:  done:
        !          3332:   LT_DLMUTEX_UNLOCK ();
        !          3333: 
        !          3334:   return errors;
1.1       paf      3335: }
                   3336: 
1.2     ! paf      3337: lt_ptr
        !          3338: lt_dlsym (handle, symbol)
        !          3339:      lt_dlhandle handle;
        !          3340:      const char *symbol;
1.1       paf      3341: {
1.2     ! paf      3342:   size_t lensym;
        !          3343:   char lsym[LT_SYMBOL_LENGTH];
        !          3344:   char *sym;
        !          3345:   lt_ptr address;
        !          3346:   lt_user_data data;
        !          3347: 
        !          3348:   if (!handle)
        !          3349:     {
        !          3350:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
        !          3351:       return 0;
        !          3352:     }
        !          3353: 
        !          3354:   if (!symbol)
        !          3355:     {
        !          3356:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
        !          3357:       return 0;
        !          3358:     }
        !          3359: 
        !          3360:   lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
        !          3361:                                        + LT_STRLEN (handle->info.name);
        !          3362: 
        !          3363:   if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
        !          3364:     {
        !          3365:       sym = lsym;
        !          3366:     }
        !          3367:   else
        !          3368:     {
        !          3369:       sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
        !          3370:       if (!sym)
        !          3371:        {
        !          3372:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
        !          3373:          return 0;
        !          3374:        }
        !          3375:     }
        !          3376: 
        !          3377:   data = handle->loader->dlloader_data;
        !          3378:   if (handle->info.name)
        !          3379:     {
        !          3380:       const char *saved_error;
        !          3381: 
        !          3382:       LT_DLMUTEX_GETERROR (saved_error);
        !          3383: 
        !          3384:       /* this is a libtool module */
        !          3385:       if (handle->loader->sym_prefix)
        !          3386:        {
        !          3387:          strcpy(sym, handle->loader->sym_prefix);
        !          3388:          strcat(sym, handle->info.name);
        !          3389:        }
        !          3390:       else
        !          3391:        {
        !          3392:          strcpy(sym, handle->info.name);
        !          3393:        }
        !          3394: 
        !          3395:       strcat(sym, "_LTX_");
        !          3396:       strcat(sym, symbol);
        !          3397: 
        !          3398:       /* try "modulename_LTX_symbol" */
        !          3399:       address = handle->loader->find_sym (data, handle->module, sym);
        !          3400:       if (address)
        !          3401:        {
        !          3402:          if (sym != lsym)
        !          3403:            {
        !          3404:              LT_DLFREE (sym);
        !          3405:            }
        !          3406:          return address;
        !          3407:        }
        !          3408:       LT_DLMUTEX_SETERROR (saved_error);
        !          3409:     }
        !          3410: 
        !          3411:   /* otherwise try "symbol" */
        !          3412:   if (handle->loader->sym_prefix)
        !          3413:     {
        !          3414:       strcpy(sym, handle->loader->sym_prefix);
        !          3415:       strcat(sym, symbol);
        !          3416:     }
        !          3417:   else
        !          3418:     {
        !          3419:       strcpy(sym, symbol);
        !          3420:     }
        !          3421: 
        !          3422:   address = handle->loader->find_sym (data, handle->module, sym);
        !          3423:   if (sym != lsym)
        !          3424:     {
        !          3425:       LT_DLFREE (sym);
        !          3426:     }
        !          3427: 
        !          3428:   return address;
1.1       paf      3429: }
                   3430: 
1.2     ! paf      3431: const char *
        !          3432: lt_dlerror ()
1.1       paf      3433: {
1.2     ! paf      3434:   const char *error;
        !          3435: 
        !          3436:   LT_DLMUTEX_GETERROR (error);
        !          3437:   LT_DLMUTEX_SETERROR (0);
        !          3438: 
        !          3439:   return error ? error : LT_DLSTRERROR (UNKNOWN);
1.1       paf      3440: }
                   3441: 
1.2     ! paf      3442: static int
        !          3443: lt_dlpath_insertdir (ppath, before, dir)
        !          3444:      char **ppath;
        !          3445:      char *before;
        !          3446:      const char *dir;
1.1       paf      3447: {
1.2     ! paf      3448:   int    errors                = 0;
        !          3449:   char  *canonical     = NULL;
        !          3450:   char  *argz          = NULL;
        !          3451:   size_t argz_len      = 0;
        !          3452: 
        !          3453:   assert (ppath);
        !          3454:   assert (dir && *dir);
        !          3455: 
        !          3456:   if (canonicalize_path (dir, &canonical) != 0)
        !          3457:     {
        !          3458:       ++errors;
        !          3459:       goto cleanup;
        !          3460:     }
        !          3461: 
        !          3462:   assert (canonical && *canonical);
        !          3463: 
        !          3464:   /* If *PPATH is empty, set it to DIR.  */
        !          3465:   if (*ppath == NULL)
        !          3466:     {
        !          3467:       assert (!before);                /* BEFORE cannot be set without PPATH.  */
        !          3468:       assert (dir);            /* Without DIR, don't call this function!  */
        !          3469: 
        !          3470:       *ppath = lt_estrdup (dir);
        !          3471:       if (*ppath == NULL)
        !          3472:        ++errors;
        !          3473: 
        !          3474:       return errors;
        !          3475:     }
        !          3476: 
        !          3477:   assert (ppath && *ppath);
        !          3478: 
        !          3479:   if (argzize_path (*ppath, &argz, &argz_len) != 0)
        !          3480:     {
        !          3481:       ++errors;
        !          3482:       goto cleanup;
        !          3483:     }
        !          3484: 
        !          3485:   /* Convert BEFORE into an equivalent offset into ARGZ.  This only works
        !          3486:      if *PPATH is already canonicalized, and hence does not change length
        !          3487:      with respect to ARGZ.  We canonicalize each entry as it is added to
        !          3488:      the search path, and don't call this function with (uncanonicalized)
        !          3489:      user paths, so this is a fair assumption.  */
        !          3490:   if (before)
        !          3491:     {
        !          3492:       assert (*ppath <= before);
        !          3493:       assert (before - *ppath <= strlen (*ppath));
        !          3494: 
        !          3495:       before = before - *ppath + argz;
        !          3496:     }
        !          3497: 
        !          3498:   if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
        !          3499:     {
        !          3500:       ++errors;
        !          3501:       goto cleanup;
        !          3502:     }
        !          3503: 
        !          3504:   argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
        !          3505:   LT_DLMEM_REASSIGN (*ppath,  argz);
        !          3506: 
        !          3507:  cleanup:
        !          3508:   LT_DLFREE (canonical);
        !          3509:   LT_DLFREE (argz);
        !          3510: 
        !          3511:   return errors;
1.1       paf      3512: }
                   3513: 
1.2     ! paf      3514: int
        !          3515: lt_dladdsearchdir (search_dir)
        !          3516:      const char *search_dir;
1.1       paf      3517: {
1.2     ! paf      3518:   int errors = 0;
        !          3519: 
        !          3520:   if (search_dir && *search_dir)
        !          3521:     {
        !          3522:       LT_DLMUTEX_LOCK ();
        !          3523:       if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
        !          3524:        ++errors;
        !          3525:       LT_DLMUTEX_UNLOCK ();
        !          3526:     }
        !          3527: 
        !          3528:   return errors;
1.1       paf      3529: }
                   3530: 
1.2     ! paf      3531: int
        !          3532: lt_dlinsertsearchdir (before, search_dir)
        !          3533:      const char *before;
        !          3534:      const char *search_dir;
        !          3535: {
        !          3536:   int errors = 0;
        !          3537: 
        !          3538:   if (before)
        !          3539:     {
        !          3540:       LT_DLMUTEX_LOCK ();
        !          3541:       if ((before < user_search_path)
        !          3542:          || (before >= user_search_path + LT_STRLEN (user_search_path)))
        !          3543:        {
        !          3544:          LT_DLMUTEX_UNLOCK ();
        !          3545:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
        !          3546:          return 1;
        !          3547:        }
        !          3548:       LT_DLMUTEX_UNLOCK ();
        !          3549:     }
        !          3550: 
        !          3551:   if (search_dir && *search_dir)
        !          3552:     {
        !          3553:       LT_DLMUTEX_LOCK ();
        !          3554:       if (lt_dlpath_insertdir (&user_search_path,
        !          3555:                               (char *) before, search_dir) != 0)
        !          3556:        {
        !          3557:          ++errors;
1.1       paf      3558:        }
1.2     ! paf      3559:       LT_DLMUTEX_UNLOCK ();
        !          3560:     }
        !          3561: 
        !          3562:   return errors;
1.1       paf      3563: }
                   3564: 
1.2     ! paf      3565: int
        !          3566: lt_dlsetsearchpath (search_path)
        !          3567:      const char *search_path;
        !          3568: {
        !          3569:   int   errors     = 0;
        !          3570: 
        !          3571:   LT_DLMUTEX_LOCK ();
        !          3572:   LT_DLFREE (user_search_path);
        !          3573:   LT_DLMUTEX_UNLOCK ();
        !          3574: 
        !          3575:   if (!search_path || !LT_STRLEN (search_path))
        !          3576:     {
        !          3577:       return errors;
        !          3578:     }
        !          3579: 
        !          3580:   LT_DLMUTEX_LOCK ();
        !          3581:   if (canonicalize_path (search_path, &user_search_path) != 0)
        !          3582:     ++errors;
        !          3583:   LT_DLMUTEX_UNLOCK ();
        !          3584: 
        !          3585:   return errors;
1.1       paf      3586: }
                   3587: 
1.2     ! paf      3588: const char *
        !          3589: lt_dlgetsearchpath ()
        !          3590: {
        !          3591:   const char *saved_path;
        !          3592: 
        !          3593:   LT_DLMUTEX_LOCK ();
        !          3594:   saved_path = user_search_path;
        !          3595:   LT_DLMUTEX_UNLOCK ();
        !          3596: 
        !          3597:   return saved_path;
1.1       paf      3598: }
                   3599: 
1.2     ! paf      3600: int
        !          3601: lt_dlmakeresident (handle)
        !          3602:      lt_dlhandle handle;
1.1       paf      3603: {
1.2     ! paf      3604:   int errors = 0;
        !          3605: 
        !          3606:   if (!handle)
        !          3607:     {
        !          3608:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
        !          3609:       ++errors;
        !          3610:     }
        !          3611:   else
        !          3612:     {
        !          3613:       LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
        !          3614:     }
        !          3615: 
        !          3616:   return errors;
1.1       paf      3617: }
                   3618: 
1.2     ! paf      3619: int
        !          3620: lt_dlisresident        (handle)
        !          3621:      lt_dlhandle handle;
1.1       paf      3622: {
1.2     ! paf      3623:   if (!handle)
        !          3624:     {
        !          3625:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
        !          3626:       return -1;
        !          3627:     }
        !          3628: 
        !          3629:   return LT_DLIS_RESIDENT (handle);
1.1       paf      3630: }
                   3631: 
1.2     ! paf      3632: 
        !          3633: 
        !          3634: 
        !          3635: /* --- MODULE INFORMATION --- */
        !          3636: 
        !          3637: const lt_dlinfo *
        !          3638: lt_dlgetinfo (handle)
        !          3639:      lt_dlhandle handle;
        !          3640: {
        !          3641:   if (!handle)
        !          3642:     {
        !          3643:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
        !          3644:       return 0;
        !          3645:     }
        !          3646: 
        !          3647:   return &(handle->info);
1.1       paf      3648: }
                   3649: 
                   3650: lt_dlhandle
1.2     ! paf      3651: lt_dlhandle_next (place)
        !          3652:      lt_dlhandle place;
1.1       paf      3653: {
1.2     ! paf      3654:   return place ? place->next : handles;
1.1       paf      3655: }
                   3656: 
1.2     ! paf      3657: int
        !          3658: lt_dlforeach (func, data)
        !          3659:      int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
        !          3660:      lt_ptr data;
1.1       paf      3661: {
1.2     ! paf      3662:   int errors = 0;
        !          3663:   lt_dlhandle cur;
        !          3664: 
        !          3665:   LT_DLMUTEX_LOCK ();
        !          3666: 
        !          3667:   cur = handles;
        !          3668:   while (cur)
        !          3669:     {
        !          3670:       lt_dlhandle tmp = cur;
        !          3671: 
        !          3672:       cur = cur->next;
        !          3673:       if ((*func) (tmp, data))
        !          3674:        {
        !          3675:          ++errors;
        !          3676:          break;
1.1       paf      3677:        }
1.2     ! paf      3678:     }
        !          3679: 
        !          3680:   LT_DLMUTEX_UNLOCK ();
        !          3681: 
        !          3682:   return errors;
1.1       paf      3683: }
                   3684: 
1.2     ! paf      3685: lt_dlcaller_id
        !          3686: lt_dlcaller_register ()
1.1       paf      3687: {
1.2     ! paf      3688:   static lt_dlcaller_id last_caller_id = 0;
        !          3689:   int result;
        !          3690: 
        !          3691:   LT_DLMUTEX_LOCK ();
        !          3692:   result = ++last_caller_id;
        !          3693:   LT_DLMUTEX_UNLOCK ();
        !          3694: 
        !          3695:   return result;
1.1       paf      3696: }
                   3697: 
1.2     ! paf      3698: lt_ptr
        !          3699: lt_dlcaller_set_data (key, handle, data)
        !          3700:      lt_dlcaller_id key;
        !          3701:      lt_dlhandle handle;
        !          3702:      lt_ptr data;
1.1       paf      3703: {
1.2     ! paf      3704:   int n_elements = 0;
        !          3705:   lt_ptr stale = NULL;
        !          3706:   int i;
        !          3707: 
        !          3708:   /* This needs to be locked so that the caller data can be updated
        !          3709:      simultaneously by different threads.  */
        !          3710:   LT_DLMUTEX_LOCK ();
        !          3711: 
        !          3712:   if (handle->caller_data)
        !          3713:     while (handle->caller_data[n_elements].key)
        !          3714:       ++n_elements;
        !          3715: 
        !          3716:   for (i = 0; i < n_elements; ++i)
        !          3717:     {
        !          3718:       if (handle->caller_data[i].key == key)
        !          3719:        {
        !          3720:          stale = handle->caller_data[i].data;
        !          3721:          break;
        !          3722:        }
        !          3723:     }
        !          3724: 
        !          3725:   /* Ensure that there is enough room in this handle's caller_data
        !          3726:      array to accept a new element (and an empty end marker).  */
        !          3727:   if (i == n_elements)
        !          3728:     {
        !          3729:       lt_caller_data *temp
        !          3730:        = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
        !          3731: 
        !          3732:       if (!temp)
        !          3733:        {
        !          3734:          stale = NULL;
        !          3735:          goto done;
1.1       paf      3736:        }
1.2     ! paf      3737: 
        !          3738:       handle->caller_data = temp;
        !          3739: 
        !          3740:       /* We only need this if we needed to allocate a new caller_data.  */
        !          3741:       handle->caller_data[i].key  = key;
        !          3742:       handle->caller_data[1+ i].key = 0;
        !          3743:     }
        !          3744: 
        !          3745:   handle->caller_data[i].data = data;
        !          3746: 
        !          3747:  done:
        !          3748:   LT_DLMUTEX_UNLOCK ();
        !          3749: 
        !          3750:   return stale;
1.1       paf      3751: }
                   3752: 
1.2     ! paf      3753: lt_ptr
        !          3754: lt_dlcaller_get_data  (key, handle)
        !          3755:      lt_dlcaller_id key;
        !          3756:      lt_dlhandle handle;
1.1       paf      3757: {
1.2     ! paf      3758:   lt_ptr result = (lt_ptr) 0;
        !          3759: 
        !          3760:   /* This needs to be locked so that the caller data isn't updated by
        !          3761:      another thread part way through this function.  */
        !          3762:   LT_DLMUTEX_LOCK ();
        !          3763: 
        !          3764:   /* Locate the index of the element with a matching KEY.  */
        !          3765:   {
        !          3766:     int i;
        !          3767:     for (i = 0; handle->caller_data[i].key; ++i)
        !          3768:       {
        !          3769:        if (handle->caller_data[i].key == key)
        !          3770:          {
        !          3771:            result = handle->caller_data[i].data;
        !          3772:            break;
        !          3773:          }
        !          3774:       }
        !          3775:   }
        !          3776: 
        !          3777:   LT_DLMUTEX_UNLOCK ();
        !          3778: 
        !          3779:   return result;
1.1       paf      3780: }
                   3781: 
1.2     ! paf      3782: 
        !          3783: 
        !          3784: /* --- USER MODULE LOADER API --- */
        !          3785: 
        !          3786: 
1.1       paf      3787: int
1.2     ! paf      3788: lt_dlloader_add (place, dlloader, loader_name)
        !          3789:      lt_dlloader *place;
        !          3790:      const struct lt_user_dlloader *dlloader;
        !          3791:      const char *loader_name;
        !          3792: {
        !          3793:   int errors = 0;
        !          3794:   lt_dlloader *node = NULL, *ptr = NULL;
        !          3795: 
        !          3796:   if ((dlloader == NULL)       /* diagnose null parameters */
        !          3797:       || (dlloader->module_open == NULL)
        !          3798:       || (dlloader->module_close == NULL)
        !          3799:       || (dlloader->find_sym == NULL))
        !          3800:     {
        !          3801:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
        !          3802:       return 1;
        !          3803:     }
        !          3804: 
        !          3805:   /* Create a new dlloader node with copies of the user callbacks.  */
        !          3806:   node = LT_EMALLOC (lt_dlloader, 1);
        !          3807:   if (!node)
        !          3808:     return 1;
        !          3809: 
        !          3810:   node->next           = NULL;
        !          3811:   node->loader_name    = loader_name;
        !          3812:   node->sym_prefix     = dlloader->sym_prefix;
        !          3813:   node->dlloader_exit  = dlloader->dlloader_exit;
        !          3814:   node->module_open    = dlloader->module_open;
        !          3815:   node->module_close   = dlloader->module_close;
        !          3816:   node->find_sym       = dlloader->find_sym;
        !          3817:   node->dlloader_data  = dlloader->dlloader_data;
        !          3818: 
        !          3819:   LT_DLMUTEX_LOCK ();
        !          3820:   if (!loaders)
        !          3821:     {
        !          3822:       /* If there are no loaders, NODE becomes the list! */
        !          3823:       loaders = node;
        !          3824:     }
        !          3825:   else if (!place)
        !          3826:     {
        !          3827:       /* If PLACE is not set, add NODE to the end of the
        !          3828:         LOADERS list. */
        !          3829:       for (ptr = loaders; ptr->next; ptr = ptr->next)
        !          3830:        {
        !          3831:          /*NOWORK*/;
        !          3832:        }
        !          3833: 
        !          3834:       ptr->next = node;
        !          3835:     }
        !          3836:   else if (loaders == place)
        !          3837:     {
        !          3838:       /* If PLACE is the first loader, NODE goes first. */
        !          3839:       node->next = place;
        !          3840:       loaders = node;
        !          3841:     }
        !          3842:   else
        !          3843:     {
        !          3844:       /* Find the node immediately preceding PLACE. */
        !          3845:       for (ptr = loaders; ptr->next != place; ptr = ptr->next)
        !          3846:        {
        !          3847:          /*NOWORK*/;
        !          3848:        }
        !          3849: 
        !          3850:       if (ptr->next != place)
        !          3851:        {
        !          3852:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
        !          3853:          ++errors;
        !          3854:        }
        !          3855:       else
        !          3856:        {
        !          3857:          /* Insert NODE between PTR and PLACE. */
        !          3858:          node->next = place;
        !          3859:          ptr->next  = node;
1.1       paf      3860:        }
1.2     ! paf      3861:     }
        !          3862: 
        !          3863:   LT_DLMUTEX_UNLOCK ();
        !          3864: 
        !          3865:   return errors;
1.1       paf      3866: }
                   3867: 
                   3868: int
1.2     ! paf      3869: lt_dlloader_remove (loader_name)
        !          3870:      const char *loader_name;
1.1       paf      3871: {
1.2     ! paf      3872:   lt_dlloader *place = lt_dlloader_find (loader_name);
        !          3873:   lt_dlhandle handle;
        !          3874:   int errors = 0;
        !          3875: 
        !          3876:   if (!place)
        !          3877:     {
        !          3878:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
        !          3879:       return 1;
        !          3880:     }
        !          3881: 
        !          3882:   LT_DLMUTEX_LOCK ();
        !          3883: 
        !          3884:   /* Fail if there are any open modules which use this loader. */
        !          3885:   for  (handle = handles; handle; handle = handle->next)
        !          3886:     {
        !          3887:       if (handle->loader == place)
        !          3888:        {
        !          3889:          LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
        !          3890:          ++errors;
        !          3891:          goto done;
        !          3892:        }
        !          3893:     }
        !          3894: 
        !          3895:   if (place == loaders)
        !          3896:     {
        !          3897:       /* PLACE is the first loader in the list. */
        !          3898:       loaders = loaders->next;
        !          3899:     }
        !          3900:   else
        !          3901:     {
        !          3902:       /* Find the loader before the one being removed. */
        !          3903:       lt_dlloader *prev;
        !          3904:       for (prev = loaders; prev->next; prev = prev->next)
        !          3905:        {
        !          3906:          if (!strcmp (prev->next->loader_name, loader_name))
        !          3907:            {
        !          3908:              break;
        !          3909:            }
        !          3910:        }
        !          3911: 
        !          3912:       place = prev->next;
        !          3913:       prev->next = prev->next->next;
        !          3914:     }
        !          3915: 
        !          3916:   if (place->dlloader_exit)
        !          3917:     {
        !          3918:       errors = place->dlloader_exit (place->dlloader_data);
        !          3919:     }
        !          3920: 
        !          3921:   LT_DLFREE (place);
        !          3922: 
        !          3923:  done:
        !          3924:   LT_DLMUTEX_UNLOCK ();
        !          3925: 
        !          3926:   return errors;
        !          3927: }
        !          3928: 
        !          3929: lt_dlloader *
        !          3930: lt_dlloader_next (place)
        !          3931:      lt_dlloader *place;
        !          3932: {
        !          3933:   lt_dlloader *next;
        !          3934: 
        !          3935:   LT_DLMUTEX_LOCK ();
        !          3936:   next = place ? place->next : loaders;
        !          3937:   LT_DLMUTEX_UNLOCK ();
        !          3938: 
        !          3939:   return next;
1.1       paf      3940: }
                   3941: 
                   3942: const char *
1.2     ! paf      3943: lt_dlloader_name (place)
        !          3944:      lt_dlloader *place;
1.1       paf      3945: {
1.2     ! paf      3946:   const char *name = NULL;
        !          3947: 
        !          3948:   if (place)
        !          3949:     {
        !          3950:       LT_DLMUTEX_LOCK ();
        !          3951:       name = place ? place->loader_name : 0;
        !          3952:       LT_DLMUTEX_UNLOCK ();
        !          3953:     }
        !          3954:   else
        !          3955:     {
        !          3956:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
        !          3957:     }
        !          3958: 
        !          3959:   return name;
        !          3960: }
        !          3961: 
        !          3962: lt_user_data *
        !          3963: lt_dlloader_data (place)
        !          3964:      lt_dlloader *place;
        !          3965: {
        !          3966:   lt_user_data *data = NULL;
        !          3967: 
        !          3968:   if (place)
        !          3969:     {
        !          3970:       LT_DLMUTEX_LOCK ();
        !          3971:       data = place ? &(place->dlloader_data) : 0;
        !          3972:       LT_DLMUTEX_UNLOCK ();
        !          3973:     }
        !          3974:   else
        !          3975:     {
        !          3976:       LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
        !          3977:     }
        !          3978: 
        !          3979:   return data;
        !          3980: }
        !          3981: 
        !          3982: lt_dlloader *
        !          3983: lt_dlloader_find (loader_name)
        !          3984:      const char *loader_name;
        !          3985: {
        !          3986:   lt_dlloader *place = NULL;
        !          3987: 
        !          3988:   LT_DLMUTEX_LOCK ();
        !          3989:   for (place = loaders; place; place = place->next)
        !          3990:     {
        !          3991:       if (strcmp (place->loader_name, loader_name) == 0)
        !          3992:        {
        !          3993:          break;
        !          3994:        }
        !          3995:     }
        !          3996:   LT_DLMUTEX_UNLOCK ();
        !          3997: 
        !          3998:   return place;
1.1       paf      3999: }

E-mail: