PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/src/pdsh/ltdl.c

https://code.google.com/
C | 2913 lines | 2759 code | 104 blank | 50 comment | 45 complexity | 270520d0c8c51fe11acdf7caae0aea9f MD5 | raw file
Possible License(s): GPL-2.0
  1. /* ltdl.c -- system independent dlopen wrapper
  2. Copyright (C) 1998, 1999, 2000, 2004, 2005 Free Software Foundation, Inc.
  3. Originally by Thomas Tanner <tanner@ffii.org>
  4. This file is part of GNU Libtool.
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9. As a special exception to the GNU Lesser General Public License,
  10. if you distribute this file as part of a program or library that
  11. is built using GNU libtool, you may include it under the same
  12. distribution terms that you use for the rest of that program.
  13. This library is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. Lesser General Public License for more details.
  17. You should have received a copy of the GNU Lesser General Public
  18. License along with this library; if not, write to the Free Software
  19. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20. 02110-1301 USA
  21. */
  22. #if HAVE_CONFIG_H
  23. # include <config.h>
  24. #endif
  25. #if HAVE_UNISTD_H
  26. # include <unistd.h>
  27. #endif
  28. #if HAVE_STDIO_H
  29. # include <stdio.h>
  30. #endif
  31. /* Include the header defining malloc. On K&R C compilers,
  32. that's <malloc.h>, on ANSI C and ISO C compilers, that's <stdlib.h>. */
  33. #if HAVE_STDLIB_H
  34. # include <stdlib.h>
  35. #else
  36. # if HAVE_MALLOC_H
  37. # include <malloc.h>
  38. # endif
  39. #endif
  40. #if HAVE_STRING_H
  41. # include <string.h>
  42. #else
  43. # if HAVE_STRINGS_H
  44. # include <strings.h>
  45. # endif
  46. #endif
  47. #if HAVE_CTYPE_H
  48. # include <ctype.h>
  49. #endif
  50. #if HAVE_MEMORY_H
  51. # include <memory.h>
  52. #endif
  53. #if HAVE_ERRNO_H
  54. # include <errno.h>
  55. #endif
  56. #ifndef __WINDOWS__
  57. # ifdef __WIN32__
  58. # define __WINDOWS__
  59. # endif
  60. #endif
  61. #undef LT_USE_POSIX_DIRENT
  62. #ifdef HAVE_CLOSEDIR
  63. # ifdef HAVE_OPENDIR
  64. # ifdef HAVE_READDIR
  65. # ifdef HAVE_DIRENT_H
  66. # define LT_USE_POSIX_DIRENT
  67. # endif /* HAVE_DIRENT_H */
  68. # endif /* HAVE_READDIR */
  69. # endif /* HAVE_OPENDIR */
  70. #endif /* HAVE_CLOSEDIR */
  71. #undef LT_USE_WINDOWS_DIRENT_EMULATION
  72. #ifndef LT_USE_POSIX_DIRENT
  73. # ifdef __WINDOWS__
  74. # define LT_USE_WINDOWS_DIRENT_EMULATION
  75. # endif /* __WINDOWS__ */
  76. #endif /* LT_USE_POSIX_DIRENT */
  77. #ifdef LT_USE_POSIX_DIRENT
  78. # include <dirent.h>
  79. # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
  80. #else
  81. # ifdef LT_USE_WINDOWS_DIRENT_EMULATION
  82. # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
  83. # else
  84. # define dirent direct
  85. # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
  86. # if HAVE_SYS_NDIR_H
  87. # include <sys/ndir.h>
  88. # endif
  89. # if HAVE_SYS_DIR_H
  90. # include <sys/dir.h>
  91. # endif
  92. # if HAVE_NDIR_H
  93. # include <ndir.h>
  94. # endif
  95. # endif
  96. #endif
  97. #if HAVE_ARGZ_H
  98. # include <argz.h>
  99. #endif
  100. #if HAVE_ASSERT_H
  101. # include <assert.h>
  102. #else
  103. # define assert(arg) ((void) 0)
  104. #endif
  105. #include "ltdl.h"
  106. #if WITH_DMALLOC
  107. # include <dmalloc.h>
  108. #endif
  109. /* --- WINDOWS SUPPORT --- */
  110. #ifdef DLL_EXPORT
  111. # define LT_GLOBAL_DATA __declspec(dllexport)
  112. #else
  113. # define LT_GLOBAL_DATA
  114. #endif
  115. /* fopen() mode flags for reading a text file */
  116. #undef LT_READTEXT_MODE
  117. #ifdef __WINDOWS__
  118. # define LT_READTEXT_MODE "rt"
  119. #else
  120. # define LT_READTEXT_MODE "r"
  121. #endif
  122. #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
  123. #include <windows.h>
  124. #define dirent lt_dirent
  125. #define DIR lt_DIR
  126. struct dirent
  127. {
  128. char d_name[2048];
  129. int d_namlen;
  130. };
  131. typedef struct _DIR
  132. {
  133. HANDLE hSearch;
  134. WIN32_FIND_DATA Win32FindData;
  135. BOOL firsttime;
  136. struct dirent file_info;
  137. } DIR;
  138. #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
  139. /* --- MANIFEST CONSTANTS --- */
  140. /* Standard libltdl search path environment variable name */
  141. #undef LTDL_SEARCHPATH_VAR
  142. #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
  143. /* Standard libtool archive file extension. */
  144. #undef LTDL_ARCHIVE_EXT
  145. #define LTDL_ARCHIVE_EXT ".la"
  146. /* max. filename length */
  147. #ifndef LT_FILENAME_MAX
  148. # define LT_FILENAME_MAX 1024
  149. #endif
  150. /* This is the maximum symbol size that won't require malloc/free */
  151. #undef LT_SYMBOL_LENGTH
  152. #define LT_SYMBOL_LENGTH 128
  153. /* This accounts for the _LTX_ separator */
  154. #undef LT_SYMBOL_OVERHEAD
  155. #define LT_SYMBOL_OVERHEAD 5
  156. /* --- MEMORY HANDLING --- */
  157. /* These are the functions used internally. In addition to making
  158. use of the associated function pointers above, they also perform
  159. error handling. */
  160. static char *lt_estrdup LT_PARAMS((const char *str));
  161. static lt_ptr lt_emalloc LT_PARAMS((size_t size));
  162. static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
  163. /* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */
  164. #define rpl_realloc realloc
  165. /* These are the pointers that can be changed by the caller: */
  166. LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
  167. = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
  168. LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
  169. = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
  170. LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
  171. = (void (*) LT_PARAMS((lt_ptr))) free;
  172. /* The following macros reduce the amount of typing needed to cast
  173. assigned memory. */
  174. #if WITH_DMALLOC
  175. #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
  176. #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
  177. #define LT_DLFREE(p) \
  178. LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
  179. #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
  180. #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
  181. #else
  182. #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
  183. #define LT_DLREALLOC(tp, p, n) ((tp *) lt_dlrealloc ((p), (n) * sizeof(tp)))
  184. #define LT_DLFREE(p) \
  185. LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
  186. #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
  187. #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
  188. #endif
  189. #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
  190. if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
  191. } LT_STMT_END
  192. /* --- REPLACEMENT FUNCTIONS --- */
  193. #undef strdup
  194. #define strdup rpl_strdup
  195. static char *strdup LT_PARAMS((const char *str));
  196. static char *
  197. strdup(str)
  198. const char *str;
  199. {
  200. char *tmp = 0;
  201. if (str)
  202. {
  203. tmp = LT_DLMALLOC (char, 1+ strlen (str));
  204. if (tmp)
  205. {
  206. strcpy(tmp, str);
  207. }
  208. }
  209. return tmp;
  210. }
  211. #if ! HAVE_STRCMP
  212. #undef strcmp
  213. #define strcmp rpl_strcmp
  214. static int strcmp LT_PARAMS((const char *str1, const char *str2));
  215. static int
  216. strcmp (str1, str2)
  217. const char *str1;
  218. const char *str2;
  219. {
  220. if (str1 == str2)
  221. return 0;
  222. if (str1 == 0)
  223. return -1;
  224. if (str2 == 0)
  225. return 1;
  226. for (;*str1 && *str2; ++str1, ++str2)
  227. {
  228. if (*str1 != *str2)
  229. break;
  230. }
  231. return (int)(*str1 - *str2);
  232. }
  233. #endif
  234. #if ! HAVE_STRCHR
  235. # if HAVE_INDEX
  236. # define strchr index
  237. # else
  238. # define strchr rpl_strchr
  239. static const char *strchr LT_PARAMS((const char *str, int ch));
  240. static const char*
  241. strchr(str, ch)
  242. const char *str;
  243. int ch;
  244. {
  245. const char *p;
  246. for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
  247. /*NOWORK*/;
  248. return (*p == (char)ch) ? p : 0;
  249. }
  250. # endif
  251. #endif /* !HAVE_STRCHR */
  252. #if ! HAVE_STRRCHR
  253. # if HAVE_RINDEX
  254. # define strrchr rindex
  255. # else
  256. # define strrchr rpl_strrchr
  257. static const char *strrchr LT_PARAMS((const char *str, int ch));
  258. static const char*
  259. strrchr(str, ch)
  260. const char *str;
  261. int ch;
  262. {
  263. const char *p, *q = 0;
  264. for (p = str; *p != LT_EOS_CHAR; ++p)
  265. {
  266. if (*p == (char) ch)
  267. {
  268. q = p;
  269. }
  270. }
  271. return q;
  272. }
  273. # endif
  274. #endif
  275. /* NOTE: Neither bcopy nor the memcpy implementation below can
  276. reliably handle copying in overlapping areas of memory. Use
  277. memmove (for which there is a fallback implmentation below)
  278. if you need that behaviour. */
  279. #if ! HAVE_MEMCPY
  280. # if HAVE_BCOPY
  281. # define memcpy(dest, src, size) bcopy (src, dest, size)
  282. # else
  283. # define memcpy rpl_memcpy
  284. static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
  285. static lt_ptr
  286. memcpy (dest, src, size)
  287. lt_ptr dest;
  288. const lt_ptr src;
  289. size_t size;
  290. {
  291. const char * s = src;
  292. char * d = dest;
  293. size_t i = 0;
  294. for (i = 0; i < size; ++i)
  295. {
  296. d[i] = s[i];
  297. }
  298. return dest;
  299. }
  300. # endif /* !HAVE_BCOPY */
  301. #endif /* !HAVE_MEMCPY */
  302. #if ! HAVE_MEMMOVE
  303. # define memmove rpl_memmove
  304. static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
  305. static lt_ptr
  306. memmove (dest, src, size)
  307. lt_ptr dest;
  308. const lt_ptr src;
  309. size_t size;
  310. {
  311. const char * s = src;
  312. char * d = dest;
  313. size_t i;
  314. if (d < s)
  315. for (i = 0; i < size; ++i)
  316. {
  317. d[i] = s[i];
  318. }
  319. else if (d > s && size > 0)
  320. for (i = size -1; ; --i)
  321. {
  322. d[i] = s[i];
  323. if (i == 0)
  324. break;
  325. }
  326. return dest;
  327. }
  328. #endif /* !HAVE_MEMMOVE */
  329. #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
  330. static void closedir LT_PARAMS((DIR *entry));
  331. static void
  332. closedir(entry)
  333. DIR *entry;
  334. {
  335. assert(entry != (DIR *) NULL);
  336. FindClose(entry->hSearch);
  337. lt_dlfree((lt_ptr)entry);
  338. }
  339. static DIR * opendir LT_PARAMS((const char *path));
  340. static DIR*
  341. opendir (path)
  342. const char *path;
  343. {
  344. char file_specification[LT_FILENAME_MAX];
  345. DIR *entry;
  346. assert(path != (char *) NULL);
  347. /* allow space for: path + '\\' '\\' '*' '.' '*' + '\0' */
  348. (void) strncpy (file_specification, path, LT_FILENAME_MAX-6);
  349. file_specification[LT_FILENAME_MAX-6] = LT_EOS_CHAR;
  350. (void) strcat(file_specification,"\\");
  351. entry = LT_DLMALLOC (DIR,sizeof(DIR));
  352. if (entry != (DIR *) 0)
  353. {
  354. entry->firsttime = TRUE;
  355. entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
  356. }
  357. if (entry->hSearch == INVALID_HANDLE_VALUE)
  358. {
  359. (void) strcat(file_specification,"\\*.*");
  360. entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
  361. if (entry->hSearch == INVALID_HANDLE_VALUE)
  362. {
  363. LT_DLFREE (entry);
  364. return (DIR *) 0;
  365. }
  366. }
  367. return(entry);
  368. }
  369. static struct dirent *readdir LT_PARAMS((DIR *entry));
  370. static struct dirent *readdir(entry)
  371. DIR *entry;
  372. {
  373. int
  374. status;
  375. if (entry == (DIR *) 0)
  376. return((struct dirent *) 0);
  377. if (!entry->firsttime)
  378. {
  379. status = FindNextFile(entry->hSearch,&entry->Win32FindData);
  380. if (status == 0)
  381. return((struct dirent *) 0);
  382. }
  383. entry->firsttime = FALSE;
  384. (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
  385. LT_FILENAME_MAX-1);
  386. entry->file_info.d_name[LT_FILENAME_MAX - 1] = LT_EOS_CHAR;
  387. entry->file_info.d_namlen = strlen(entry->file_info.d_name);
  388. return(&entry->file_info);
  389. }
  390. #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
  391. /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
  392. ``realloc is not entirely portable''
  393. In any case we want to use the allocator supplied by the user without
  394. burdening them with an lt_dlrealloc function pointer to maintain.
  395. Instead implement our own version (with known boundary conditions)
  396. using lt_dlmalloc and lt_dlfree. */
  397. /* #undef realloc
  398. #define realloc rpl_realloc
  399. */
  400. #if 0
  401. /* You can't (re)define realloc unless you also (re)define malloc.
  402. Right now, this code uses the size of the *destination* to decide
  403. how much to copy. That's not right, but you can't know the size
  404. of the source unless you know enough about, or wrote malloc. So
  405. this code is disabled... */
  406. static lt_ptr
  407. realloc (ptr, size)
  408. lt_ptr ptr;
  409. size_t size;
  410. {
  411. if (size == 0)
  412. {
  413. /* For zero or less bytes, free the original memory */
  414. if (ptr != 0)
  415. {
  416. lt_dlfree (ptr);
  417. }
  418. return (lt_ptr) 0;
  419. }
  420. else if (ptr == 0)
  421. {
  422. /* Allow reallocation of a NULL pointer. */
  423. return lt_dlmalloc (size);
  424. }
  425. else
  426. {
  427. /* Allocate a new block, copy and free the old block. */
  428. lt_ptr mem = lt_dlmalloc (size);
  429. if (mem)
  430. {
  431. memcpy (mem, ptr, size);
  432. lt_dlfree (ptr);
  433. }
  434. /* Note that the contents of PTR are not damaged if there is
  435. insufficient memory to realloc. */
  436. return mem;
  437. }
  438. }
  439. #endif
  440. #if ! HAVE_ARGZ_APPEND
  441. # define argz_append rpl_argz_append
  442. static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
  443. const char *buf, size_t buf_len));
  444. static error_t
  445. argz_append (pargz, pargz_len, buf, buf_len)
  446. char **pargz;
  447. size_t *pargz_len;
  448. const char *buf;
  449. size_t buf_len;
  450. {
  451. size_t argz_len;
  452. char *argz;
  453. assert (pargz);
  454. assert (pargz_len);
  455. assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
  456. /* If nothing needs to be appended, no more work is required. */
  457. if (buf_len == 0)
  458. return 0;
  459. /* Ensure there is enough room to append BUF_LEN. */
  460. argz_len = *pargz_len + buf_len;
  461. argz = LT_DLREALLOC (char, *pargz, argz_len);
  462. if (!argz)
  463. return ENOMEM;
  464. /* Copy characters from BUF after terminating '\0' in ARGZ. */
  465. memcpy (argz + *pargz_len, buf, buf_len);
  466. /* Assign new values. */
  467. *pargz = argz;
  468. *pargz_len = argz_len;
  469. return 0;
  470. }
  471. #endif /* !HAVE_ARGZ_APPEND */
  472. #if ! HAVE_ARGZ_CREATE_SEP
  473. # define argz_create_sep rpl_argz_create_sep
  474. static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
  475. char **pargz, size_t *pargz_len));
  476. static error_t
  477. argz_create_sep (str, delim, pargz, pargz_len)
  478. const char *str;
  479. int delim;
  480. char **pargz;
  481. size_t *pargz_len;
  482. {
  483. size_t argz_len;
  484. char *argz = 0;
  485. assert (str);
  486. assert (pargz);
  487. assert (pargz_len);
  488. /* Make a copy of STR, but replacing each occurrence of
  489. DELIM with '\0'. */
  490. argz_len = 1+ LT_STRLEN (str);
  491. if (argz_len)
  492. {
  493. const char *p;
  494. char *q;
  495. argz = LT_DLMALLOC (char, argz_len);
  496. if (!argz)
  497. return ENOMEM;
  498. for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
  499. {
  500. if (*p == delim)
  501. {
  502. /* Ignore leading delimiters, and fold consecutive
  503. delimiters in STR into a single '\0' in ARGZ. */
  504. if ((q > argz) && (q[-1] != LT_EOS_CHAR))
  505. *q++ = LT_EOS_CHAR;
  506. else
  507. --argz_len;
  508. }
  509. else
  510. *q++ = *p;
  511. }
  512. /* Copy terminating LT_EOS_CHAR. */
  513. *q = *p;
  514. }
  515. /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
  516. if (!argz_len)
  517. LT_DLFREE (argz);
  518. /* Assign new values. */
  519. *pargz = argz;
  520. *pargz_len = argz_len;
  521. return 0;
  522. }
  523. #endif /* !HAVE_ARGZ_CREATE_SEP */
  524. #if ! HAVE_ARGZ_INSERT
  525. # define argz_insert rpl_argz_insert
  526. static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
  527. char *before, const char *entry));
  528. static error_t
  529. argz_insert (pargz, pargz_len, before, entry)
  530. char **pargz;
  531. size_t *pargz_len;
  532. char *before;
  533. const char *entry;
  534. {
  535. assert (pargz);
  536. assert (pargz_len);
  537. assert (entry && *entry);
  538. /* No BEFORE address indicates ENTRY should be inserted after the
  539. current last element. */
  540. if (!before)
  541. return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
  542. /* This probably indicates a programmer error, but to preserve
  543. semantics, scan back to the start of an entry if BEFORE points
  544. into the middle of it. */
  545. while ((before > *pargz) && (before[-1] != LT_EOS_CHAR))
  546. --before;
  547. {
  548. size_t entry_len = 1+ LT_STRLEN (entry);
  549. size_t argz_len = *pargz_len + entry_len;
  550. size_t offset = before - *pargz;
  551. char *argz = LT_DLREALLOC (char, *pargz, argz_len);
  552. if (!argz)
  553. return ENOMEM;
  554. /* Make BEFORE point to the equivalent offset in ARGZ that it
  555. used to have in *PARGZ incase realloc() moved the block. */
  556. before = argz + offset;
  557. /* Move the ARGZ entries starting at BEFORE up into the new
  558. space at the end -- making room to copy ENTRY into the
  559. resulting gap. */
  560. memmove (before + entry_len, before, *pargz_len - offset);
  561. memcpy (before, entry, entry_len);
  562. /* Assign new values. */
  563. *pargz = argz;
  564. *pargz_len = argz_len;
  565. }
  566. return 0;
  567. }
  568. #endif /* !HAVE_ARGZ_INSERT */
  569. #if ! HAVE_ARGZ_NEXT
  570. # define argz_next rpl_argz_next
  571. static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
  572. const char *entry));
  573. static char *
  574. argz_next (argz, argz_len, entry)
  575. char *argz;
  576. size_t argz_len;
  577. const char *entry;
  578. {
  579. assert ((argz && argz_len) || (!argz && !argz_len));
  580. if (entry)
  581. {
  582. /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
  583. within the ARGZ vector. */
  584. assert ((!argz && !argz_len)
  585. || ((argz <= entry) && (entry < (argz + argz_len))));
  586. /* Move to the char immediately after the terminating
  587. '\0' of ENTRY. */
  588. entry = 1+ strchr (entry, LT_EOS_CHAR);
  589. /* Return either the new ENTRY, or else NULL if ARGZ is
  590. exhausted. */
  591. return (entry >= argz + argz_len) ? 0 : (char *) entry;
  592. }
  593. else
  594. {
  595. /* This should probably be flagged as a programmer error,
  596. since starting an argz_next loop with the iterator set
  597. to ARGZ is safer. To preserve semantics, handle the NULL
  598. case by returning the start of ARGZ (if any). */
  599. if (argz_len > 0)
  600. return argz;
  601. else
  602. return 0;
  603. }
  604. }
  605. #endif /* !HAVE_ARGZ_NEXT */
  606. #if ! HAVE_ARGZ_STRINGIFY
  607. # define argz_stringify rpl_argz_stringify
  608. static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
  609. int sep));
  610. static void
  611. argz_stringify (argz, argz_len, sep)
  612. char *argz;
  613. size_t argz_len;
  614. int sep;
  615. {
  616. assert ((argz && argz_len) || (!argz && !argz_len));
  617. if (sep)
  618. {
  619. --argz_len; /* don't stringify the terminating EOS */
  620. while (--argz_len > 0)
  621. {
  622. if (argz[argz_len] == LT_EOS_CHAR)
  623. argz[argz_len] = sep;
  624. }
  625. }
  626. }
  627. #endif /* !HAVE_ARGZ_STRINGIFY */
  628. /* --- TYPE DEFINITIONS -- */
  629. /* This type is used for the array of caller data sets in each handler. */
  630. typedef struct {
  631. lt_dlcaller_id key;
  632. lt_ptr data;
  633. } lt_caller_data;
  634. /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
  635. /* Extract the diagnostic strings from the error table macro in the same
  636. order as the enumerated indices in ltdl.h. */
  637. static const char *lt_dlerror_strings[] =
  638. {
  639. #define LT_ERROR(name, diagnostic) (diagnostic),
  640. lt_dlerror_table
  641. #undef LT_ERROR
  642. 0
  643. };
  644. /* This structure is used for the list of registered loaders. */
  645. struct lt_dlloader {
  646. struct lt_dlloader *next;
  647. const char *loader_name; /* identifying name for each loader */
  648. const char *sym_prefix; /* prefix for symbols */
  649. lt_module_open *module_open;
  650. lt_module_close *module_close;
  651. lt_find_sym *find_sym;
  652. lt_dlloader_exit *dlloader_exit;
  653. lt_user_data dlloader_data;
  654. };
  655. struct lt_dlhandle_struct {
  656. struct lt_dlhandle_struct *next;
  657. lt_dlloader *loader; /* dlopening interface */
  658. lt_dlinfo info;
  659. int depcount; /* number of dependencies */
  660. lt_dlhandle *deplibs; /* dependencies */
  661. lt_module module; /* system module handle */
  662. lt_ptr system; /* system specific data */
  663. lt_caller_data *caller_data; /* per caller associated data */
  664. int flags; /* various boolean stats */
  665. };
  666. /* Various boolean flags can be stored in the flags field of an
  667. lt_dlhandle_struct... */
  668. #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
  669. #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
  670. #define LT_DLRESIDENT_FLAG (0x01 << 0)
  671. /* ...add more flags here... */
  672. #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
  673. #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
  674. static const char objdir[] = LTDL_OBJDIR;
  675. static const char archive_ext[] = LTDL_ARCHIVE_EXT;
  676. #ifdef LTDL_SHLIB_EXT
  677. static const char shlib_ext[] = LTDL_SHLIB_EXT;
  678. #endif
  679. #ifdef LTDL_SYSSEARCHPATH
  680. static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
  681. #endif
  682. /* --- MUTEX LOCKING --- */
  683. /* Macros to make it easier to run the lock functions only if they have
  684. been registered. The reason for the complicated lock macro is to
  685. ensure that the stored error message from the last error is not
  686. accidentally erased if the current function doesn't generate an
  687. error of its own. */
  688. #define LT_DLMUTEX_LOCK() LT_STMT_START { \
  689. if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
  690. } LT_STMT_END
  691. #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
  692. if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
  693. } LT_STMT_END
  694. #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
  695. if (lt_dlmutex_seterror_func) \
  696. (*lt_dlmutex_seterror_func) (errormsg); \
  697. else lt_dllast_error = (errormsg); } LT_STMT_END
  698. #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
  699. if (lt_dlmutex_geterror_func) \
  700. (errormsg) = (*lt_dlmutex_geterror_func) (); \
  701. else (errormsg) = lt_dllast_error; } LT_STMT_END
  702. /* The mutex functions stored here are global, and are necessarily the
  703. same for all threads that wish to share access to libltdl. */
  704. static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
  705. static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
  706. static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
  707. static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
  708. static const char *lt_dllast_error = 0;
  709. /* Either set or reset the mutex functions. Either all the arguments must
  710. be valid functions, or else all can be NULL to turn off locking entirely.
  711. The registered functions should be manipulating a static global lock
  712. from the lock() and unlock() callbacks, which needs to be reentrant. */
  713. int
  714. lt_dlmutex_register (lock, unlock, seterror, geterror)
  715. lt_dlmutex_lock *lock;
  716. lt_dlmutex_unlock *unlock;
  717. lt_dlmutex_seterror *seterror;
  718. lt_dlmutex_geterror *geterror;
  719. {
  720. lt_dlmutex_unlock *old_unlock = unlock;
  721. int errors = 0;
  722. /* Lock using the old lock() callback, if any. */
  723. LT_DLMUTEX_LOCK ();
  724. if ((lock && unlock && seterror && geterror)
  725. || !(lock || unlock || seterror || geterror))
  726. {
  727. lt_dlmutex_lock_func = lock;
  728. lt_dlmutex_unlock_func = unlock;
  729. lt_dlmutex_geterror_func = geterror;
  730. }
  731. else
  732. {
  733. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
  734. ++errors;
  735. }
  736. /* Use the old unlock() callback we saved earlier, if any. Otherwise
  737. record any errors using internal storage. */
  738. if (old_unlock)
  739. (*old_unlock) ();
  740. /* Return the number of errors encountered during the execution of
  741. this function. */
  742. return errors;
  743. }
  744. /* --- ERROR HANDLING --- */
  745. static const char **user_error_strings = 0;
  746. static int errorcount = LT_ERROR_MAX;
  747. int
  748. lt_dladderror (diagnostic)
  749. const char *diagnostic;
  750. {
  751. int errindex = 0;
  752. int result = -1;
  753. const char **temp = (const char **) 0;
  754. assert (diagnostic);
  755. LT_DLMUTEX_LOCK ();
  756. errindex = errorcount - LT_ERROR_MAX;
  757. temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
  758. if (temp)
  759. {
  760. user_error_strings = temp;
  761. user_error_strings[errindex] = diagnostic;
  762. result = errorcount++;
  763. }
  764. LT_DLMUTEX_UNLOCK ();
  765. return result;
  766. }
  767. int
  768. lt_dlseterror (errindex)
  769. int errindex;
  770. {
  771. int errors = 0;
  772. LT_DLMUTEX_LOCK ();
  773. if (errindex >= errorcount || errindex < 0)
  774. {
  775. /* Ack! Error setting the error message! */
  776. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
  777. ++errors;
  778. }
  779. else if (errindex < LT_ERROR_MAX)
  780. {
  781. /* No error setting the error message! */
  782. LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
  783. }
  784. else
  785. {
  786. /* No error setting the error message! */
  787. LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
  788. }
  789. LT_DLMUTEX_UNLOCK ();
  790. return errors;
  791. }
  792. static lt_ptr
  793. lt_emalloc (size)
  794. size_t size;
  795. {
  796. lt_ptr mem = lt_dlmalloc (size);
  797. if (size && !mem)
  798. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
  799. return mem;
  800. }
  801. static lt_ptr
  802. lt_erealloc (addr, size)
  803. lt_ptr addr;
  804. size_t size;
  805. {
  806. lt_ptr mem = lt_dlrealloc (addr, size);
  807. if (size && !mem)
  808. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
  809. return mem;
  810. }
  811. static char *
  812. lt_estrdup (str)
  813. const char *str;
  814. {
  815. char *copy = strdup (str);
  816. if (LT_STRLEN (str) && !copy)
  817. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
  818. return copy;
  819. }
  820. /* --- DLOPEN() INTERFACE LOADER --- */
  821. #if HAVE_LIBDL
  822. /* dynamic linking with dlopen/dlsym */
  823. #if HAVE_DLFCN_H
  824. # include <dlfcn.h>
  825. #endif
  826. #if HAVE_SYS_DL_H
  827. # include <sys/dl.h>
  828. #endif
  829. #ifdef RTLD_GLOBAL
  830. # define LT_GLOBAL RTLD_GLOBAL
  831. #else
  832. # ifdef DL_GLOBAL
  833. # define LT_GLOBAL DL_GLOBAL
  834. # endif
  835. #endif /* !RTLD_GLOBAL */
  836. #ifndef LT_GLOBAL
  837. # define LT_GLOBAL 0
  838. #endif /* !LT_GLOBAL */
  839. /* We may have to define LT_LAZY_OR_NOW in the command line if we
  840. find out it does not work in some platform. */
  841. #ifndef LT_LAZY_OR_NOW
  842. # ifdef RTLD_LAZY
  843. # define LT_LAZY_OR_NOW RTLD_LAZY
  844. # else
  845. # ifdef DL_LAZY
  846. # define LT_LAZY_OR_NOW DL_LAZY
  847. # endif
  848. # endif /* !RTLD_LAZY */
  849. #endif
  850. #ifndef LT_LAZY_OR_NOW
  851. # ifdef RTLD_NOW
  852. # define LT_LAZY_OR_NOW RTLD_NOW
  853. # else
  854. # ifdef DL_NOW
  855. # define LT_LAZY_OR_NOW DL_NOW
  856. # endif
  857. # endif /* !RTLD_NOW */
  858. #endif
  859. #ifndef LT_LAZY_OR_NOW
  860. # define LT_LAZY_OR_NOW 0
  861. #endif /* !LT_LAZY_OR_NOW */
  862. #if HAVE_DLERROR
  863. # define DLERROR(arg) dlerror ()
  864. #else
  865. # define DLERROR(arg) LT_DLSTRERROR (arg)
  866. #endif
  867. static lt_module
  868. sys_dl_open (loader_data, filename)
  869. lt_user_data loader_data;
  870. const char *filename;
  871. {
  872. lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
  873. if (!module)
  874. {
  875. LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
  876. }
  877. return module;
  878. }
  879. static int
  880. sys_dl_close (loader_data, module)
  881. lt_user_data loader_data;
  882. lt_module module;
  883. {
  884. int errors = 0;
  885. if (dlclose (module) != 0)
  886. {
  887. LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
  888. ++errors;
  889. }
  890. return errors;
  891. }
  892. static lt_ptr
  893. sys_dl_sym (loader_data, module, symbol)
  894. lt_user_data loader_data;
  895. lt_module module;
  896. const char *symbol;
  897. {
  898. lt_ptr address = dlsym (module, symbol);
  899. if (!address)
  900. {
  901. LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
  902. }
  903. return address;
  904. }
  905. static struct lt_user_dlloader sys_dl =
  906. {
  907. # ifdef NEED_USCORE
  908. "_",
  909. # else
  910. 0,
  911. # endif
  912. sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
  913. #endif /* HAVE_LIBDL */
  914. /* --- SHL_LOAD() INTERFACE LOADER --- */
  915. #if HAVE_SHL_LOAD
  916. /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
  917. #ifdef HAVE_DL_H
  918. # include <dl.h>
  919. #endif
  920. /* some flags are missing on some systems, so we provide
  921. * harmless defaults.
  922. *
  923. * Mandatory:
  924. * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
  925. * BIND_DEFERRED - Delay code symbol resolution until actual reference.
  926. *
  927. * Optionally:
  928. * BIND_FIRST - Place the library at the head of the symbol search
  929. * order.
  930. * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
  931. * unsatisfied symbols as fatal. This flag allows
  932. * binding of unsatisfied code symbols to be deferred
  933. * until use.
  934. * [Perl: For certain libraries, like DCE, deferred
  935. * binding often causes run time problems. Adding
  936. * BIND_NONFATAL to BIND_IMMEDIATE still allows
  937. * unresolved references in situations like this.]
  938. * BIND_NOSTART - Do not call the initializer for the shared library
  939. * when the library is loaded, nor on a future call to
  940. * shl_unload().
  941. * BIND_VERBOSE - Print verbose messages concerning possible
  942. * unsatisfied symbols.
  943. *
  944. * hp9000s700/hp9000s800:
  945. * BIND_RESTRICTED - Restrict symbols visible by the library to those
  946. * present at library load time.
  947. * DYNAMIC_PATH - Allow the loader to dynamically search for the
  948. * library specified by the path argument.
  949. */
  950. #ifndef DYNAMIC_PATH
  951. # define DYNAMIC_PATH 0
  952. #endif
  953. #ifndef BIND_RESTRICTED
  954. # define BIND_RESTRICTED 0
  955. #endif
  956. #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
  957. static lt_module
  958. sys_shl_open (loader_data, filename)
  959. lt_user_data loader_data;
  960. const char *filename;
  961. {
  962. static shl_t self = (shl_t) 0;
  963. lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
  964. /* Since searching for a symbol against a NULL module handle will also
  965. look in everything else that was already loaded and exported with
  966. the -E compiler flag, we always cache a handle saved before any
  967. modules are loaded. */
  968. if (!self)
  969. {
  970. lt_ptr address;
  971. shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
  972. }
  973. if (!filename)
  974. {
  975. module = self;
  976. }
  977. else
  978. {
  979. module = shl_load (filename, LT_BIND_FLAGS, 0L);
  980. if (!module)
  981. {
  982. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
  983. }
  984. }
  985. return module;
  986. }
  987. static int
  988. sys_shl_close (loader_data, module)
  989. lt_user_data loader_data;
  990. lt_module module;
  991. {
  992. int errors = 0;
  993. if (module && (shl_unload ((shl_t) (module)) != 0))
  994. {
  995. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
  996. ++errors;
  997. }
  998. return errors;
  999. }
  1000. static lt_ptr
  1001. sys_shl_sym (loader_data, module, symbol)
  1002. lt_user_data loader_data;
  1003. lt_module module;
  1004. const char *symbol;
  1005. {
  1006. lt_ptr address = 0;
  1007. /* sys_shl_open should never return a NULL module handle */
  1008. if (module == (lt_module) 0)
  1009. {
  1010. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
  1011. }
  1012. else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
  1013. {
  1014. if (!address)
  1015. {
  1016. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  1017. }
  1018. }
  1019. return address;
  1020. }
  1021. static struct lt_user_dlloader sys_shl = {
  1022. 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
  1023. };
  1024. #endif /* HAVE_SHL_LOAD */
  1025. /* --- LOADLIBRARY() INTERFACE LOADER --- */
  1026. #ifdef __WINDOWS__
  1027. /* dynamic linking for Win32 */
  1028. #include <windows.h>
  1029. /* Forward declaration; required to implement handle search below. */
  1030. static lt_dlhandle handles;
  1031. static lt_module
  1032. sys_wll_open (loader_data, filename)
  1033. lt_user_data loader_data;
  1034. const char *filename;
  1035. {
  1036. lt_dlhandle cur;
  1037. lt_module module = 0;
  1038. const char *errormsg = 0;
  1039. char *searchname = 0;
  1040. char *ext;
  1041. char self_name_buf[MAX_PATH];
  1042. if (!filename)
  1043. {
  1044. /* Get the name of main module */
  1045. *self_name_buf = 0;
  1046. GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
  1047. filename = ext = self_name_buf;
  1048. }
  1049. else
  1050. {
  1051. ext = strrchr (filename, '.');
  1052. }
  1053. if (ext)
  1054. {
  1055. /* FILENAME already has an extension. */
  1056. searchname = lt_estrdup (filename);
  1057. }
  1058. else
  1059. {
  1060. /* Append a `.' to stop Windows from adding an
  1061. implicit `.dll' extension. */
  1062. searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
  1063. if (searchname)
  1064. sprintf (searchname, "%s.", filename);
  1065. }
  1066. if (!searchname)
  1067. return 0;
  1068. {
  1069. /* Silence dialog from LoadLibrary on some failures.
  1070. No way to get the error mode, but to set it,
  1071. so set it twice to preserve any previous flags. */
  1072. UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
  1073. SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
  1074. #if defined(__CYGWIN__)
  1075. {
  1076. char wpath[MAX_PATH];
  1077. cygwin_conv_to_full_win32_path (searchname, wpath);
  1078. module = LoadLibrary (wpath);
  1079. }
  1080. #else
  1081. module = LoadLibrary (searchname);
  1082. #endif
  1083. /* Restore the error mode. */
  1084. SetErrorMode(errormode);
  1085. }
  1086. LT_DLFREE (searchname);
  1087. /* libltdl expects this function to fail if it is unable
  1088. to physically load the library. Sadly, LoadLibrary
  1089. will search the loaded libraries for a match and return
  1090. one of them if the path search load fails.
  1091. We check whether LoadLibrary is returning a handle to
  1092. an already loaded module, and simulate failure if we
  1093. find one. */
  1094. LT_DLMUTEX_LOCK ();
  1095. cur = handles;
  1096. while (cur)
  1097. {
  1098. if (!cur->module)
  1099. {
  1100. cur = 0;
  1101. break;
  1102. }
  1103. if (cur->module == module)
  1104. {
  1105. break;
  1106. }
  1107. cur = cur->next;
  1108. }
  1109. LT_DLMUTEX_UNLOCK ();
  1110. if (cur || !module)
  1111. {
  1112. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
  1113. module = 0;
  1114. }
  1115. return module;
  1116. }
  1117. static int
  1118. sys_wll_close (loader_data, module)
  1119. lt_user_data loader_data;
  1120. lt_module module;
  1121. {
  1122. int errors = 0;
  1123. if (FreeLibrary(module) == 0)
  1124. {
  1125. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
  1126. ++errors;
  1127. }
  1128. return errors;
  1129. }
  1130. static lt_ptr
  1131. sys_wll_sym (loader_data, module, symbol)
  1132. lt_user_data loader_data;
  1133. lt_module module;
  1134. const char *symbol;
  1135. {
  1136. lt_ptr address = GetProcAddress (module, symbol);
  1137. if (!address)
  1138. {
  1139. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  1140. }
  1141. return address;
  1142. }
  1143. static struct lt_user_dlloader sys_wll = {
  1144. 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
  1145. };
  1146. #endif /* __WINDOWS__ */
  1147. /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
  1148. #ifdef __BEOS__
  1149. /* dynamic linking for BeOS */
  1150. #include <kernel/image.h>
  1151. static lt_module
  1152. sys_bedl_open (loader_data, filename)
  1153. lt_user_data loader_data;
  1154. const char *filename;
  1155. {
  1156. image_id image = 0;
  1157. if (filename)
  1158. {
  1159. image = load_add_on (filename);
  1160. }
  1161. else
  1162. {
  1163. image_info info;
  1164. int32 cookie = 0;
  1165. if (get_next_image_info (0, &cookie, &info) == B_OK)
  1166. image = load_add_on (info.name);
  1167. }
  1168. if (image <= 0)
  1169. {
  1170. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
  1171. image = 0;
  1172. }
  1173. return (lt_module) image;
  1174. }
  1175. static int
  1176. sys_bedl_close (loader_data, module)
  1177. lt_user_data loader_data;
  1178. lt_module module;
  1179. {
  1180. int errors = 0;
  1181. if (unload_add_on ((image_id) module) != B_OK)
  1182. {
  1183. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
  1184. ++errors;
  1185. }
  1186. return errors;
  1187. }
  1188. static lt_ptr
  1189. sys_bedl_sym (loader_data, module, symbol)
  1190. lt_user_data loader_data;
  1191. lt_module module;
  1192. const char *symbol;
  1193. {
  1194. lt_ptr address = 0;
  1195. image_id image = (image_id) module;
  1196. if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
  1197. {
  1198. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  1199. address = 0;
  1200. }
  1201. return address;
  1202. }
  1203. static struct lt_user_dlloader sys_bedl = {
  1204. 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
  1205. };
  1206. #endif /* __BEOS__ */
  1207. /* --- DLD_LINK() INTERFACE LOADER --- */
  1208. #if HAVE_DLD
  1209. /* dynamic linking with dld */
  1210. #if HAVE_DLD_H
  1211. #include <dld.h>
  1212. #endif
  1213. static lt_module
  1214. sys_dld_open (loader_data, filename)
  1215. lt_user_data loader_data;
  1216. const char *filename;
  1217. {
  1218. lt_module module = strdup (filename);
  1219. if (dld_link (filename) != 0)
  1220. {
  1221. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
  1222. LT_DLFREE (module);
  1223. module = 0;
  1224. }
  1225. return module;
  1226. }
  1227. static int
  1228. sys_dld_close (loader_data, module)
  1229. lt_user_data loader_data;
  1230. lt_module module;
  1231. {
  1232. int errors = 0;
  1233. if (dld_unlink_by_file ((char*)(module), 1) != 0)
  1234. {
  1235. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
  1236. ++errors;
  1237. }
  1238. else
  1239. {
  1240. LT_DLFREE (module);
  1241. }
  1242. return errors;
  1243. }
  1244. static lt_ptr
  1245. sys_dld_sym (loader_data, module, symbol)
  1246. lt_user_data loader_data;
  1247. lt_module module;
  1248. const char *symbol;
  1249. {
  1250. lt_ptr address = dld_get_func (symbol);
  1251. if (!address)
  1252. {
  1253. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  1254. }
  1255. return address;
  1256. }
  1257. static struct lt_user_dlloader sys_dld = {
  1258. 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
  1259. };
  1260. #endif /* HAVE_DLD */
  1261. /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
  1262. #if HAVE_DYLD
  1263. #if HAVE_MACH_O_DYLD_H
  1264. #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
  1265. /* Is this correct? Does it still function properly? */
  1266. #define __private_extern__ extern
  1267. #endif
  1268. # include <mach-o/dyld.h>
  1269. #endif
  1270. #include <mach-o/getsect.h>
  1271. /* We have to put some stuff here that isn't in older dyld.h files */
  1272. #ifndef ENUM_DYLD_BOOL
  1273. # define ENUM_DYLD_BOOL
  1274. # undef FALSE
  1275. # undef TRUE
  1276. enum DYLD_BOOL {
  1277. FALSE,
  1278. TRUE
  1279. };
  1280. #endif
  1281. #ifndef LC_REQ_DYLD
  1282. # define LC_REQ_DYLD 0x80000000
  1283. #endif
  1284. #ifndef LC_LOAD_WEAK_DYLIB
  1285. # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
  1286. #endif
  1287. static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
  1288. static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
  1289. static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
  1290. static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
  1291. #ifndef NSADDIMAGE_OPTION_NONE
  1292. #define NSADDIMAGE_OPTION_NONE 0x0
  1293. #endif
  1294. #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
  1295. #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
  1296. #endif
  1297. #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
  1298. #define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
  1299. #endif
  1300. #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
  1301. #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
  1302. #endif
  1303. #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
  1304. #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
  1305. #endif
  1306. #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
  1307. #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
  1308. #endif
  1309. #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
  1310. #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
  1311. #endif
  1312. #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
  1313. #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
  1314. #endif
  1315. #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
  1316. #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
  1317. #endif
  1318. static const char *
  1319. lt_int_dyld_error(othererror)
  1320. char* othererror;
  1321. {
  1322. /* return the dyld error string, or the passed in error string if none */
  1323. NSLinkEditErrors ler;
  1324. int lerno;
  1325. const char *errstr;
  1326. const char *file;
  1327. NSLinkEditError(&ler,&lerno,&file,&errstr);
  1328. if (!errstr || !strlen(errstr)) errstr = othererror;
  1329. return errstr;
  1330. }
  1331. static const struct mach_header *
  1332. lt_int_dyld_get_mach_header_from_nsmodule(module)
  1333. NSModule module;
  1334. {
  1335. /* There should probably be an apple dyld api for this */
  1336. int i=_dyld_image_count();
  1337. int j;
  1338. const char *modname=NSNameOfModule(module);
  1339. const struct mach_header *mh=NULL;
  1340. if (!modname) return NULL;
  1341. for (j = 0; j < i; j++)
  1342. {
  1343. if (!strcmp(_dyld_get_image_name(j),modname))
  1344. {
  1345. mh=_dyld_get_image_header(j);
  1346. break;
  1347. }
  1348. }
  1349. return mh;
  1350. }
  1351. static const char* lt_int_dyld_lib_install_name(mh)
  1352. const struct mach_header *mh;
  1353. {
  1354. /* NSAddImage is also used to get the loaded image, but it only works if the lib
  1355. is installed, for uninstalled libs we need to check the install_names against
  1356. each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
  1357. different lib was loaded as a result
  1358. */
  1359. int j;
  1360. struct load_command *lc;
  1361. unsigned long offset = sizeof(struct mach_header);
  1362. const char* retStr=NULL;
  1363. for (j = 0; j < mh->ncmds; j++)
  1364. {
  1365. lc = (struct load_command*)(((unsigned long)mh) + offset);
  1366. if (LC_ID_DYLIB == lc->cmd)
  1367. {
  1368. retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
  1369. (unsigned long)lc);
  1370. }
  1371. offset += lc->cmdsize;
  1372. }
  1373. return retStr;
  1374. }
  1375. static const struct mach_header *
  1376. lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
  1377. {
  1378. int i=_dyld_image_count();
  1379. int j;
  1380. const struct mach_header *mh=NULL;
  1381. const char *id=NULL;
  1382. for (j = 0; j < i; j++)
  1383. {
  1384. id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
  1385. if ((id) && (!strcmp(id,name)))
  1386. {
  1387. mh=_dyld_get_image_header(j);
  1388. break;
  1389. }
  1390. }
  1391. return mh;
  1392. }
  1393. static NSSymbol
  1394. lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
  1395. const char *symbol;
  1396. const struct mach_header *mh;
  1397. {
  1398. /* Safe to assume our mh is good */
  1399. int j;
  1400. struct load_command *lc;
  1401. unsigned long offset = sizeof(struct mach_header);
  1402. NSSymbol retSym = 0;
  1403. const struct mach_header *mh1;
  1404. if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
  1405. {
  1406. for (j = 0; j < mh->ncmds; j++)
  1407. {
  1408. lc = (struct load_command*)(((unsigned long)mh) + offset);
  1409. if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
  1410. {
  1411. mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
  1412. (unsigned long)lc));
  1413. if (!mh1)
  1414. {
  1415. /* Maybe NSAddImage can find it */
  1416. mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
  1417. (unsigned long)lc),
  1418. NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
  1419. NSADDIMAGE_OPTION_WITH_SEARCHING +
  1420. NSADDIMAGE_OPTION_RETURN_ON_ERROR );
  1421. }
  1422. if (mh1)
  1423. {
  1424. retSym = ltdl_NSLookupSymbolInImage(mh1,
  1425. symbol,
  1426. NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
  1427. | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
  1428. );
  1429. if (retSym) break;
  1430. }
  1431. }
  1432. offset += lc->cmdsize;
  1433. }
  1434. }
  1435. return retSym;
  1436. }
  1437. static int
  1438. sys_dyld_init()
  1439. {
  1440. int retCode = 0;
  1441. int err = 0;
  1442. if (!_dyld_present()) {
  1443. retCode=1;
  1444. }
  1445. else {
  1446. err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
  1447. err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
  1448. err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
  1449. err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
  1450. }
  1451. return retCode;
  1452. }
  1453. static lt_module
  1454. sys_dyld_open (loader_data, filename)
  1455. lt_user_data loader_data;
  1456. const char *filename;
  1457. {
  1458. lt_module module = 0;
  1459. NSObjectFileImage ofi = 0;
  1460. NSObjectFileImageReturnCode ofirc;
  1461. if (!filename)
  1462. return (lt_module)-1;
  1463. ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
  1464. switch (ofirc)
  1465. {
  1466. case NSObjectFileImageSuccess:
  1467. module = NSLinkModule(ofi, filename,
  1468. NSLINKMODULE_OPTION_RETURN_ON_ERROR
  1469. | NSLINKMODULE_OPTION_PRIVATE
  1470. | NSLINKMODULE_OPTION_BINDNOW);
  1471. NSDestroyObjectFileImage(ofi);
  1472. if (module)
  1473. ltdl_NSMakePrivateModulePublic(module);
  1474. break;
  1475. case NSObjectFileImageInappropriateFile:
  1476. if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
  1477. {
  1478. module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
  1479. break;
  1480. }
  1481. default:
  1482. LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
  1483. return 0;
  1484. }
  1485. if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
  1486. return module;
  1487. }
  1488. static int
  1489. sys_dyld_close (loader_data, module)
  1490. lt_user_data loader_data;
  1491. lt_module module;
  1492. {
  1493. int retCode = 0;
  1494. int flags = 0;
  1495. if (module == (lt_module)-1) return 0;
  1496. #ifdef __BIG_ENDIAN__
  1497. if (((struct mach_header *)module)->magic == MH_MAGIC)
  1498. #else
  1499. if (((struct mach_header *)module)->magic == MH_CIGAM)
  1500. #endif
  1501. {
  1502. LT_DLMUTEX_SETERROR("Can not close a dylib");
  1503. retCode = 1;
  1504. }
  1505. else
  1506. {
  1507. #if 1
  1508. /* Currently, if a module contains c++ static destructors and it is unloaded, we
  1509. get a segfault in atexit(), due to compiler and dynamic loader differences of
  1510. opinion, this works around that.
  1511. */
  1512. if ((const struct section *)NULL !=
  1513. getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
  1514. "__DATA","__mod_term_func"))
  1515. {
  1516. flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
  1517. }
  1518. #endif
  1519. #ifdef __ppc__
  1520. flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
  1521. #endif
  1522. if (!NSUnLinkModule(module,flags))
  1523. {
  1524. retCode=1;
  1525. LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
  1526. }
  1527. }
  1528. return retCode;
  1529. }
  1530. static lt_ptr
  1531. sys_dyld_sym (loader_data, module, symbol)
  1532. lt_user_data loader_data;
  1533. lt_module module;
  1534. const char *symbol;
  1535. {
  1536. lt_ptr address = 0;
  1537. NSSymbol *nssym = 0;
  1538. void *unused;
  1539. const struct mach_header *mh=NULL;
  1540. char saveError[256] = "Symbol not found";
  1541. if (module == (lt_module)-1)
  1542. {
  1543. _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
  1544. return address;
  1545. }
  1546. #ifdef __BIG_ENDIAN__
  1547. if (((struct mach_header *)module)->magic == MH_MAGIC)
  1548. #else
  1549. if (((struct mach_header *)module)->magic == MH_CIGAM)
  1550. #endif
  1551. {
  1552. if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
  1553. {
  1554. mh=module;
  1555. if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
  1556. {
  1557. nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
  1558. symbol,
  1559. NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
  1560. | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
  1561. );
  1562. }
  1563. }
  1564. }
  1565. else {
  1566. nssym = NSLookupSymbolInModule(module, symbol);
  1567. }
  1568. if (!nssym)
  1569. {
  1570. strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
  1571. saveError[255] = 0;
  1572. if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
  1573. nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
  1574. }
  1575. if (!nssym)
  1576. {
  1577. LT_DLMUTEX_SETERROR (saveError);
  1578. return NULL;
  1579. }
  1580. return NSAddressOfSymbol(nssym);
  1581. }
  1582. static struct lt_user_dlloader sys_dyld =
  1583. { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
  1584. #endif /* HAVE_DYLD */
  1585. /* --- DLPREOPEN() INTERFACE LOADER --- */
  1586. /* emulate dynamic linking using preloaded_symbols */
  1587. typedef struct lt_dlsymlists_t
  1588. {
  1589. struct lt_dlsymlists_t *next;
  1590. const lt_dlsymlist *syms;
  1591. } lt_dlsymlists_t;
  1592. static const lt_dlsymlist *default_preloaded_symbols = 0;
  1593. static lt_dlsymlists_t *preloaded_symbols = 0;
  1594. static int
  1595. presym_init (loader_data)
  1596. lt_user_data loader_data;
  1597. {
  1598. int errors = 0;
  1599. LT_DLMUTEX_LOCK ();
  1600. preloaded_symbols = 0;
  1601. if (default_preloaded_symbols)
  1602. {
  1603. errors = lt_dlpreload (default_preloaded_symbols);
  1604. }
  1605. LT_DLMUTEX_UNLOCK ();
  1606. return errors;
  1607. }
  1608. static int
  1609. presym_free_symlists ()
  1610. {
  1611. lt_dlsymlists_t *lists;
  1612. LT_DLMUTEX_LOCK ();
  1613. lists = preloaded_symbols;
  1614. while (lists)
  1615. {
  1616. lt_dlsymlists_t *tmp = lists;
  1617. lists = lists->next;
  1618. LT_DLFREE (tmp);
  1619. }
  1620. preloaded_symbols = 0;
  1621. LT_DLMUTEX_UNLOCK ();
  1622. return 0;
  1623. }
  1624. static int
  1625. presym_exit (loader_data)
  1626. lt_user_data loader_data;
  1627. {
  1628. presym_free_symlists ();
  1629. return 0;
  1630. }
  1631. static int
  1632. presym_add_symlist (preloaded)
  1633. const lt_dlsymlist *preloaded;
  1634. {
  1635. lt_dlsymlists_t *tmp;
  1636. lt_dlsymlists_t *lists;
  1637. int errors = 0;
  1638. LT_DLMUTEX_LOCK ();
  1639. lists = preloaded_symbols;
  1640. while (lists)
  1641. {
  1642. if (lists->syms == preloaded)
  1643. {
  1644. goto done;
  1645. }
  1646. lists = lists->next;
  1647. }
  1648. tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
  1649. if (tmp)
  1650. {
  1651. memset (tmp, 0, sizeof(lt_dlsymlists_t));
  1652. tmp->syms = preloaded;
  1653. tmp->next = preloaded_symbols;
  1654. preloaded_symbols = tmp;
  1655. }
  1656. else
  1657. {
  1658. ++errors;
  1659. }
  1660. done:
  1661. LT_DLMUTEX_UNLOCK ();
  1662. return errors;
  1663. }
  1664. static lt_module
  1665. presym_open (loader_data, filename)
  1666. lt_user_data loader_data;
  1667. const char *filename;
  1668. {
  1669. lt_dlsymlists_t *lists;
  1670. lt_module module = (lt_module) 0;
  1671. LT_DLMUTEX_LOCK ();
  1672. lists = preloaded_symbols;
  1673. if (!lists)
  1674. {
  1675. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
  1676. goto done;
  1677. }
  1678. /* Can't use NULL as the reflective symbol header, as NULL is
  1679. used to mark the end of the entire symbol list. Self-dlpreopened
  1680. symbols follow this magic number, chosen to be an unlikely
  1681. clash with a real module name. */
  1682. if (!filename)
  1683. {
  1684. filename = "@PROGRAM@";
  1685. }
  1686. while (lists)
  1687. {
  1688. const lt_dlsymlist *syms = lists->syms;
  1689. while (syms->name)
  1690. {
  1691. if (!syms->address && strcmp(syms->name, filename) == 0)
  1692. {
  1693. module = (lt_module) syms;
  1694. goto done;
  1695. }
  1696. ++syms;
  1697. }
  1698. lists = lists->next;
  1699. }
  1700. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
  1701. done:
  1702. LT_DLMUTEX_UNLOCK ();
  1703. return module;
  1704. }
  1705. static int
  1706. presym_close (loader_data, module)
  1707. lt_user_data loader_data;
  1708. lt_module module;
  1709. {
  1710. /* Just to silence gcc -Wall */
  1711. module = 0;
  1712. return 0;
  1713. }
  1714. static lt_ptr
  1715. presym_sym (loader_data, module, symbol)
  1716. lt_user_data loader_data;
  1717. lt_module module;
  1718. const char *symbol;
  1719. {
  1720. lt_dlsymlist *syms = (lt_dlsymlist*) module;
  1721. ++syms;
  1722. while (syms->address)
  1723. {
  1724. if (strcmp(syms->name, symbol) == 0)
  1725. {
  1726. return syms->address;
  1727. }
  1728. ++syms;
  1729. }
  1730. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
  1731. return 0;
  1732. }
  1733. static struct lt_user_dlloader presym = {
  1734. 0, presym_open, presym_close, presym_sym, presym_exit, 0
  1735. };
  1736. /* --- DYNAMIC MODULE LOADING --- */
  1737. /* The type of a function used at each iteration of foreach_dirinpath(). */
  1738. typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
  1739. lt_ptr data2));
  1740. static int foreach_dirinpath LT_PARAMS((const char *search_path,
  1741. const char *base_name,
  1742. foreach_callback_func *func,
  1743. lt_ptr data1, lt_ptr data2));
  1744. static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
  1745. lt_ptr ignored));
  1746. static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
  1747. lt_ptr ignored));
  1748. static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
  1749. lt_ptr data2));
  1750. static int canonicalize_path LT_PARAMS((const char *path,
  1751. char **pcanonical));
  1752. static int argzize_path LT_PARAMS((const char *path,
  1753. char **pargz,
  1754. size_t *pargz_len));
  1755. static FILE *find_file LT_PARAMS((const char *search_path,
  1756. const char *base_name,
  1757. char **pdir));
  1758. static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
  1759. const char *base_name,
  1760. lt_dlhandle *handle));
  1761. static int find_module LT_PARAMS((lt_dlhandle *handle,
  1762. const char *dir,
  1763. const char *libdir,
  1764. const char *dlname,
  1765. const char *old_name,
  1766. int installed));
  1767. static int free_vars LT_PARAMS((char *dlname, char *oldname,
  1768. char *libdir, char *deplibs));
  1769. static int load_deplibs LT_PARAMS((lt_dlhandle handle,
  1770. char *deplibs));
  1771. static int trim LT_PARAMS((char **dest,
  1772. const char *str));
  1773. static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
  1774. const char *filename));
  1775. static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
  1776. const char *filename,
  1777. const char * useloader));
  1778. static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
  1779. static int lt_argz_insert LT_PARAMS((char **pargz,
  1780. size_t *pargz_len,
  1781. char *before,
  1782. const char *entry));
  1783. static int lt_argz_insertinorder LT_PARAMS((char **pargz,
  1784. size_t *pargz_len,
  1785. const char *entry));
  1786. static int lt_argz_insertdir LT_PARAMS((char **pargz,
  1787. size_t *pargz_len,
  1788. const char *dirnam,
  1789. struct dirent *dp));
  1790. static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
  1791. char *before,
  1792. const char *dir));
  1793. static int list_files_by_dir LT_PARAMS((const char *dirnam,
  1794. char **pargz,
  1795. size_t *pargz_len));
  1796. static int file_not_found LT_PARAMS((void));
  1797. static char *user_search_path= 0;
  1798. static lt_dlloader *loaders = 0;
  1799. static lt_dlhandle handles = 0;
  1800. static int initialized = 0;
  1801. /* Initialize libltdl. */
  1802. int
  1803. lt_dlinit ()
  1804. {
  1805. int errors = 0;
  1806. LT_DLMUTEX_LOCK ();
  1807. /* Initialize only at first call. */
  1808. if (++initialized == 1)
  1809. {
  1810. handles = 0;
  1811. user_search_path = 0; /* empty search path */
  1812. #if HAVE_LIBDL
  1813. errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
  1814. #endif
  1815. #if HAVE_SHL_LOAD
  1816. errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
  1817. #endif
  1818. #ifdef __WINDOWS__
  1819. errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
  1820. #endif
  1821. #ifdef __BEOS__
  1822. errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
  1823. #endif
  1824. #if HAVE_DLD
  1825. errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
  1826. #endif
  1827. #if HAVE_DYLD
  1828. errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
  1829. errors += sys_dyld_init();
  1830. #endif
  1831. errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
  1832. if (presym_init (presym.dlloader_data))
  1833. {
  1834. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
  1835. ++errors;
  1836. }
  1837. else if (errors != 0)
  1838. {
  1839. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
  1840. ++errors;
  1841. }
  1842. }
  1843. LT_DLMUTEX_UNLOCK ();
  1844. return errors;
  1845. }
  1846. int
  1847. lt_dlpreload (preloaded)
  1848. const lt_dlsymlist *preloaded;
  1849. {
  1850. int errors = 0;
  1851. if (preloaded)
  1852. {
  1853. errors = presym_add_symlist (preloaded);
  1854. }
  1855. else
  1856. {
  1857. presym_free_symlists();
  1858. LT_DLMUTEX_LOCK ();
  1859. if (default_preloaded_symbols)
  1860. {
  1861. errors = lt_dlpreload (default_preloaded_symbols);
  1862. }
  1863. LT_DLMUTEX_UNLOCK ();
  1864. }
  1865. return errors;
  1866. }
  1867. int
  1868. lt_dlpreload_default (preloaded)
  1869. const lt_dlsymlist *preloaded;
  1870. {
  1871. LT_DLMUTEX_LOCK ();
  1872. default_preloaded_symbols = preloaded;
  1873. LT_DLMUTEX_UNLOCK ();
  1874. return 0;
  1875. }
  1876. int
  1877. lt_dlexit ()
  1878. {
  1879. /* shut down libltdl */
  1880. lt_dlloader *loader;
  1881. int errors = 0;
  1882. LT_DLMUTEX_LOCK ();
  1883. loader = loaders;
  1884. if (!initialized)
  1885. {
  1886. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
  1887. ++errors;
  1888. goto done;
  1889. }
  1890. /* shut down only at last call. */
  1891. if (--initialized == 0)
  1892. {
  1893. int level;
  1894. while (handles && LT_DLIS_RESIDENT (handles))
  1895. {
  1896. handles = handles->next;
  1897. }
  1898. /* close all modules */
  1899. for (level = 1; handles; ++level)
  1900. {
  1901. lt_dlhandle cur = handles;
  1902. int saw_nonresident = 0;
  1903. while (cur)
  1904. {
  1905. lt_dlhandle tmp = cur;
  1906. cur = cur->next;
  1907. if (!LT_DLIS_RESIDENT (tmp))
  1908. saw_nonresident = 1;
  1909. if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
  1910. {
  1911. if (lt_dlclose (tmp))
  1912. {
  1913. ++errors;
  1914. }
  1915. }
  1916. }
  1917. /* done if only resident modules are left */
  1918. if (!saw_nonresident)
  1919. break;
  1920. }
  1921. /* close all loaders */
  1922. while (loader)
  1923. {
  1924. lt_dlloader *next = loader->next;
  1925. lt_user_data data = loader->dlloader_data;
  1926. if (loader->dlloader_exit && loader->dlloader_exit (data))
  1927. {
  1928. ++errors;
  1929. }
  1930. LT_DLMEM_REASSIGN (loader, next);
  1931. }
  1932. loaders = 0;
  1933. }
  1934. done:
  1935. LT_DLMUTEX_UNLOCK ();
  1936. return errors;
  1937. }
  1938. static int
  1939. tryall_dlopen (handle, filename, useloader)
  1940. lt_dlhandle *handle;
  1941. const char *filename;
  1942. const char *useloader;
  1943. {
  1944. lt_dlhandle cur;
  1945. lt_dlloader *loader;
  1946. const char *saved_error;
  1947. int errors = 0;
  1948. LT_DLMUTEX_GETERROR (saved_error);
  1949. LT_DLMUTEX_LOCK ();
  1950. cur = handles;
  1951. loader = loaders;
  1952. /* check whether the module was already opened */
  1953. while (cur)
  1954. {
  1955. /* try to dlopen the program itself? */
  1956. if (!cur->info.filename && !filename)
  1957. {
  1958. break;
  1959. }
  1960. if (cur->info.filename && filename
  1961. && strcmp (cur->info.filename, filename) == 0)
  1962. {
  1963. break;
  1964. }
  1965. cur = cur->next;
  1966. }
  1967. if (cur)
  1968. {
  1969. ++cur->info.ref_count;
  1970. *handle = cur;
  1971. goto done;
  1972. }
  1973. cur = *handle;
  1974. if (filename)
  1975. {
  1976. /* Comment out the check of file permissions using access.
  1977. This call seems to always return -1 with error EACCES.
  1978. */
  1979. /* We need to catch missing file errors early so that
  1980. file_not_found() can detect what happened.
  1981. if (access (filename, R_OK) != 0)
  1982. {
  1983. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
  1984. ++errors;
  1985. goto done;
  1986. } */
  1987. cur->info.filename = lt_estrdup (filename);
  1988. if (!cur->info.filename)
  1989. {
  1990. ++errors;
  1991. goto done;
  1992. }
  1993. }
  1994. else
  1995. {
  1996. cur->info.filename = 0;
  1997. }
  1998. while (loader)
  1999. {
  2000. if (useloader && strcmp(loader->loader_name, useloader))
  2001. {
  2002. loader = loader->next;
  2003. continue;
  2004. }
  2005. lt_user_data data = loader->dlloader_data;
  2006. cur->module = loader->module_open (data, filename);
  2007. if (cur->module != 0)
  2008. {
  2009. break;
  2010. }
  2011. loader = loader->next;
  2012. }
  2013. if (!loader)
  2014. {
  2015. LT_DLFREE (cur->info.filename);
  2016. ++errors;
  2017. goto done;
  2018. }
  2019. cur->loader = loader;
  2020. LT_DLMUTEX_SETERROR (saved_error);
  2021. done:
  2022. LT_DLMUTEX_UNLOCK ();
  2023. return errors;
  2024. }
  2025. static int
  2026. tryall_dlopen_module (handle, prefix, dirname, dlname)
  2027. lt_dlhandle *handle;
  2028. const char *prefix;
  2029. const char *dirname;
  2030. const char *dlname;
  2031. {
  2032. int error = 0;
  2033. char *filename = 0;
  2034. size_t filename_len = 0;
  2035. size_t dirname_len = LT_STRLEN (dirname);
  2036. assert (handle);
  2037. assert (dirname);
  2038. assert (dlname);
  2039. #ifdef LT_DIRSEP_CHAR
  2040. /* Only canonicalized names (i.e. with DIRSEP chars already converted)
  2041. should make it into this function: */
  2042. assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
  2043. #endif
  2044. if (dirname_len > 0)
  2045. if (dirname[dirname_len -1] == '/')
  2046. --dirname_len;
  2047. filename_len = dirname_len + 1 + LT_STRLEN (dlname);
  2048. /* Allocate memory, and combine DIRNAME and MODULENAME into it.
  2049. The PREFIX (if any) is handled below. */
  2050. filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
  2051. if (!filename)
  2052. return 1;
  2053. sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
  2054. /* Now that we have combined DIRNAME and MODULENAME, if there is
  2055. also a PREFIX to contend with, simply recurse with the arguments
  2056. shuffled. Otherwise, attempt to open FILENAME as a module. */
  2057. if (prefix)
  2058. {
  2059. error += tryall_dlopen_module (handle,
  2060. (const char *) 0, prefix, filename);
  2061. }
  2062. else if (tryall_dlopen (handle, filename, NULL) != 0)
  2063. {
  2064. ++error;
  2065. }
  2066. LT_DLFREE (filename);
  2067. return error;
  2068. }
  2069. static int
  2070. find_module (handle, dir, libdir, dlname, old_name, installed)
  2071. lt_dlhandle *handle;
  2072. const char *dir;
  2073. const char *libdir;
  2074. const char *dlname;
  2075. const char *old_name;
  2076. int installed;
  2077. {
  2078. /* Try to open the old library first; if it was dlpreopened,
  2079. we want the preopened version of it, even if a dlopenable
  2080. module is available. */
  2081. if (old_name && tryall_dlopen (handle, old_name, "dlpreload") == 0)
  2082. {
  2083. return 0;
  2084. }
  2085. /* Try to open the dynamic library. */
  2086. if (dlname)
  2087. {
  2088. /* try to open the installed module */
  2089. if (installed && libdir)
  2090. {
  2091. if (tryall_dlopen_module (handle,
  2092. (const char *) 0, libdir, dlname) == 0)
  2093. return 0;
  2094. }
  2095. /* try to open the not-installed module */
  2096. if (!installed)
  2097. {
  2098. if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
  2099. return 0;
  2100. }
  2101. /* maybe it was moved to another directory */
  2102. {
  2103. if (dir && (tryall_dlopen_module (handle,
  2104. (const char *) 0, dir, dlname) == 0))
  2105. return 0;
  2106. }
  2107. }
  2108. return 1;
  2109. }
  2110. static int
  2111. canonicalize_path (path, pcanonical)
  2112. const char *path;
  2113. char **pcanonical;
  2114. {
  2115. char *canonical = 0;
  2116. assert (path && *path);
  2117. assert (pcanonical);
  2118. canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
  2119. if (!canonical)
  2120. return 1;
  2121. {
  2122. size_t dest = 0;
  2123. size_t src;
  2124. for (src = 0; path[src] != LT_EOS_CHAR; ++src)
  2125. {
  2126. /* Path separators are not copied to the beginning or end of
  2127. the destination, or if another separator would follow
  2128. immediately. */
  2129. if (path[src] == LT_PATHSEP_CHAR)
  2130. {
  2131. if ((dest == 0)
  2132. || (path[1+ src] == LT_PATHSEP_CHAR)
  2133. || (path[1+ src] == LT_EOS_CHAR))
  2134. continue;
  2135. }
  2136. /* Anything other than a directory separator is copied verbatim. */
  2137. if ((path[src] != '/')
  2138. #ifdef LT_DIRSEP_CHAR
  2139. && (path[src] != LT_DIRSEP_CHAR)
  2140. #endif
  2141. )
  2142. {
  2143. canonical[dest++] = path[src];
  2144. }
  2145. /* Directory separators are converted and copied only if they are
  2146. not at the end of a path -- i.e. before a path separator or
  2147. NULL terminator. */
  2148. else if ((path[1+ src] != LT_PATHSEP_CHAR)
  2149. && (path[1+ src] != LT_EOS_CHAR)
  2150. #ifdef LT_DIRSEP_CHAR
  2151. && (path[1+ src] != LT_DIRSEP_CHAR)
  2152. #endif
  2153. && (path[1+ src] != '/'))
  2154. {
  2155. canonical[dest++] = '/';
  2156. }
  2157. }
  2158. /* Add an end-of-string marker at the end. */
  2159. canonical[dest] = LT_EOS_CHAR;
  2160. }
  2161. /* Assign new value. */
  2162. *pcanonical = canonical;
  2163. return 0;
  2164. }
  2165. static int
  2166. argzize_path (path, pargz, pargz_len)
  2167. const char *path;
  2168. char **pargz;
  2169. size_t *pargz_len;
  2170. {
  2171. error_t error;
  2172. assert (path);
  2173. assert (pargz);
  2174. assert (pargz_len);
  2175. if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
  2176. {
  2177. switch (error)
  2178. {
  2179. case ENOMEM:
  2180. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
  2181. break;
  2182. default:
  2183. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
  2184. break;
  2185. }
  2186. return 1;
  2187. }
  2188. return 0;
  2189. }
  2190. /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
  2191. of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
  2192. non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
  2193. it is appended to each SEARCH_PATH element before FUNC is called. */
  2194. static int
  2195. foreach_dirinpath (search_path, base_name, func, data1, data2)
  2196. const char *search_path;
  2197. const char *base_name;
  2198. foreach_callback_func *func;
  2199. lt_ptr data1;
  2200. lt_ptr data2;
  2201. {
  2202. int result = 0;
  2203. int filenamesize = 0;
  2204. size_t lenbase = LT_STRLEN (base_name);
  2205. size_t argz_len = 0;
  2206. char *argz = 0;
  2207. char *filename = 0;
  2208. char *canonical = 0;
  2209. LT_DLMUTEX_LOCK ();
  2210. if (!search_path || !*search_path)
  2211. {
  2212. LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
  2213. goto cleanup;
  2214. }
  2215. if (canonicalize_path (search_path, &canonical) != 0)
  2216. goto cleanup;
  2217. if (argzize_path (canonical, &argz, &argz_len) != 0)
  2218. goto cleanup;
  2219. {
  2220. char *dir_name = 0;
  2221. while ((dir_name = argz_next (argz, argz_len, dir_name)))
  2222. {
  2223. size_t lendir = LT_STRLEN (dir_name);
  2224. if (lendir +1 +lenbase >= filenamesize)
  2225. {
  2226. LT_DLFREE (filename);
  2227. filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
  2228. filename = LT_EMALLOC (char, filenamesize);
  2229. if (!filename)
  2230. goto cleanup;
  2231. }
  2232. assert (filenamesize > lendir);
  2233. strcpy (filename, dir_name);
  2234. if (base_name && *base_name)
  2235. {
  2236. if (filename[lendir -1] != '/')
  2237. filename[lendir++] = '/';
  2238. strcpy (filename +lendir, base_name);
  2239. }
  2240. if ((result = (*func) (filename, data1, data2)))
  2241. {
  2242. break;
  2243. }
  2244. }
  2245. }
  2246. cleanup:
  2247. LT_DLFREE (argz);
  2248. LT_DLFREE (canonical);
  2249. LT_DLFREE (filename);
  2250. LT_DLMUTEX_UNLOCK ();
  2251. return result;
  2252. }
  2253. /* If FILEPATH can be opened, store the name of the directory component
  2254. in DATA1, and the opened FILE* structure address in DATA2. Otherwise
  2255. DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
  2256. static int
  2257. find_file_callback (filename, data1, data2)
  2258. char *filename;
  2259. lt_ptr data1;
  2260. lt_ptr data2;
  2261. {
  2262. char **pdir = (char **) data1;
  2263. FILE **pfile = (FILE **) data2;
  2264. int is_done = 0;
  2265. assert (filename && *filename);
  2266. assert (pdir);
  2267. assert (pfile);
  2268. if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
  2269. {
  2270. char *dirend = strrchr (filename, '/');
  2271. if (dirend > filename)
  2272. *dirend = LT_EOS_CHAR;
  2273. LT_DLFREE (*pdir);
  2274. *pdir = lt_estrdup (filename);
  2275. is_done = (*pdir == 0) ? -1 : 1;
  2276. }
  2277. return is_done;
  2278. }
  2279. static FILE *
  2280. find_file (search_path, base_name, pdir)
  2281. const char *search_path;
  2282. const char *base_name;
  2283. char **pdir;
  2284. {
  2285. FILE *file = 0;
  2286. foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
  2287. return file;
  2288. }
  2289. static int
  2290. find_handle_callback (filename, data, ignored)
  2291. char *filename;
  2292. lt_ptr data;
  2293. lt_ptr ignored;
  2294. {
  2295. lt_dlhandle *handle = (lt_dlhandle *) data;
  2296. int notfound = access (filename, R_OK);
  2297. /* Bail out if file cannot be read... */
  2298. if (notfound)
  2299. return 0;
  2300. /* Try to dlopen the file, but do not continue searching in any
  2301. case. */
  2302. if (tryall_dlopen (handle, filename,NULL) != 0)
  2303. *handle = 0;
  2304. return 1;
  2305. }
  2306. /* If HANDLE was found return it, otherwise return 0. If HANDLE was
  2307. found but could not be opened, *HANDLE will be set to 0. */
  2308. static lt_dlhandle *
  2309. find_handle (search_path, base_name, handle)
  2310. const char *search_path;
  2311. const char *base_name;
  2312. lt_dlhandle *handle;
  2313. {
  2314. if (!search_path)
  2315. return 0;
  2316. if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
  2317. handle, 0))
  2318. return 0;
  2319. return handle;
  2320. }
  2321. static int
  2322. load_deplibs (handle, deplibs)
  2323. lt_dlhandle handle;
  2324. char *deplibs;
  2325. {
  2326. #if LTDL_DLOPEN_DEPLIBS
  2327. char *p, *save_search_path = 0;
  2328. int depcount = 0;
  2329. int i;
  2330. char **names = 0;
  2331. #endif
  2332. int errors = 0;
  2333. handle->depcount = 0;
  2334. #if LTDL_DLOPEN_DEPLIBS
  2335. if (!deplibs)
  2336. {
  2337. return errors;
  2338. }
  2339. ++errors;
  2340. LT_DLMUTEX_LOCK ();
  2341. if (user_search_path)
  2342. {
  2343. save_search_path = lt_estrdup (user_search_path);
  2344. if (!save_search_path)
  2345. goto cleanup;
  2346. }
  2347. /* extract search paths and count deplibs */
  2348. p = deplibs;
  2349. while (*p)
  2350. {
  2351. if (!isspace ((int) *p))
  2352. {
  2353. char *end = p+1;
  2354. while (*end && !isspace((int) *end))
  2355. {
  2356. ++end;
  2357. }
  2358. if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
  2359. {
  2360. char save = *end;
  2361. *end = 0; /* set a temporary string terminator */
  2362. if (lt_dladdsearchdir(p+2))
  2363. {
  2364. goto cleanup;
  2365. }
  2366. *end = save;
  2367. }
  2368. else
  2369. {
  2370. ++depcount;
  2371. }
  2372. p = end;
  2373. }
  2374. else
  2375. {
  2376. ++p;
  2377. }
  2378. }
  2379. if (!depcount)
  2380. {
  2381. errors = 0;
  2382. goto cleanup;
  2383. }
  2384. names = LT_EMALLOC (char *, depcount * sizeof (char*));
  2385. if (!names)
  2386. goto cleanup;
  2387. /* now only extract the actual deplibs */
  2388. depcount = 0;
  2389. p = deplibs;
  2390. while (*p)
  2391. {
  2392. if (isspace ((int) *p))
  2393. {
  2394. ++p;
  2395. }
  2396. else
  2397. {
  2398. char *end = p+1;
  2399. while (*end && !is