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