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

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

E-mail: