ltdl.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985
  1. /* ltdl.c -- system independent dlopen wrapper
  2. Copyright (C) 1998, 1999, 2000 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., 59 Temple Place, Suite 330, Boston, MA
  20. 02111-1307 USA
  21. */
  22. #define _LTDL_COMPILE_
  23. #if HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26. #if HAVE_STRING_H
  27. #include <string.h>
  28. #endif
  29. #if HAVE_STRINGS_H
  30. #include <strings.h>
  31. #endif
  32. #if HAVE_CTYPE_H
  33. #include <ctype.h>
  34. #endif
  35. #if HAVE_MALLOC_H
  36. #include <malloc.h>
  37. #endif
  38. #if HAVE_MEMORY_H
  39. #include <memory.h>
  40. #endif
  41. #if HAVE_STDLIB_H
  42. #include <stdlib.h>
  43. #endif
  44. #if HAVE_STDIO_H
  45. #include <stdio.h>
  46. #endif
  47. #if HAVE_BOEHM_GC
  48. #include <gc.h>
  49. #endif
  50. #include "ltdl.h"
  51. #ifdef DLL_EXPORT
  52. # define LTDL_GLOBAL_DATA __declspec(dllexport)
  53. #else
  54. # define LTDL_GLOBAL_DATA
  55. #endif
  56. /* max. filename length */
  57. #ifndef LTDL_FILENAME_MAX
  58. #define LTDL_FILENAME_MAX 1024
  59. #endif
  60. #undef LTDL_READTEXT_MODE
  61. /* fopen() mode flags for reading a text file */
  62. #ifdef _WIN32
  63. #define LTDL_READTEXT_MODE "rt"
  64. #else
  65. #define LTDL_READTEXT_MODE "r"
  66. #endif
  67. #undef LTDL_SYMBOL_LENGTH
  68. /* This is the maximum symbol size that won't require malloc/free */
  69. #define LTDL_SYMBOL_LENGTH 128
  70. #undef LTDL_SYMBOL_OVERHEAD
  71. /* This accounts for the _LTX_ separator */
  72. #define LTDL_SYMBOL_OVERHEAD 5
  73. /* NOTE: typedefed in ltdl.h
  74. This structure is used for the list of registered loaders. */
  75. struct lt_dlloader_t {
  76. struct lt_dlloader_t *next;
  77. const char *loader_name; /* identifying name for each loader */
  78. const char *sym_prefix; /* prefix for symbols */
  79. lt_module_open_t *module_open;
  80. lt_module_close_t *module_close;
  81. lt_find_sym_t *find_sym;
  82. lt_dlloader_exit_t *dlloader_exit;
  83. lt_dlloader_data_t dlloader_data;
  84. };
  85. typedef struct lt_dlhandle_t {
  86. struct lt_dlhandle_t *next;
  87. lt_dlloader_t *loader; /* dlopening interface */
  88. lt_dlinfo info;
  89. int depcount; /* number of dependencies */
  90. lt_dlhandle *deplibs; /* dependencies */
  91. lt_module_t module; /* system module handle */
  92. lt_ptr_t system; /* system specific data */
  93. lt_ptr_t app_private; /* application private data */
  94. } lt_dlhandle_t;
  95. static const char objdir[] = LTDL_OBJDIR;
  96. #ifdef LTDL_SHLIB_EXT
  97. static const char shlib_ext[] = LTDL_SHLIB_EXT;
  98. #endif
  99. #ifdef LTDL_SYSSEARCHPATH
  100. static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
  101. #endif
  102. /* Extract the diagnostic strings from the error table macro in the same
  103. order as the enumberated indices in ltdl.h. */
  104. #define LTDL_ERROR(name, diagnostic) (diagnostic),
  105. static const char *ltdl_error_strings[] = {
  106. ltdl_error_table
  107. 0
  108. };
  109. #undef LTDL_ERROR
  110. #ifdef __STDC__
  111. # define LT_DLSTRERROR(name) ltdl_error_strings[LTDL_ERROR_##name]
  112. #else
  113. # define LT_DLSTRERROR(name) ltdl_error_strings[LTDL_ERROR_/**/name]
  114. #endif
  115. static const char *last_error = 0;
  116. LTDL_GLOBAL_DATA lt_ptr_t (*lt_dlmalloc) LTDL_PARAMS((size_t size)) = (lt_ptr_t(*)LTDL_PARAMS((size_t)))malloc;
  117. LTDL_GLOBAL_DATA void (*lt_dlfree) LTDL_PARAMS((lt_ptr_t ptr)) = (void(*)LTDL_PARAMS((lt_ptr_t)))free;
  118. #undef strdup
  119. #define strdup xstrdup
  120. static inline char *
  121. strdup(str)
  122. const char *str;
  123. {
  124. char *tmp;
  125. if (!str)
  126. return 0;
  127. tmp = (char*) lt_dlmalloc(strlen(str)+1);
  128. if (tmp)
  129. strcpy(tmp, str);
  130. return tmp;
  131. }
  132. #if ! HAVE_STRCMP
  133. #undef strcmp
  134. #define strcmp xstrcmp
  135. static inline int
  136. strcmp (str1, str2)
  137. const char *str1;
  138. const char *str2;
  139. {
  140. if (str1 == str2)
  141. return 0;
  142. if (str1 == 0)
  143. return -1;
  144. if (str2 == 0)
  145. return 1;
  146. for (;*str1 && *str2; str1++, str2++)
  147. if (*str1 != *str2)
  148. break;
  149. return (int)(*str1 - *str2);
  150. }
  151. #endif
  152. #if ! HAVE_STRCHR
  153. # if HAVE_INDEX
  154. # define strchr index
  155. # else
  156. # define strchr xstrchr
  157. static inline const char*
  158. strchr(str, ch)
  159. const char *str;
  160. int ch;
  161. {
  162. const char *p;
  163. for (p = str; *p != (char)ch && *p != '\0'; p++)
  164. /*NOWORK*/;
  165. return (*p == (char)ch) ? p : 0;
  166. }
  167. # endif
  168. #endif
  169. #if ! HAVE_STRRCHR
  170. # if HAVE_RINDEX
  171. # define strrchr rindex
  172. # else
  173. # define strrchr xstrrchr
  174. static inline const char*
  175. strrchr(str, ch)
  176. const char *str;
  177. int ch;
  178. {
  179. const char *p;
  180. for (p = str; *p != '\0'; p++)
  181. /*NOWORK*/;
  182. while (*p != (char)ch && p >= str)
  183. p--;
  184. return (*p == (char)ch) ? p : 0;
  185. }
  186. # endif
  187. #endif
  188. /* The Cygwin dlopen implementation prints a spurious error message to
  189. stderr if its call to LoadLibrary() fails for any reason. We can
  190. mitigate this by not using the Cygwin implementation, and falling
  191. back to our own LoadLibrary() wrapper. */
  192. #if HAVE_LIBDL && !defined(__CYGWIN__)
  193. /* dynamic linking with dlopen/dlsym */
  194. #if HAVE_DLFCN_H
  195. # include <dlfcn.h>
  196. #endif
  197. #ifdef RTLD_GLOBAL
  198. # define LTDL_GLOBAL RTLD_GLOBAL
  199. #else
  200. # ifdef DL_GLOBAL
  201. # define LTDL_GLOBAL DL_GLOBAL
  202. # else
  203. # define LTDL_GLOBAL 0
  204. # endif
  205. #endif
  206. /* We may have to define LTDL_LAZY_OR_NOW in the command line if we
  207. find out it does not work in some platform. */
  208. #ifndef LTDL_LAZY_OR_NOW
  209. # ifdef RTLD_LAZY
  210. # define LTDL_LAZY_OR_NOW RTLD_LAZY
  211. # else
  212. # ifdef DL_LAZY
  213. # define LTDL_LAZY_OR_NOW DL_LAZY
  214. # else
  215. # ifdef RTLD_NOW
  216. # define LTDL_LAZY_OR_NOW RTLD_NOW
  217. # else
  218. # ifdef DL_NOW
  219. # define LTDL_LAZY_OR_NOW DL_NOW
  220. # else
  221. # define LTDL_LAZY_OR_NOW 0
  222. # endif
  223. # endif
  224. # endif
  225. # endif
  226. #endif
  227. static lt_module_t
  228. sys_dl_open (loader_data, filename)
  229. lt_dlloader_data_t loader_data;
  230. const char *filename;
  231. {
  232. lt_module_t module = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW);
  233. if (!module) {
  234. #if HAVE_DLERROR
  235. last_error = dlerror();
  236. #else
  237. last_error = LT_DLSTRERROR(CANNOT_OPEN);
  238. #endif
  239. }
  240. return module;
  241. }
  242. static int
  243. sys_dl_close (loader_data, module)
  244. lt_dlloader_data_t loader_data;
  245. lt_module_t module;
  246. {
  247. if (dlclose(module) != 0) {
  248. #if HAVE_DLERROR
  249. last_error = dlerror();
  250. #else
  251. last_error = LT_DLSTRERROR(CANNOT_CLOSE);
  252. #endif
  253. return 1;
  254. }
  255. return 0;
  256. }
  257. static lt_ptr_t
  258. sys_dl_sym (loader_data, module, symbol)
  259. lt_dlloader_data_t loader_data;
  260. lt_module_t module;
  261. const char *symbol;
  262. {
  263. lt_ptr_t address = dlsym(module, symbol);
  264. if (!address)
  265. #if HAVE_DLERROR
  266. last_error = dlerror();
  267. #else
  268. last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
  269. #endif
  270. return address;
  271. }
  272. static struct lt_user_dlloader sys_dl = {
  273. # ifdef NEED_USCORE
  274. "_",
  275. # else
  276. 0,
  277. # endif
  278. sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
  279. #endif
  280. #if HAVE_SHL_LOAD
  281. /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
  282. #ifdef HAVE_DL_H
  283. #include <dl.h>
  284. #endif
  285. /* some flags are missing on some systems, so we provide
  286. * harmless defaults.
  287. *
  288. * Mandatory:
  289. * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
  290. * BIND_DEFERRED - Delay code symbol resolution until actual reference.
  291. *
  292. * Optionally:
  293. * BIND_FIRST - Place the library at the head of the symbol search order.
  294. * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all unsatisfied
  295. * symbols as fatal. This flag allows binding of unsatisfied code
  296. * symbols to be deferred until use.
  297. * [Perl: For certain libraries, like DCE, deferred binding often
  298. * causes run time problems. Adding BIND_NONFATAL to BIND_IMMEDIATE
  299. * still allows unresolved references in situations like this.]
  300. * BIND_NOSTART - Do not call the initializer for the shared library when the
  301. * library is loaded, nor on a future call to shl_unload().
  302. * BIND_VERBOSE - Print verbose messages concerning possible unsatisfied symbols.
  303. *
  304. * hp9000s700/hp9000s800:
  305. * BIND_RESTRICTED - Restrict symbols visible by the library to those present at
  306. * library load time.
  307. * DYNAMIC_PATH - Allow the loader to dynamically search for the library specified
  308. * by the path argument.
  309. */
  310. #ifndef DYNAMIC_PATH
  311. #define DYNAMIC_PATH 0
  312. #endif /* DYNAMIC_PATH */
  313. #ifndef BIND_RESTRICTED
  314. #define BIND_RESTRICTED 0
  315. #endif /* BIND_RESTRICTED */
  316. #define LTDL_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
  317. static lt_module_t
  318. sys_shl_open (loader_data, filename)
  319. lt_dlloader_data_t loader_data;
  320. const char *filename;
  321. {
  322. lt_module_t module = shl_load(filename, LTDL_BIND_FLAGS, 0L);
  323. if (!module) {
  324. last_error = LT_DLSTRERROR(CANNOT_OPEN);
  325. }
  326. return module;
  327. }
  328. static int
  329. sys_shl_close (loader_data, module)
  330. lt_dlloader_data_t loader_data;
  331. lt_module_t module;
  332. {
  333. if (shl_unload((shl_t) (module)) != 0) {
  334. last_error = LT_DLSTRERROR(CANNOT_CLOSE);
  335. return 1;
  336. }
  337. return 0;
  338. }
  339. static lt_ptr_t
  340. sys_shl_sym (loader_data, module, symbol)
  341. lt_dlloader_data_t loader_data;
  342. lt_module_t module;
  343. const char *symbol;
  344. {
  345. lt_ptr_t address;
  346. if (module && shl_findsym((shl_t*) &module,
  347. symbol, TYPE_UNDEFINED, &address) == 0)
  348. if (address)
  349. return address;
  350. last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
  351. return 0;
  352. }
  353. static struct lt_user_dlloader
  354. sys_shl = { 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 };
  355. #undef LTDL_TYPE_TOP
  356. #define LTDL_TYPE_TOP &sys_shl
  357. #endif
  358. #ifdef _WIN32
  359. /* dynamic linking for Win32 */
  360. #include <windows.h>
  361. /* Forward declaration; required to implement handle search below. */
  362. static lt_dlhandle handles;
  363. static lt_module_t
  364. sys_wll_open (loader_data, filename)
  365. lt_dlloader_data_t loader_data;
  366. const char *filename;
  367. {
  368. lt_dlhandle cur;
  369. lt_module_t module;
  370. char *searchname = 0;
  371. char *ext;
  372. char self_name_buf[MAX_PATH];
  373. if (!filename) {
  374. /* Get the name of main module */
  375. *self_name_buf = 0;
  376. GetModuleFileName(NULL, self_name_buf, sizeof(self_name_buf));
  377. filename = ext = self_name_buf;
  378. }
  379. else ext = strrchr(filename, '.');
  380. if (ext) {
  381. /* FILENAME already has an extension. */
  382. searchname = strdup(filename);
  383. } else {
  384. /* Append a `.' to stop Windows from adding an
  385. implicit `.dll' extension. */
  386. searchname = (char*)lt_dlmalloc(2+ strlen(filename));
  387. if (!searchname) {
  388. last_error = LT_DLSTRERROR(NO_MEMORY);
  389. return 0;
  390. }
  391. strcpy(searchname, filename);
  392. strcat(searchname, ".");
  393. }
  394. module = LoadLibrary(searchname);
  395. lt_dlfree(searchname);
  396. /* libltdl expects this function to fail if it is unable
  397. to physically load the library. Sadly, LoadLibrary
  398. will search the loaded libraries for a match and return
  399. one of them if the path search load fails.
  400. We check whether LoadLibrary is returning a handle to
  401. an already loaded module, and simulate failure if we
  402. find one. */
  403. cur = handles;
  404. while (cur) {
  405. if (!cur->module) {
  406. cur = 0;
  407. break;
  408. }
  409. if (cur->module == module)
  410. break;
  411. cur = cur->next;
  412. }
  413. if (cur || !module) {
  414. last_error = LT_DLSTRERROR(CANNOT_OPEN);
  415. return 0;
  416. }
  417. return module;
  418. }
  419. static int
  420. sys_wll_close (loader_data, module)
  421. lt_dlloader_data_t loader_data;
  422. lt_module_t module;
  423. {
  424. if (FreeLibrary(module) == 0) {
  425. last_error = LT_DLSTRERROR(CANNOT_CLOSE);
  426. return 1;
  427. }
  428. return 0;
  429. }
  430. static lt_ptr_t
  431. sys_wll_sym (loader_data, module, symbol)
  432. lt_dlloader_data_t loader_data;
  433. lt_module_t module;
  434. const char *symbol;
  435. {
  436. lt_ptr_t address = GetProcAddress(module, symbol);
  437. if (!address)
  438. last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
  439. return address;
  440. }
  441. static struct lt_user_dlloader
  442. sys_wll = { 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 };
  443. #endif
  444. #ifdef __BEOS__
  445. /* dynamic linking for BeOS */
  446. #include <kernel/image.h>
  447. static lt_module_t
  448. sys_bedl_open (loader_data, filename)
  449. lt_dlloader_data_t loader_data;
  450. const char *filename;
  451. {
  452. image_id image = 0;
  453. if (filename) {
  454. image = load_add_on(filename);
  455. } else {
  456. image_info info;
  457. int32 cookie = 0;
  458. if (get_next_image_info(0, &cookie, &info) == B_OK)
  459. image = load_add_on(info.name);
  460. }
  461. if (image <= 0) {
  462. last_error = LT_DLSTRERROR(CANNOT_OPEN);
  463. return 0;
  464. }
  465. return (lt_module_t) image;
  466. }
  467. static int
  468. sys_bedl_close (loader_data, module)
  469. lt_dlloader_data_t loader_data;
  470. lt_module_t module;
  471. {
  472. if (unload_add_on((image_id)module) != B_OK) {
  473. last_error = LT_DLSTRERROR(CANNOT_CLOSE);
  474. return 1;
  475. }
  476. return 0;
  477. }
  478. static lt_ptr_t
  479. sys_bedl_sym (loader_data, module, symbol)
  480. lt_dlloader_data_t loader_data;
  481. lt_module_t module;
  482. const char *symbol;
  483. {
  484. lt_ptr_t address = 0;
  485. image_id image = (image_id)module;
  486. if (get_image_symbol(image, symbol, B_SYMBOL_TYPE_ANY,
  487. &address) != B_OK) {
  488. last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
  489. return 0;
  490. }
  491. return address;
  492. }
  493. static struct lt_user_dlloader
  494. sys_bedl = { 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 };
  495. #endif
  496. #if HAVE_DLD
  497. /* dynamic linking with dld */
  498. #if HAVE_DLD_H
  499. #include <dld.h>
  500. #endif
  501. static lt_module_t
  502. sys_dld_open (loader_data, filename)
  503. lt_dlloader_data_t loader_data;
  504. const char *filename;
  505. {
  506. lt_module_t module = strdup(filename);
  507. if (!module) {
  508. last_error = LT_DLSTRERROR(NO_MEMORY);
  509. return 0;
  510. }
  511. if (dld_link(filename) != 0) {
  512. last_error = LT_DLSTRERROR(CANNOT_OPEN);
  513. lt_dlfree(module);
  514. return 0;
  515. }
  516. return module;
  517. }
  518. static int
  519. sys_dld_close (loader_data, module)
  520. lt_dlloader_data_t loader_data;
  521. lt_module_t module;
  522. {
  523. if (dld_unlink_by_file((char*)(module), 1) != 0) {
  524. last_error = LT_DLSTRERROR(CANNOT_CLOSE);
  525. return 1;
  526. }
  527. lt_dlfree(module);
  528. return 0;
  529. }
  530. static lt_ptr_t
  531. sys_dld_sym (loader_data, module, symbol)
  532. lt_dlloader_data_t loader_data;
  533. lt_module_t module;
  534. const char *symbol;
  535. {
  536. lt_ptr_t address = dld_get_func(symbol);
  537. if (!address)
  538. last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
  539. return address;
  540. }
  541. static struct lt_user_dlloader
  542. sys_dld = { 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 };
  543. #endif
  544. /* emulate dynamic linking using preloaded_symbols */
  545. typedef struct lt_dlsymlists_t {
  546. struct lt_dlsymlists_t *next;
  547. const lt_dlsymlist *syms;
  548. } lt_dlsymlists_t;
  549. static const lt_dlsymlist *default_preloaded_symbols = 0;
  550. static lt_dlsymlists_t *preloaded_symbols = 0;
  551. static int
  552. presym_init (loader_data)
  553. lt_dlloader_data_t loader_data;
  554. {
  555. preloaded_symbols = 0;
  556. if (default_preloaded_symbols)
  557. return lt_dlpreload(default_preloaded_symbols);
  558. return 0;
  559. }
  560. static int
  561. presym_free_symlists LTDL_PARAMS((void))
  562. {
  563. lt_dlsymlists_t *lists = preloaded_symbols;
  564. while (lists) {
  565. lt_dlsymlists_t *tmp = lists;
  566. lists = lists->next;
  567. lt_dlfree(tmp);
  568. }
  569. preloaded_symbols = 0;
  570. return 0;
  571. }
  572. static int
  573. presym_exit (loader_data)
  574. lt_dlloader_data_t loader_data;
  575. {
  576. presym_free_symlists();
  577. return 0;
  578. }
  579. static int
  580. presym_add_symlist (preloaded)
  581. const lt_dlsymlist *preloaded;
  582. {
  583. lt_dlsymlists_t *tmp;
  584. lt_dlsymlists_t *lists = preloaded_symbols;
  585. while (lists) {
  586. if (lists->syms == preloaded)
  587. return 0;
  588. lists = lists->next;
  589. }
  590. tmp = (lt_dlsymlists_t*) lt_dlmalloc(sizeof(lt_dlsymlists_t));
  591. if (!tmp) {
  592. last_error = LT_DLSTRERROR(NO_MEMORY);
  593. return 1;
  594. }
  595. tmp->syms = preloaded;
  596. tmp->next = preloaded_symbols;
  597. preloaded_symbols = tmp;
  598. return 0;
  599. }
  600. static lt_module_t
  601. presym_open (loader_data, filename)
  602. lt_dlloader_data_t loader_data;
  603. const char *filename;
  604. {
  605. lt_dlsymlists_t *lists = preloaded_symbols;
  606. if (!lists) {
  607. last_error = LT_DLSTRERROR(NO_SYMBOLS);
  608. return 0;
  609. }
  610. if (!filename)
  611. filename = "@PROGRAM@";
  612. while (lists) {
  613. const lt_dlsymlist *syms = lists->syms;
  614. while (syms->name) {
  615. if (!syms->address &&
  616. strcmp(syms->name, filename) == 0) {
  617. return (lt_module_t) syms;
  618. }
  619. syms++;
  620. }
  621. lists = lists->next;
  622. }
  623. last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
  624. return 0;
  625. }
  626. static int
  627. presym_close (loader_data, module)
  628. lt_dlloader_data_t loader_data;
  629. lt_module_t module;
  630. {
  631. /* Just to silence gcc -Wall */
  632. module = 0;
  633. return 0;
  634. }
  635. static lt_ptr_t
  636. presym_sym (loader_data, module, symbol)
  637. lt_dlloader_data_t loader_data;
  638. lt_module_t module;
  639. const char *symbol;
  640. {
  641. lt_dlsymlist *syms = (lt_dlsymlist*)(module);
  642. syms++;
  643. while (syms->address) {
  644. if (strcmp(syms->name, symbol) == 0)
  645. return syms->address;
  646. syms++;
  647. }
  648. last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
  649. return 0;
  650. }
  651. static struct lt_user_dlloader
  652. presym = { 0, presym_open, presym_close, presym_sym, presym_exit, 0 };
  653. static char *user_search_path = 0;
  654. static lt_dlloader_t *loaders = 0;
  655. static lt_dlhandle handles = 0;
  656. static int initialized = 0;
  657. int
  658. lt_dlinit LTDL_PARAMS((void))
  659. {
  660. /* initialize libltdl */
  661. int errors = 0;
  662. if (initialized) { /* Initialize only at first call. */
  663. initialized++;
  664. return 0;
  665. }
  666. handles = 0;
  667. user_search_path = 0; /* empty search path */
  668. #if HAVE_LIBDL && !defined(__CYGWIN__)
  669. errors += lt_dlloader_add (lt_dlloader_next(0), &sys_dl, "dlopen");
  670. #endif
  671. #if HAVE_SHL_LOAD
  672. errors += lt_dlloader_add (lt_dlloader_next(0), &sys_shl, "dlopen");
  673. #endif
  674. #ifdef _WIN32
  675. errors += lt_dlloader_add (lt_dlloader_next(0), &sys_wll, "dlopen");
  676. #endif
  677. #ifdef __BEOS__
  678. errors += lt_dlloader_add (lt_dlloader_next(0), &sys_bedl, "dlopen");
  679. #endif
  680. #if HAVE_DLD
  681. errors += lt_dlloader_add (lt_dlloader_next(0), &sys_dld, "dld");
  682. #endif
  683. errors += lt_dlloader_add (lt_dlloader_next(0), &presym, "dlpreload");
  684. if (presym_init(presym.dlloader_data)) {
  685. last_error = LT_DLSTRERROR(INIT_LOADER);
  686. return 1;
  687. }
  688. if (errors != 0) {
  689. last_error = LT_DLSTRERROR(DLOPEN_NOT_SUPPORTED);
  690. return 1;
  691. }
  692. last_error = 0;
  693. initialized = 1;
  694. return 0;
  695. }
  696. int
  697. lt_dlpreload (preloaded)
  698. const lt_dlsymlist *preloaded;
  699. {
  700. if (preloaded)
  701. return presym_add_symlist(preloaded);
  702. presym_free_symlists();
  703. if (default_preloaded_symbols)
  704. return lt_dlpreload(default_preloaded_symbols);
  705. return 0;
  706. }
  707. int
  708. lt_dlpreload_default (preloaded)
  709. const lt_dlsymlist *preloaded;
  710. {
  711. default_preloaded_symbols = preloaded;
  712. return 0;
  713. }
  714. int
  715. lt_dlexit LTDL_PARAMS((void))
  716. {
  717. /* shut down libltdl */
  718. lt_dlloader_t *loader = loaders;
  719. int errors, level;
  720. if (!initialized) {
  721. last_error = LT_DLSTRERROR(SHUTDOWN);
  722. return 1;
  723. }
  724. if (initialized != 1) { /* shut down only at last call. */
  725. initialized--;
  726. return 0;
  727. }
  728. /* close all modules */
  729. errors = 0;
  730. for (level = 1; handles; level++) {
  731. lt_dlhandle cur = handles;
  732. while (cur) {
  733. lt_dlhandle tmp = cur;
  734. cur = cur->next;
  735. if (tmp->info.ref_count <= level)
  736. if (lt_dlclose(tmp))
  737. errors++;
  738. }
  739. }
  740. /* close all loaders */
  741. while (loader) {
  742. lt_dlloader_t *next = loader->next;
  743. lt_dlloader_data_t data = loader->dlloader_data;
  744. if (loader->dlloader_exit && loader->dlloader_exit(data))
  745. errors++;
  746. lt_dlfree (loader);
  747. loader = next;
  748. }
  749. initialized = 0;
  750. return errors;
  751. }
  752. static int
  753. tryall_dlopen (handle, filename)
  754. lt_dlhandle *handle;
  755. const char *filename;
  756. {
  757. lt_dlhandle cur = handles;
  758. lt_dlloader_t *loader = loaders;
  759. const char *saved_error = last_error;
  760. /* check whether the module was already opened */
  761. while (cur) {
  762. /* try to dlopen the program itself? */
  763. if (!cur->info.filename && !filename)
  764. break;
  765. if (cur->info.filename && filename &&
  766. strcmp(cur->info.filename, filename) == 0)
  767. break;
  768. cur = cur->next;
  769. }
  770. if (cur) {
  771. cur->info.ref_count++;
  772. *handle = cur;
  773. return 0;
  774. }
  775. cur = *handle;
  776. if (filename) {
  777. cur->info.filename = strdup(filename);
  778. if (!cur->info.filename) {
  779. last_error = LT_DLSTRERROR(NO_MEMORY);
  780. return 1;
  781. }
  782. } else
  783. cur->info.filename = 0;
  784. while (loader) {
  785. lt_dlloader_data_t data = loader->dlloader_data;
  786. cur->module = loader->module_open(data, filename);
  787. if (cur->module != 0)
  788. break;
  789. loader = loader->next;
  790. }
  791. if (!loader) {
  792. if (cur->info.filename)
  793. lt_dlfree(cur->info.filename);
  794. return 1;
  795. }
  796. cur->loader = loader;
  797. last_error = saved_error;
  798. return 0;
  799. }
  800. static int
  801. find_module (handle, dir, libdir, dlname, old_name, installed)
  802. lt_dlhandle *handle;
  803. const char *dir;
  804. const char *libdir;
  805. const char *dlname;
  806. const char *old_name;
  807. int installed;
  808. {
  809. int error;
  810. char *filename;
  811. /* try to open the old library first; if it was dlpreopened,
  812. we want the preopened version of it, even if a dlopenable
  813. module is available */
  814. if (old_name && tryall_dlopen(handle, old_name) == 0)
  815. return 0;
  816. /* try to open the dynamic library */
  817. if (dlname) {
  818. /* try to open the installed module */
  819. if (installed && libdir) {
  820. filename = (char*)
  821. lt_dlmalloc(strlen(libdir)+1+strlen(dlname)+1);
  822. if (!filename) {
  823. last_error = LT_DLSTRERROR(NO_MEMORY);
  824. return 1;
  825. }
  826. sprintf (filename, "%s/%s", libdir, dlname);
  827. error = tryall_dlopen(handle, filename) != 0;
  828. lt_dlfree(filename);
  829. if (!error)
  830. return 0;
  831. }
  832. /* try to open the not-installed module */
  833. if (!installed) {
  834. filename = (char*)
  835. lt_dlmalloc((dir ? strlen(dir) : 0)
  836. + strlen(objdir) + strlen(dlname) + 1);
  837. if (!filename) {
  838. last_error = LT_DLSTRERROR(NO_MEMORY);
  839. return 1;
  840. }
  841. if (dir)
  842. strcpy(filename, dir);
  843. else
  844. *filename = 0;
  845. strcat(filename, objdir);
  846. strcat(filename, dlname);
  847. error = tryall_dlopen(handle, filename) != 0;
  848. lt_dlfree(filename);
  849. if (!error)
  850. return 0;
  851. }
  852. /* maybe it was moved to another directory */
  853. {
  854. filename = (char*)
  855. lt_dlmalloc((dir ? strlen(dir) : 0)
  856. + strlen(dlname) + 1);
  857. if (dir)
  858. strcpy(filename, dir);
  859. else
  860. *filename = 0;
  861. strcat(filename, dlname);
  862. error = tryall_dlopen(handle, filename) != 0;
  863. lt_dlfree(filename);
  864. if (!error)
  865. return 0;
  866. }
  867. }
  868. return 1;
  869. }
  870. static char*
  871. canonicalize_path (path)
  872. const char *path;
  873. {
  874. char *canonical = 0;
  875. if (path && *path) {
  876. char *ptr = strdup (path);
  877. canonical = ptr;
  878. #ifdef LTDL_DIRSEP_CHAR
  879. /* Avoid this overhead where '/' is the only separator. */
  880. while (ptr = strchr (ptr, LTDL_DIRSEP_CHAR))
  881. *ptr++ = '/';
  882. #endif
  883. }
  884. return canonical;
  885. }
  886. static lt_ptr_t
  887. find_file (basename, search_path, pdir, handle)
  888. const char *basename;
  889. const char *search_path;
  890. char **pdir;
  891. lt_dlhandle *handle;
  892. {
  893. /* when handle != NULL search a library, otherwise a file */
  894. /* return NULL on failure, otherwise the file/handle */
  895. lt_ptr_t result = 0;
  896. char *filename = 0;
  897. int filenamesize = 0;
  898. int lenbase = strlen(basename);
  899. char *canonical = 0, *next = 0;
  900. if (!search_path || !*search_path) {
  901. last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
  902. return 0;
  903. }
  904. canonical = canonicalize_path (search_path);
  905. if (!canonical) {
  906. last_error = LT_DLSTRERROR(NO_MEMORY);
  907. goto cleanup;
  908. }
  909. next = canonical;
  910. while (next) {
  911. int lendir;
  912. char *cur = next;
  913. next = strchr(cur, LTDL_PATHSEP_CHAR);
  914. if (!next)
  915. next = cur + strlen(cur);
  916. lendir = next - cur;
  917. if (*next == LTDL_PATHSEP_CHAR)
  918. ++next;
  919. else
  920. next = 0;
  921. if (lendir == 0)
  922. continue;
  923. if (lendir + 1 + lenbase >= filenamesize) {
  924. if (filename)
  925. lt_dlfree(filename);
  926. filenamesize = lendir + 1 + lenbase + 1;
  927. filename = (char*) lt_dlmalloc(filenamesize);
  928. if (!filename) {
  929. last_error = LT_DLSTRERROR(NO_MEMORY);
  930. goto cleanup;
  931. }
  932. }
  933. strncpy(filename, cur, lendir);
  934. if (filename[lendir-1] != '/')
  935. filename[lendir++] = '/';
  936. strcpy(filename+lendir, basename);
  937. if (handle) {
  938. if (tryall_dlopen(handle, filename) == 0) {
  939. result = (lt_ptr_t) handle;
  940. goto cleanup;
  941. }
  942. } else {
  943. FILE *file = fopen(filename, LTDL_READTEXT_MODE);
  944. if (file) {
  945. if (*pdir)
  946. lt_dlfree(*pdir);
  947. filename[lendir] = '\0';
  948. *pdir = strdup(filename);
  949. if (!*pdir) {
  950. /* We could have even avoided the
  951. strdup, but there would be some
  952. memory overhead. */
  953. *pdir = filename;
  954. filename = 0;
  955. }
  956. result = (lt_ptr_t) file;
  957. goto cleanup;
  958. }
  959. }
  960. }
  961. last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
  962. cleanup:
  963. if (filename)
  964. lt_dlfree(filename);
  965. if (canonical)
  966. lt_dlfree(canonical);
  967. return result;
  968. }
  969. static int
  970. load_deplibs(handle, deplibs)
  971. lt_dlhandle handle;
  972. char *deplibs;
  973. {
  974. char *p, *save_search_path;
  975. int i;
  976. int ret = 1, depcount = 0;
  977. char **names = 0;
  978. lt_dlhandle *handles = 0;
  979. handle->depcount = 0;
  980. if (!deplibs)
  981. return 0;
  982. save_search_path = strdup(user_search_path);
  983. if (user_search_path && !save_search_path) {
  984. last_error = LT_DLSTRERROR(NO_MEMORY);
  985. return 1;
  986. }
  987. p = deplibs;
  988. /* extract search paths and count deplibs */
  989. while (*p) {
  990. if (!isspace(*p)) {
  991. char *end = p+1;
  992. while (*end && !isspace(*end)) end++;
  993. if (strncmp(p, "-L", 2) == 0 ||
  994. strncmp(p, "-R", 2) == 0) {
  995. char save = *end;
  996. *end = 0; /* set a temporary string terminator */
  997. if (lt_dladdsearchdir(p+2))
  998. goto cleanup;
  999. *end = save;
  1000. } else
  1001. depcount++;
  1002. p = end;
  1003. } else
  1004. p++;
  1005. }
  1006. if (!depcount) {
  1007. ret = 0;
  1008. goto cleanup;
  1009. }
  1010. names = (char**)lt_dlmalloc(depcount * sizeof(char*));
  1011. if (!names)
  1012. goto cleanup;
  1013. handles = (lt_dlhandle*)lt_dlmalloc(depcount * sizeof(lt_dlhandle*));
  1014. if (!handles)
  1015. goto cleanup;
  1016. depcount = 0;
  1017. /* now only extract the actual deplibs */
  1018. p = deplibs;
  1019. while (*p) {
  1020. if (!isspace(*p)) {
  1021. char *end = p+1;
  1022. while (*end && !isspace(*end)) end++;
  1023. if (strncmp(p, "-L", 2) != 0 &&
  1024. strncmp(p, "-R", 2) != 0) {
  1025. char *name;
  1026. char save = *end;
  1027. *end = 0; /* set a temporary string terminator */
  1028. if (strncmp(p, "-l", 2) == 0) {
  1029. name = lt_dlmalloc(3+ /* "lib" */
  1030. strlen(p+2)+1);
  1031. if (name)
  1032. sprintf (name, "lib%s", p+2);
  1033. } else
  1034. name = strdup(p);
  1035. if (name)
  1036. names[depcount++] = name;
  1037. else
  1038. goto cleanup_names;
  1039. *end = save;
  1040. }
  1041. p = end;
  1042. } else
  1043. p++;
  1044. }
  1045. /* load the deplibs (in reverse order) */
  1046. for (i = 0; i < depcount; i++) {
  1047. lt_dlhandle handle = lt_dlopenext(names[depcount-1-i]);
  1048. if (!handle) {
  1049. int j;
  1050. for (j = 0; j < i; j++)
  1051. lt_dlclose(handles[j]);
  1052. last_error = LT_DLSTRERROR(DEPLIB_NOT_FOUND);
  1053. goto cleanup_names;
  1054. }
  1055. handles[i] = handle;
  1056. }
  1057. handle->depcount = depcount;
  1058. handle->deplibs = handles;
  1059. handles = 0;
  1060. ret = 0;
  1061. cleanup_names:
  1062. for (i = 0; i < depcount; i++)
  1063. lt_dlfree(names[i]);
  1064. cleanup:
  1065. if (names)
  1066. lt_dlfree(names);
  1067. if (handles)
  1068. lt_dlfree(handles);
  1069. /* restore the old search path */
  1070. if (user_search_path)
  1071. lt_dlfree(user_search_path);
  1072. user_search_path = save_search_path;
  1073. return ret;
  1074. }
  1075. static int
  1076. unload_deplibs(handle)
  1077. lt_dlhandle handle;
  1078. {
  1079. int i;
  1080. int errors = 0;
  1081. if (!handle->depcount)
  1082. return 0;
  1083. for (i = 0; i < handle->depcount; i++)
  1084. errors += lt_dlclose(handle->deplibs[i]);
  1085. return errors;
  1086. }
  1087. static inline int
  1088. trim (dest, str)
  1089. char **dest;
  1090. const char *str;
  1091. {
  1092. /* remove the leading and trailing "'" from str
  1093. and store the result in dest */
  1094. char *tmp;
  1095. const char *end = strrchr(str, '\'');
  1096. int len = strlen(str);
  1097. if (*dest)
  1098. lt_dlfree(*dest);
  1099. if (len > 3 && str[0] == '\'') {
  1100. tmp = (char*) lt_dlmalloc(end - str);
  1101. if (!tmp) {
  1102. last_error = LT_DLSTRERROR(NO_MEMORY);
  1103. return 1;
  1104. }
  1105. strncpy(tmp, &str[1], (end - str) - 1);
  1106. tmp[len-3] = '\0';
  1107. *dest = tmp;
  1108. } else
  1109. *dest = 0;
  1110. return 0;
  1111. }
  1112. static inline int
  1113. free_vars( dlname, oldname, libdir, deplibs)
  1114. char *dlname;
  1115. char *oldname;
  1116. char *libdir;
  1117. char *deplibs;
  1118. {
  1119. if (dlname)
  1120. lt_dlfree(dlname);
  1121. if (oldname)
  1122. lt_dlfree(oldname);
  1123. if (libdir)
  1124. lt_dlfree(libdir);
  1125. if (deplibs)
  1126. lt_dlfree(deplibs);
  1127. return 0;
  1128. }
  1129. lt_dlhandle
  1130. lt_dlopen (filename)
  1131. const char *filename;
  1132. {
  1133. lt_dlhandle handle = 0, newhandle;
  1134. const char *ext;
  1135. const char *saved_error = last_error;
  1136. char *canonical = 0, *basename = 0, *dir = 0, *name = 0;
  1137. if (!filename) {
  1138. handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
  1139. if (!handle) {
  1140. last_error = LT_DLSTRERROR(NO_MEMORY);
  1141. return 0;
  1142. }
  1143. handle->info.ref_count = 0;
  1144. handle->depcount = 0;
  1145. handle->deplibs = 0;
  1146. newhandle = handle;
  1147. if (tryall_dlopen(&newhandle, 0) != 0) {
  1148. lt_dlfree(handle);
  1149. return 0;
  1150. }
  1151. goto register_handle;
  1152. }
  1153. canonical = canonicalize_path (filename);
  1154. if (!canonical) {
  1155. last_error = LT_DLSTRERROR(NO_MEMORY);
  1156. if (handle)
  1157. lt_dlfree(handle);
  1158. return 0;
  1159. }
  1160. basename = strrchr(canonical, '/');
  1161. if (basename) {
  1162. basename++;
  1163. dir = (char*) lt_dlmalloc(basename - canonical + 1);
  1164. if (!dir) {
  1165. last_error = LT_DLSTRERROR(NO_MEMORY);
  1166. handle = 0;
  1167. goto cleanup;
  1168. }
  1169. strncpy(dir, canonical, basename - canonical);
  1170. dir[basename - canonical] = '\0';
  1171. } else
  1172. basename = canonical;
  1173. /* check whether we open a libtool module (.la extension) */
  1174. ext = strrchr(basename, '.');
  1175. if (ext && strcmp(ext, ".la") == 0) {
  1176. /* this seems to be a libtool module */
  1177. FILE *file;
  1178. int i;
  1179. char *dlname = 0, *old_name = 0;
  1180. char *libdir = 0, *deplibs = 0;
  1181. char *line;
  1182. int error = 0;
  1183. /* if we can't find the installed flag, it is probably an
  1184. installed libtool archive, produced with an old version
  1185. of libtool */
  1186. int installed = 1;
  1187. /* extract the module name from the file name */
  1188. name = (char*) lt_dlmalloc(ext - basename + 1);
  1189. if (!name) {
  1190. last_error = LT_DLSTRERROR(NO_MEMORY);
  1191. handle = 0;
  1192. goto cleanup;
  1193. }
  1194. /* canonicalize the module name */
  1195. for (i = 0; i < ext - basename; i++)
  1196. if (isalnum((int)(basename[i])))
  1197. name[i] = basename[i];
  1198. else
  1199. name[i] = '_';
  1200. name[ext - basename] = '\0';
  1201. /* now try to open the .la file */
  1202. file = fopen(filename, LTDL_READTEXT_MODE);
  1203. if (!file)
  1204. last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
  1205. if (!file && !dir) {
  1206. /* try other directories */
  1207. file = (FILE*) find_file(basename,
  1208. user_search_path,
  1209. &dir, 0);
  1210. if (!file)
  1211. file = (FILE*) find_file(basename,
  1212. getenv("LTDL_LIBRARY_PATH"),
  1213. &dir, 0);
  1214. #ifdef LTDL_SHLIBPATH_VAR
  1215. if (!file)
  1216. file = (FILE*) find_file(basename,
  1217. getenv(LTDL_SHLIBPATH_VAR),
  1218. &dir, 0);
  1219. #endif
  1220. #ifdef LTDL_SYSSEARCHPATH
  1221. if (!file)
  1222. file = (FILE*) find_file(basename,
  1223. sys_search_path,
  1224. &dir, 0);
  1225. #endif
  1226. }
  1227. if (!file) {
  1228. handle = 0;
  1229. goto cleanup;
  1230. }
  1231. line = (char*) lt_dlmalloc(LTDL_FILENAME_MAX);
  1232. if (!line) {
  1233. fclose(file);
  1234. last_error = LT_DLSTRERROR(NO_MEMORY);
  1235. handle = 0;
  1236. goto cleanup;
  1237. }
  1238. /* read the .la file */
  1239. while (!feof(file)) {
  1240. if (!fgets(line, LTDL_FILENAME_MAX, file))
  1241. break;
  1242. if (line[0] == '\n' || line[0] == '#')
  1243. continue;
  1244. # undef STR_DLNAME
  1245. # define STR_DLNAME "dlname="
  1246. if (strncmp(line, STR_DLNAME,
  1247. sizeof(STR_DLNAME) - 1) == 0)
  1248. error = trim(&dlname,
  1249. &line[sizeof(STR_DLNAME) - 1]);
  1250. else
  1251. # undef STR_OLD_LIBRARY
  1252. # define STR_OLD_LIBRARY "old_library="
  1253. if (strncmp(line, STR_OLD_LIBRARY,
  1254. sizeof(STR_OLD_LIBRARY) - 1) == 0)
  1255. error = trim(&old_name,
  1256. &line[sizeof(STR_OLD_LIBRARY) - 1]);
  1257. else
  1258. # undef STR_LIBDIR
  1259. # define STR_LIBDIR "libdir="
  1260. if (strncmp(line, STR_LIBDIR,
  1261. sizeof(STR_LIBDIR) - 1) == 0)
  1262. error = trim(&libdir,
  1263. &line[sizeof(STR_LIBDIR) - 1]);
  1264. else
  1265. # undef STR_DL_DEPLIBS
  1266. # define STR_DL_DEPLIBS "dl_dependency_libs="
  1267. if (strncmp(line, STR_DL_DEPLIBS,
  1268. sizeof(STR_DL_DEPLIBS) - 1) == 0)
  1269. error = trim(&deplibs,
  1270. &line[sizeof(STR_DL_DEPLIBS) - 1]);
  1271. else
  1272. if (strcmp(line, "installed=yes\n") == 0)
  1273. installed = 1;
  1274. else
  1275. if (strcmp(line, "installed=no\n") == 0)
  1276. installed = 0;
  1277. else
  1278. # undef STR_LIBRARY_NAMES
  1279. # define STR_LIBRARY_NAMES "library_names="
  1280. if (! dlname &&
  1281. strncmp(line, STR_LIBRARY_NAMES,
  1282. sizeof(STR_LIBRARY_NAMES) - 1) == 0) {
  1283. char *last_libname;
  1284. error = trim(&dlname,
  1285. &line[sizeof(STR_LIBRARY_NAMES) - 1]);
  1286. if (! error && dlname &&
  1287. (last_libname = strrchr(dlname, ' ')) != NULL) {
  1288. last_libname = strdup(last_libname + 1);
  1289. free(dlname);
  1290. dlname = last_libname;
  1291. }
  1292. }
  1293. if (error)
  1294. break;
  1295. }
  1296. fclose(file);
  1297. lt_dlfree(line);
  1298. /* allocate the handle */
  1299. handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
  1300. if (!handle || error) {
  1301. if (handle)
  1302. lt_dlfree(handle);
  1303. if (!error)
  1304. last_error = LT_DLSTRERROR(NO_MEMORY);
  1305. free_vars(dlname, old_name, libdir, deplibs);
  1306. /* handle is already set to 0 */
  1307. goto cleanup;
  1308. }
  1309. handle->info.ref_count = 0;
  1310. if (load_deplibs(handle, deplibs) == 0) {
  1311. newhandle = handle;
  1312. /* find_module may replace newhandle */
  1313. if (find_module(&newhandle, dir, libdir,
  1314. dlname, old_name, installed)) {
  1315. unload_deplibs(handle);
  1316. error = 1;
  1317. }
  1318. } else
  1319. error = 1;
  1320. free_vars(dlname, old_name, libdir, deplibs);
  1321. if (error) {
  1322. lt_dlfree(handle);
  1323. handle = 0;
  1324. goto cleanup;
  1325. }
  1326. if (handle != newhandle)
  1327. unload_deplibs(handle);
  1328. } else {
  1329. /* not a libtool module */
  1330. handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
  1331. if (!handle) {
  1332. last_error = LT_DLSTRERROR(NO_MEMORY);
  1333. /* handle is already set to 0 */
  1334. goto cleanup;
  1335. }
  1336. handle->info.ref_count = 0;
  1337. /* non-libtool modules don't have dependencies */
  1338. handle->depcount = 0;
  1339. handle->deplibs = 0;
  1340. newhandle = handle;
  1341. if (tryall_dlopen(&newhandle, filename)
  1342. && (dir
  1343. || (!find_file(basename, user_search_path,
  1344. 0, &newhandle)
  1345. && !find_file(basename,
  1346. getenv("LTDL_LIBRARY_PATH"),
  1347. 0, &newhandle)
  1348. #ifdef LTDL_SHLIBPATH_VAR
  1349. && !find_file(basename,
  1350. getenv(LTDL_SHLIBPATH_VAR),
  1351. 0, &newhandle)
  1352. #endif
  1353. #ifdef LTDL_SYSSEARCHPATH
  1354. && !find_file(basename, sys_search_path,
  1355. 0, &newhandle)
  1356. #endif
  1357. ))) {
  1358. lt_dlfree(handle);
  1359. handle = 0;
  1360. goto cleanup;
  1361. }
  1362. }
  1363. register_handle:
  1364. if (newhandle != handle) {
  1365. lt_dlfree(handle);
  1366. handle = newhandle;
  1367. }
  1368. if (!handle->info.ref_count) {
  1369. handle->info.ref_count = 1;
  1370. handle->info.name = name;
  1371. handle->next = handles;
  1372. handles = handle;
  1373. name = 0; /* don't free this during `cleanup' */
  1374. }
  1375. last_error = saved_error;
  1376. cleanup:
  1377. if (dir)
  1378. lt_dlfree(dir);
  1379. if (name)
  1380. lt_dlfree(name);
  1381. if (canonical)
  1382. lt_dlfree(canonical);
  1383. return handle;
  1384. }
  1385. lt_dlhandle
  1386. lt_dlopenext (filename)
  1387. const char *filename;
  1388. {
  1389. lt_dlhandle handle;
  1390. char *tmp;
  1391. int len;
  1392. const char *saved_error = last_error;
  1393. if (!filename)
  1394. return lt_dlopen(filename);
  1395. len = strlen(filename);
  1396. if (!len) {
  1397. last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
  1398. return 0;
  1399. }
  1400. /* try the normal file name */
  1401. handle = lt_dlopen(filename);
  1402. if (handle)
  1403. return handle;
  1404. /* try "filename.la" */
  1405. tmp = (char*) lt_dlmalloc(len+4);
  1406. if (!tmp) {
  1407. last_error = LT_DLSTRERROR(NO_MEMORY);
  1408. return 0;
  1409. }
  1410. strcpy(tmp, filename);
  1411. strcat(tmp, ".la");
  1412. handle = lt_dlopen(tmp);
  1413. if (handle) {
  1414. last_error = saved_error;
  1415. lt_dlfree(tmp);
  1416. return handle;
  1417. }
  1418. #ifdef LTDL_SHLIB_EXT
  1419. /* try "filename.EXT" */
  1420. if (strlen(shlib_ext) > 3) {
  1421. lt_dlfree(tmp);
  1422. tmp = (char*) lt_dlmalloc(len + strlen(shlib_ext) + 1);
  1423. if (!tmp) {
  1424. last_error = LT_DLSTRERROR(NO_MEMORY);
  1425. return 0;
  1426. }
  1427. strcpy(tmp, filename);
  1428. } else
  1429. tmp[len] = '\0';
  1430. strcat(tmp, shlib_ext);
  1431. handle = lt_dlopen(tmp);
  1432. if (handle) {
  1433. last_error = saved_error;
  1434. lt_dlfree(tmp);
  1435. return handle;
  1436. }
  1437. #endif
  1438. last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
  1439. lt_dlfree(tmp);
  1440. return 0;
  1441. }
  1442. int
  1443. lt_dlclose (handle)
  1444. lt_dlhandle handle;
  1445. {
  1446. lt_dlhandle cur, last;
  1447. /* check whether the handle is valid */
  1448. last = cur = handles;
  1449. while (cur && handle != cur) {
  1450. last = cur;
  1451. cur = cur->next;
  1452. }
  1453. if (!cur) {
  1454. last_error = LT_DLSTRERROR(INVALID_HANDLE);
  1455. return 1;
  1456. }
  1457. handle->info.ref_count--;
  1458. if (!handle->info.ref_count) {
  1459. int error;
  1460. lt_dlloader_data_t data = handle->loader->dlloader_data;
  1461. if (handle != handles)
  1462. last->next = handle->next;
  1463. else
  1464. handles = handle->next;
  1465. error = handle->loader->module_close(data, handle->module);
  1466. error += unload_deplibs(handle);
  1467. if (handle->info.filename)
  1468. lt_dlfree(handle->info.filename);
  1469. if (handle->info.name)
  1470. lt_dlfree(handle->info.name);
  1471. lt_dlfree(handle);
  1472. return error;
  1473. }
  1474. return 0;
  1475. }
  1476. lt_ptr_t
  1477. lt_dlsym (handle, symbol)
  1478. lt_dlhandle handle;
  1479. const char *symbol;
  1480. {
  1481. int lensym;
  1482. char lsym[LTDL_SYMBOL_LENGTH];
  1483. char *sym;
  1484. lt_ptr_t address;
  1485. lt_dlloader_data_t data;
  1486. if (!handle) {
  1487. last_error = LT_DLSTRERROR(INVALID_HANDLE);
  1488. return 0;
  1489. }
  1490. if (!symbol) {
  1491. last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
  1492. return 0;
  1493. }
  1494. lensym = strlen(symbol);
  1495. if (handle->loader->sym_prefix)
  1496. lensym += strlen(handle->loader->sym_prefix);
  1497. if (handle->info.name)
  1498. lensym += strlen(handle->info.name);
  1499. if (lensym + LTDL_SYMBOL_OVERHEAD < LTDL_SYMBOL_LENGTH)
  1500. sym = lsym;
  1501. else
  1502. sym = (char*) lt_dlmalloc(lensym + LTDL_SYMBOL_OVERHEAD + 1);
  1503. if (!sym) {
  1504. last_error = LT_DLSTRERROR(BUFFER_OVERFLOW);
  1505. return 0;
  1506. }
  1507. data = handle->loader->dlloader_data;
  1508. if (handle->info.name) {
  1509. const char *saved_error = last_error;
  1510. /* this is a libtool module */
  1511. if (handle->loader->sym_prefix) {
  1512. strcpy(sym, handle->loader->sym_prefix);
  1513. strcat(sym, handle->info.name);
  1514. } else
  1515. strcpy(sym, handle->info.name);
  1516. strcat(sym, "_LTX_");
  1517. strcat(sym, symbol);
  1518. /* try "modulename_LTX_symbol" */
  1519. address = handle->loader->find_sym(data, handle->module, sym);
  1520. if (address) {
  1521. if (sym != lsym)
  1522. lt_dlfree(sym);
  1523. return address;
  1524. }
  1525. last_error = saved_error;
  1526. }
  1527. /* otherwise try "symbol" */
  1528. if (handle->loader->sym_prefix) {
  1529. strcpy(sym, handle->loader->sym_prefix);
  1530. strcat(sym, symbol);
  1531. } else
  1532. strcpy(sym, symbol);
  1533. address = handle->loader->find_sym(data, handle->module, sym);
  1534. if (sym != lsym)
  1535. lt_dlfree(sym);
  1536. return address;
  1537. }
  1538. const char *
  1539. lt_dlerror LTDL_PARAMS((void))
  1540. {
  1541. const char *error = last_error;
  1542. last_error = 0;
  1543. return error;
  1544. }
  1545. int
  1546. lt_dladdsearchdir (search_dir)
  1547. const char *search_dir;
  1548. {
  1549. if (!search_dir || !strlen(search_dir))
  1550. return 0;
  1551. if (!user_search_path) {
  1552. user_search_path = strdup(search_dir);
  1553. if (!user_search_path) {
  1554. last_error = LT_DLSTRERROR(NO_MEMORY);
  1555. return 1;
  1556. }
  1557. } else {
  1558. char *new_search_path = (char*)
  1559. lt_dlmalloc(strlen(user_search_path) +
  1560. strlen(search_dir) + 2); /* ':' + '\0' == 2 */
  1561. if (!new_search_path) {
  1562. last_error = LT_DLSTRERROR(NO_MEMORY);
  1563. return 1;
  1564. }
  1565. sprintf (new_search_path, "%s%c%s", user_search_path,
  1566. LTDL_PATHSEP_CHAR, search_dir);
  1567. lt_dlfree(user_search_path);
  1568. user_search_path = new_search_path;
  1569. }
  1570. return 0;
  1571. }
  1572. int
  1573. lt_dlsetsearchpath (search_path)
  1574. const char *search_path;
  1575. {
  1576. if (user_search_path)
  1577. lt_dlfree(user_search_path);
  1578. user_search_path = 0; /* reset the search path */
  1579. if (!search_path || !strlen(search_path))
  1580. return 0;
  1581. user_search_path = strdup(search_path);
  1582. if (!user_search_path)
  1583. return 1;
  1584. return 0;
  1585. }
  1586. const char *
  1587. lt_dlgetsearchpath LTDL_PARAMS((void))
  1588. {
  1589. return user_search_path;
  1590. }
  1591. const lt_dlinfo *
  1592. lt_dlgetinfo (handle)
  1593. lt_dlhandle handle;
  1594. {
  1595. if (!handle) {
  1596. last_error = LT_DLSTRERROR(INVALID_HANDLE);
  1597. return 0;
  1598. }
  1599. return &(handle->info);
  1600. }
  1601. int
  1602. lt_dlforeach (func, data)
  1603. int (*func) LTDL_PARAMS((lt_dlhandle handle, lt_ptr_t data));
  1604. lt_ptr_t data;
  1605. {
  1606. lt_dlhandle cur = handles;
  1607. while (cur) {
  1608. lt_dlhandle tmp = cur;
  1609. cur = cur->next;
  1610. if (func(tmp, data))
  1611. return 1;
  1612. }
  1613. return 0;
  1614. }
  1615. int
  1616. lt_dlloader_add (place, dlloader, loader_name)
  1617. lt_dlloader_t *place;
  1618. const struct lt_user_dlloader *dlloader;
  1619. const char *loader_name;
  1620. {
  1621. lt_dlloader_t *node = 0, *ptr = 0;
  1622. if ((dlloader == 0) /* diagnose null parameters */
  1623. || (dlloader->module_open == 0)
  1624. || (dlloader->module_close == 0)
  1625. || (dlloader->find_sym == 0)) {
  1626. last_error = LT_DLSTRERROR(INVALID_LOADER);
  1627. return 1;
  1628. }
  1629. /* Create a new dlloader node with copies of the user callbacks. */
  1630. node = (lt_dlloader_t *) lt_dlmalloc (sizeof (lt_dlloader_t));
  1631. if (node == 0) {
  1632. last_error = LT_DLSTRERROR(NO_MEMORY);
  1633. return 1;
  1634. }
  1635. node->next = 0;
  1636. node->loader_name = loader_name;
  1637. node->sym_prefix = dlloader->sym_prefix;
  1638. node->dlloader_exit = dlloader->dlloader_exit;
  1639. node->module_open = dlloader->module_open;
  1640. node->module_close = dlloader->module_close;
  1641. node->find_sym = dlloader->find_sym;
  1642. node->dlloader_data = dlloader->dlloader_data;
  1643. if (!loaders)
  1644. /* If there are no loaders, NODE becomes the list! */
  1645. loaders = node;
  1646. else if (!place) {
  1647. /* If PLACE is not set, add NODE to the end of the
  1648. LOADERS list. */
  1649. for (ptr = loaders; ptr->next; ptr = ptr->next)
  1650. /*NOWORK*/;
  1651. ptr->next = node;
  1652. } else if (loaders == place) {
  1653. /* If PLACE is the first loader, NODE goes first. */
  1654. node->next = place;
  1655. loaders = node;
  1656. } else {
  1657. /* Find the node immediately preceding PLACE. */
  1658. for (ptr = loaders; ptr->next != place; ptr = ptr->next)
  1659. /*NOWORK*/;
  1660. if (ptr->next != place) {
  1661. last_error = LT_DLSTRERROR(INVALID_LOADER);
  1662. return 1;
  1663. }
  1664. /* Insert NODE between PTR and PLACE. */
  1665. node->next = place;
  1666. ptr->next = node;
  1667. }
  1668. return 0;
  1669. }
  1670. int
  1671. lt_dlloader_remove (loader_name)
  1672. const char *loader_name;
  1673. {
  1674. lt_dlloader_t *place = lt_dlloader_find (loader_name);
  1675. lt_dlhandle handle;
  1676. int result = 0;
  1677. if (!place) {
  1678. last_error = LT_DLSTRERROR(INVALID_LOADER);
  1679. return 1;
  1680. }
  1681. /* Fail if there are any open modules which use this loader. */
  1682. for (handle = handles; handle; handle = handle->next)
  1683. if (handle->loader == place) {
  1684. last_error = LT_DLSTRERROR(REMOVE_LOADER);
  1685. return 1;
  1686. }
  1687. if (place == loaders)
  1688. /* PLACE is the first loader in the list. */
  1689. loaders = loaders->next;
  1690. else {
  1691. /* Find the loader before the one being removed. */
  1692. lt_dlloader_t *prev;
  1693. for (prev = loaders; prev->next; prev = prev->next)
  1694. if (!strcmp (prev->next->loader_name, loader_name))
  1695. break;
  1696. place = prev->next;
  1697. prev->next = prev->next->next;
  1698. }
  1699. if (place->dlloader_exit)
  1700. result = place->dlloader_exit (place->dlloader_data);
  1701. lt_dlfree (place);
  1702. return result;
  1703. }
  1704. lt_dlloader_t *
  1705. lt_dlloader_next (place)
  1706. lt_dlloader_t *place;
  1707. {
  1708. return place ? place->next : loaders;
  1709. }
  1710. const char *
  1711. lt_dlloader_name (place)
  1712. lt_dlloader_t *place;
  1713. {
  1714. if (!place)
  1715. last_error = LT_DLSTRERROR(INVALID_LOADER);
  1716. return place ? place->loader_name : 0;
  1717. }
  1718. lt_dlloader_data_t *
  1719. lt_dlloader_data (place)
  1720. lt_dlloader_t *place;
  1721. {
  1722. if (!place)
  1723. last_error = LT_DLSTRERROR(INVALID_LOADER);
  1724. return place ? &(place->dlloader_data) : 0;
  1725. }
  1726. lt_dlloader_t *
  1727. lt_dlloader_find (loader_name)
  1728. const char *loader_name;
  1729. {
  1730. lt_dlloader_t *place = 0;
  1731. for (place = loaders; place; place = place->next)
  1732. if (strcmp (place->loader_name, loader_name) == 0)
  1733. break;
  1734. return place;
  1735. }
  1736. static const char **user_error_strings = 0;
  1737. static int errorcode = LTDL_ERROR_MAX;
  1738. int
  1739. lt_dladderror (diagnostic)
  1740. const char *diagnostic;
  1741. {
  1742. int index = errorcode - LTDL_ERROR_MAX;
  1743. const char **temp = 0;
  1744. /* realloc is not entirely portable, so simulate it using
  1745. lt_dlmalloc and lt_dlfree. */
  1746. temp = (const char **) lt_dlmalloc ((1+index) * sizeof(const char*));
  1747. if (temp == 0) {
  1748. last_error = LT_DLSTRERROR(NO_MEMORY);
  1749. return -1;
  1750. }
  1751. /* Build the new vector in the memory addressed by temp. */
  1752. temp[index] = diagnostic;
  1753. while (--index >= 0)
  1754. temp[index] = user_error_strings[index];
  1755. lt_dlfree (user_error_strings);
  1756. user_error_strings = temp;
  1757. return errorcode++;
  1758. }
  1759. int
  1760. lt_dlseterror (index)
  1761. int index;
  1762. {
  1763. if (index >= errorcode || index < 0) {
  1764. last_error = LT_DLSTRERROR(INVALID_ERRORCODE);
  1765. return 1;
  1766. }
  1767. if (index < LTDL_ERROR_MAX)
  1768. last_error = ltdl_error_strings[errorcode];
  1769. else
  1770. last_error = user_error_strings[errorcode - LTDL_ERROR_MAX];
  1771. return 0;
  1772. }