Annotation of tme/libltdl/ltdl.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.