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