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