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

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

unix.superglobalmegacorp.com

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