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