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