Imported upstream version 0.61.0
[hcoop/debian/courier-authlib.git] / 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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 \f
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 #ifdef RTLD_GLOBAL
1072 # define LT_GLOBAL RTLD_GLOBAL
1073 #else
1074 # ifdef DL_GLOBAL
1075 # define LT_GLOBAL DL_GLOBAL
1076 # endif
1077 #endif /* !RTLD_GLOBAL */
1078 #ifndef LT_GLOBAL
1079 # define LT_GLOBAL 0
1080 #endif /* !LT_GLOBAL */
1081
1082 /* We may have to define LT_LAZY_OR_NOW in the command line if we
1083 find out it does not work in some platform. */
1084 #ifndef LT_LAZY_OR_NOW
1085 # ifdef RTLD_LAZY
1086 # define LT_LAZY_OR_NOW RTLD_LAZY
1087 # else
1088 # ifdef DL_LAZY
1089 # define LT_LAZY_OR_NOW DL_LAZY
1090 # endif
1091 # endif /* !RTLD_LAZY */
1092 #endif
1093 #ifndef LT_LAZY_OR_NOW
1094 # ifdef RTLD_NOW
1095 # define LT_LAZY_OR_NOW RTLD_NOW
1096 # else
1097 # ifdef DL_NOW
1098 # define LT_LAZY_OR_NOW DL_NOW
1099 # endif
1100 # endif /* !RTLD_NOW */
1101 #endif
1102 #ifndef LT_LAZY_OR_NOW
1103 # define LT_LAZY_OR_NOW 0
1104 #endif /* !LT_LAZY_OR_NOW */
1105
1106 #if HAVE_DLERROR
1107 # define DLERROR(arg) dlerror ()
1108 #else
1109 # define DLERROR(arg) LT_DLSTRERROR (arg)
1110 #endif
1111
1112 static lt_module
1113 sys_dl_open (loader_data, filename)
1114 lt_user_data loader_data;
1115 const char *filename;
1116 {
1117 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
1118
1119 if (!module)
1120 {
1121 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
1122 }
1123
1124 return module;
1125 }
1126
1127 static int
1128 sys_dl_close (loader_data, module)
1129 lt_user_data loader_data;
1130 lt_module module;
1131 {
1132 int errors = 0;
1133
1134 if (dlclose (module) != 0)
1135 {
1136 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
1137 ++errors;
1138 }
1139
1140 return errors;
1141 }
1142
1143 static lt_ptr
1144 sys_dl_sym (loader_data, module, symbol)
1145 lt_user_data loader_data;
1146 lt_module module;
1147 const char *symbol;
1148 {
1149 lt_ptr address = dlsym (module, symbol);
1150
1151 if (!address)
1152 {
1153 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1154 }
1155
1156 return address;
1157 }
1158
1159 static struct lt_user_dlloader sys_dl =
1160 {
1161 # ifdef NEED_USCORE
1162 "_",
1163 # else
1164 0,
1165 # endif
1166 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1167
1168
1169 #endif /* HAVE_LIBDL */
1170
1171
1172 \f
1173 /* --- SHL_LOAD() INTERFACE LOADER --- */
1174
1175 #if HAVE_SHL_LOAD
1176
1177 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1178
1179 #ifdef HAVE_DL_H
1180 # include <dl.h>
1181 #endif
1182
1183 /* some flags are missing on some systems, so we provide
1184 * harmless defaults.
1185 *
1186 * Mandatory:
1187 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
1188 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
1189 *
1190 * Optionally:
1191 * BIND_FIRST - Place the library at the head of the symbol search
1192 * order.
1193 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
1194 * unsatisfied symbols as fatal. This flag allows
1195 * binding of unsatisfied code symbols to be deferred
1196 * until use.
1197 * [Perl: For certain libraries, like DCE, deferred
1198 * binding often causes run time problems. Adding
1199 * BIND_NONFATAL to BIND_IMMEDIATE still allows
1200 * unresolved references in situations like this.]
1201 * BIND_NOSTART - Do not call the initializer for the shared library
1202 * when the library is loaded, nor on a future call to
1203 * shl_unload().
1204 * BIND_VERBOSE - Print verbose messages concerning possible
1205 * unsatisfied symbols.
1206 *
1207 * hp9000s700/hp9000s800:
1208 * BIND_RESTRICTED - Restrict symbols visible by the library to those
1209 * present at library load time.
1210 * DYNAMIC_PATH - Allow the loader to dynamically search for the
1211 * library specified by the path argument.
1212 */
1213
1214 #ifndef DYNAMIC_PATH
1215 # define DYNAMIC_PATH 0
1216 #endif
1217 #ifndef BIND_RESTRICTED
1218 # define BIND_RESTRICTED 0
1219 #endif
1220
1221 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1222
1223 static lt_module
1224 sys_shl_open (loader_data, filename)
1225 lt_user_data loader_data;
1226 const char *filename;
1227 {
1228 static shl_t self = (shl_t) 0;
1229 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1230
1231 /* Since searching for a symbol against a NULL module handle will also
1232 look in everything else that was already loaded and exported with
1233 the -E compiler flag, we always cache a handle saved before any
1234 modules are loaded. */
1235 if (!self)
1236 {
1237 lt_ptr address;
1238 shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1239 }
1240
1241 if (!filename)
1242 {
1243 module = self;
1244 }
1245 else
1246 {
1247 module = shl_load (filename, LT_BIND_FLAGS, 0L);
1248
1249 if (!module)
1250 {
1251 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1252 }
1253 }
1254
1255 return module;
1256 }
1257
1258 static int
1259 sys_shl_close (loader_data, module)
1260 lt_user_data loader_data;
1261 lt_module module;
1262 {
1263 int errors = 0;
1264
1265 if (module && (shl_unload ((shl_t) (module)) != 0))
1266 {
1267 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1268 ++errors;
1269 }
1270
1271 return errors;
1272 }
1273
1274 static lt_ptr
1275 sys_shl_sym (loader_data, module, symbol)
1276 lt_user_data loader_data;
1277 lt_module module;
1278 const char *symbol;
1279 {
1280 lt_ptr address = 0;
1281
1282 /* sys_shl_open should never return a NULL module handle */
1283 if (module == (lt_module) 0)
1284 {
1285 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1286 }
1287 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1288 {
1289 if (!address)
1290 {
1291 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1292 }
1293 }
1294
1295 return address;
1296 }
1297
1298 static struct lt_user_dlloader sys_shl = {
1299 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1300 };
1301
1302 #endif /* HAVE_SHL_LOAD */
1303
1304
1305
1306 \f
1307 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1308
1309 #ifdef __WINDOWS__
1310
1311 /* dynamic linking for Win32 */
1312
1313 #include <windows.h>
1314
1315 /* Forward declaration; required to implement handle search below. */
1316 static lt_dlhandle handles;
1317
1318 static lt_module
1319 sys_wll_open (loader_data, filename)
1320 lt_user_data loader_data;
1321 const char *filename;
1322 {
1323 lt_dlhandle cur;
1324 lt_module module = 0;
1325 const char *errormsg = 0;
1326 char *searchname = 0;
1327 char *ext;
1328 char self_name_buf[MAX_PATH];
1329
1330 if (!filename)
1331 {
1332 /* Get the name of main module */
1333 *self_name_buf = 0;
1334 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1335 filename = ext = self_name_buf;
1336 }
1337 else
1338 {
1339 ext = strrchr (filename, '.');
1340 }
1341
1342 if (ext)
1343 {
1344 /* FILENAME already has an extension. */
1345 searchname = lt_estrdup (filename);
1346 }
1347 else
1348 {
1349 /* Append a `.' to stop Windows from adding an
1350 implicit `.dll' extension. */
1351 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1352 if (searchname)
1353 sprintf (searchname, "%s.", filename);
1354 }
1355 if (!searchname)
1356 return 0;
1357
1358 {
1359 /* Silence dialog from LoadLibrary on some failures.
1360 No way to get the error mode, but to set it,
1361 so set it twice to preserve any previous flags. */
1362 UINT errormode = SetErrorMode(SEM_FAILCRITICALERRORS);
1363 SetErrorMode(errormode | SEM_FAILCRITICALERRORS);
1364
1365 #if defined(__CYGWIN__)
1366 {
1367 char wpath[MAX_PATH];
1368 cygwin_conv_to_full_win32_path (searchname, wpath);
1369 module = LoadLibrary (wpath);
1370 }
1371 #else
1372 module = LoadLibrary (searchname);
1373 #endif
1374
1375 /* Restore the error mode. */
1376 SetErrorMode(errormode);
1377 }
1378
1379 LT_DLFREE (searchname);
1380
1381 /* libltdl expects this function to fail if it is unable
1382 to physically load the library. Sadly, LoadLibrary
1383 will search the loaded libraries for a match and return
1384 one of them if the path search load fails.
1385
1386 We check whether LoadLibrary is returning a handle to
1387 an already loaded module, and simulate failure if we
1388 find one. */
1389 LT_DLMUTEX_LOCK ();
1390 cur = handles;
1391 while (cur)
1392 {
1393 if (!cur->module)
1394 {
1395 cur = 0;
1396 break;
1397 }
1398
1399 if (cur->module == module)
1400 {
1401 break;
1402 }
1403
1404 cur = cur->next;
1405 }
1406 LT_DLMUTEX_UNLOCK ();
1407
1408 if (cur || !module)
1409 {
1410 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1411 module = 0;
1412 }
1413
1414 return module;
1415 }
1416
1417 static int
1418 sys_wll_close (loader_data, module)
1419 lt_user_data loader_data;
1420 lt_module module;
1421 {
1422 int errors = 0;
1423
1424 if (FreeLibrary(module) == 0)
1425 {
1426 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1427 ++errors;
1428 }
1429
1430 return errors;
1431 }
1432
1433 static lt_ptr
1434 sys_wll_sym (loader_data, module, symbol)
1435 lt_user_data loader_data;
1436 lt_module module;
1437 const char *symbol;
1438 {
1439 lt_ptr address = GetProcAddress (module, symbol);
1440
1441 if (!address)
1442 {
1443 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1444 }
1445
1446 return address;
1447 }
1448
1449 static struct lt_user_dlloader sys_wll = {
1450 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1451 };
1452
1453 #endif /* __WINDOWS__ */
1454
1455
1456
1457 \f
1458 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1459
1460
1461 #ifdef __BEOS__
1462
1463 /* dynamic linking for BeOS */
1464
1465 #include <kernel/image.h>
1466
1467 static lt_module
1468 sys_bedl_open (loader_data, filename)
1469 lt_user_data loader_data;
1470 const char *filename;
1471 {
1472 image_id image = 0;
1473
1474 if (filename)
1475 {
1476 image = load_add_on (filename);
1477 }
1478 else
1479 {
1480 image_info info;
1481 int32 cookie = 0;
1482 if (get_next_image_info (0, &cookie, &info) == B_OK)
1483 image = load_add_on (info.name);
1484 }
1485
1486 if (image <= 0)
1487 {
1488 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1489 image = 0;
1490 }
1491
1492 return (lt_module) image;
1493 }
1494
1495 static int
1496 sys_bedl_close (loader_data, module)
1497 lt_user_data loader_data;
1498 lt_module module;
1499 {
1500 int errors = 0;
1501
1502 if (unload_add_on ((image_id) module) != B_OK)
1503 {
1504 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1505 ++errors;
1506 }
1507
1508 return errors;
1509 }
1510
1511 static lt_ptr
1512 sys_bedl_sym (loader_data, module, symbol)
1513 lt_user_data loader_data;
1514 lt_module module;
1515 const char *symbol;
1516 {
1517 lt_ptr address = 0;
1518 image_id image = (image_id) module;
1519
1520 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1521 {
1522 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1523 address = 0;
1524 }
1525
1526 return address;
1527 }
1528
1529 static struct lt_user_dlloader sys_bedl = {
1530 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1531 };
1532
1533 #endif /* __BEOS__ */
1534
1535
1536
1537 \f
1538 /* --- DLD_LINK() INTERFACE LOADER --- */
1539
1540
1541 #if HAVE_DLD
1542
1543 /* dynamic linking with dld */
1544
1545 #if HAVE_DLD_H
1546 #include <dld.h>
1547 #endif
1548
1549 static lt_module
1550 sys_dld_open (loader_data, filename)
1551 lt_user_data loader_data;
1552 const char *filename;
1553 {
1554 lt_module module = strdup (filename);
1555
1556 if (dld_link (filename) != 0)
1557 {
1558 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1559 LT_DLFREE (module);
1560 module = 0;
1561 }
1562
1563 return module;
1564 }
1565
1566 static int
1567 sys_dld_close (loader_data, module)
1568 lt_user_data loader_data;
1569 lt_module module;
1570 {
1571 int errors = 0;
1572
1573 if (dld_unlink_by_file ((char*)(module), 1) != 0)
1574 {
1575 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1576 ++errors;
1577 }
1578 else
1579 {
1580 LT_DLFREE (module);
1581 }
1582
1583 return errors;
1584 }
1585
1586 static lt_ptr
1587 sys_dld_sym (loader_data, module, symbol)
1588 lt_user_data loader_data;
1589 lt_module module;
1590 const char *symbol;
1591 {
1592 lt_ptr address = dld_get_func (symbol);
1593
1594 if (!address)
1595 {
1596 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1597 }
1598
1599 return address;
1600 }
1601
1602 static struct lt_user_dlloader sys_dld = {
1603 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1604 };
1605
1606 #endif /* HAVE_DLD */
1607
1608 /* --- DYLD() MACOSX/DARWIN INTERFACE LOADER --- */
1609 #if HAVE_DYLD
1610
1611
1612 #if HAVE_MACH_O_DYLD_H
1613 #if !defined(__APPLE_CC__) && !defined(__MWERKS__) && !defined(__private_extern__)
1614 /* Is this correct? Does it still function properly? */
1615 #define __private_extern__ extern
1616 #endif
1617 # include <mach-o/dyld.h>
1618 #endif
1619 #include <mach-o/getsect.h>
1620
1621 /* We have to put some stuff here that isn't in older dyld.h files */
1622 #ifndef ENUM_DYLD_BOOL
1623 # define ENUM_DYLD_BOOL
1624 # undef FALSE
1625 # undef TRUE
1626 enum DYLD_BOOL {
1627 FALSE,
1628 TRUE
1629 };
1630 #endif
1631 #ifndef LC_REQ_DYLD
1632 # define LC_REQ_DYLD 0x80000000
1633 #endif
1634 #ifndef LC_LOAD_WEAK_DYLIB
1635 # define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
1636 #endif
1637 static const struct mach_header * (*ltdl_NSAddImage)(const char *image_name, unsigned long options) = 0;
1638 static NSSymbol (*ltdl_NSLookupSymbolInImage)(const struct mach_header *image,const char *symbolName, unsigned long options) = 0;
1639 static enum DYLD_BOOL (*ltdl_NSIsSymbolNameDefinedInImage)(const struct mach_header *image, const char *symbolName) = 0;
1640 static enum DYLD_BOOL (*ltdl_NSMakePrivateModulePublic)(NSModule module) = 0;
1641
1642 #ifndef NSADDIMAGE_OPTION_NONE
1643 #define NSADDIMAGE_OPTION_NONE 0x0
1644 #endif
1645 #ifndef NSADDIMAGE_OPTION_RETURN_ON_ERROR
1646 #define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
1647 #endif
1648 #ifndef NSADDIMAGE_OPTION_WITH_SEARCHING
1649 #define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
1650 #endif
1651 #ifndef NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
1652 #define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
1653 #endif
1654 #ifndef NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
1655 #define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
1656 #endif
1657 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
1658 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
1659 #endif
1660 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1661 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
1662 #endif
1663 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
1664 #define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
1665 #endif
1666 #ifndef NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1667 #define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
1668 #endif
1669
1670
1671 static const char *
1672 lt_int_dyld_error(othererror)
1673 char* othererror;
1674 {
1675 /* return the dyld error string, or the passed in error string if none */
1676 NSLinkEditErrors ler;
1677 int lerno;
1678 const char *errstr;
1679 const char *file;
1680 NSLinkEditError(&ler,&lerno,&file,&errstr);
1681 if (!errstr || !strlen(errstr)) errstr = othererror;
1682 return errstr;
1683 }
1684
1685 static const struct mach_header *
1686 lt_int_dyld_get_mach_header_from_nsmodule(module)
1687 NSModule module;
1688 {
1689 /* There should probably be an apple dyld api for this */
1690 int i=_dyld_image_count();
1691 int j;
1692 const char *modname=NSNameOfModule(module);
1693 const struct mach_header *mh=NULL;
1694 if (!modname) return NULL;
1695 for (j = 0; j < i; j++)
1696 {
1697 if (!strcmp(_dyld_get_image_name(j),modname))
1698 {
1699 mh=_dyld_get_image_header(j);
1700 break;
1701 }
1702 }
1703 return mh;
1704 }
1705
1706 static const char* lt_int_dyld_lib_install_name(mh)
1707 const struct mach_header *mh;
1708 {
1709 /* NSAddImage is also used to get the loaded image, but it only works if the lib
1710 is installed, for uninstalled libs we need to check the install_names against
1711 each other. Note that this is still broken if DYLD_IMAGE_SUFFIX is set and a
1712 different lib was loaded as a result
1713 */
1714 int j;
1715 struct load_command *lc;
1716 unsigned long offset = sizeof(struct mach_header);
1717 const char* retStr=NULL;
1718 for (j = 0; j < mh->ncmds; j++)
1719 {
1720 lc = (struct load_command*)(((unsigned long)mh) + offset);
1721 if (LC_ID_DYLIB == lc->cmd)
1722 {
1723 retStr=(char*)(((struct dylib_command*)lc)->dylib.name.offset +
1724 (unsigned long)lc);
1725 }
1726 offset += lc->cmdsize;
1727 }
1728 return retStr;
1729 }
1730
1731 static const struct mach_header *
1732 lt_int_dyld_match_loaded_lib_by_install_name(const char *name)
1733 {
1734 int i=_dyld_image_count();
1735 int j;
1736 const struct mach_header *mh=NULL;
1737 const char *id=NULL;
1738 for (j = 0; j < i; j++)
1739 {
1740 id=lt_int_dyld_lib_install_name(_dyld_get_image_header(j));
1741 if ((id) && (!strcmp(id,name)))
1742 {
1743 mh=_dyld_get_image_header(j);
1744 break;
1745 }
1746 }
1747 return mh;
1748 }
1749
1750 static NSSymbol
1751 lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh)
1752 const char *symbol;
1753 const struct mach_header *mh;
1754 {
1755 /* Safe to assume our mh is good */
1756 int j;
1757 struct load_command *lc;
1758 unsigned long offset = sizeof(struct mach_header);
1759 NSSymbol retSym = 0;
1760 const struct mach_header *mh1;
1761 if ((ltdl_NSLookupSymbolInImage) && NSIsSymbolNameDefined(symbol) )
1762 {
1763 for (j = 0; j < mh->ncmds; j++)
1764 {
1765 lc = (struct load_command*)(((unsigned long)mh) + offset);
1766 if ((LC_LOAD_DYLIB == lc->cmd) || (LC_LOAD_WEAK_DYLIB == lc->cmd))
1767 {
1768 mh1=lt_int_dyld_match_loaded_lib_by_install_name((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1769 (unsigned long)lc));
1770 if (!mh1)
1771 {
1772 /* Maybe NSAddImage can find it */
1773 mh1=ltdl_NSAddImage((char*)(((struct dylib_command*)lc)->dylib.name.offset +
1774 (unsigned long)lc),
1775 NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED +
1776 NSADDIMAGE_OPTION_WITH_SEARCHING +
1777 NSADDIMAGE_OPTION_RETURN_ON_ERROR );
1778 }
1779 if (mh1)
1780 {
1781 retSym = ltdl_NSLookupSymbolInImage(mh1,
1782 symbol,
1783 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1784 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1785 );
1786 if (retSym) break;
1787 }
1788 }
1789 offset += lc->cmdsize;
1790 }
1791 }
1792 return retSym;
1793 }
1794
1795 static int
1796 sys_dyld_init()
1797 {
1798 int retCode = 0;
1799 int err = 0;
1800 if (!_dyld_present()) {
1801 retCode=1;
1802 }
1803 else {
1804 err = _dyld_func_lookup("__dyld_NSAddImage",(unsigned long*)&ltdl_NSAddImage);
1805 err = _dyld_func_lookup("__dyld_NSLookupSymbolInImage",(unsigned long*)&ltdl_NSLookupSymbolInImage);
1806 err = _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage",(unsigned long*)&ltdl_NSIsSymbolNameDefinedInImage);
1807 err = _dyld_func_lookup("__dyld_NSMakePrivateModulePublic",(unsigned long*)&ltdl_NSMakePrivateModulePublic);
1808 }
1809 return retCode;
1810 }
1811
1812 static lt_module
1813 sys_dyld_open (loader_data, filename)
1814 lt_user_data loader_data;
1815 const char *filename;
1816 {
1817 lt_module module = 0;
1818 NSObjectFileImage ofi = 0;
1819 NSObjectFileImageReturnCode ofirc;
1820
1821 if (!filename)
1822 return (lt_module)-1;
1823 ofirc = NSCreateObjectFileImageFromFile(filename, &ofi);
1824 switch (ofirc)
1825 {
1826 case NSObjectFileImageSuccess:
1827 module = NSLinkModule(ofi, filename,
1828 NSLINKMODULE_OPTION_RETURN_ON_ERROR
1829 | NSLINKMODULE_OPTION_PRIVATE
1830 | NSLINKMODULE_OPTION_BINDNOW);
1831 NSDestroyObjectFileImage(ofi);
1832 if (module)
1833 ltdl_NSMakePrivateModulePublic(module);
1834 break;
1835 case NSObjectFileImageInappropriateFile:
1836 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1837 {
1838 module = (lt_module)ltdl_NSAddImage(filename, NSADDIMAGE_OPTION_RETURN_ON_ERROR);
1839 break;
1840 }
1841 default:
1842 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1843 return 0;
1844 }
1845 if (!module) LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_OPEN)));
1846 return module;
1847 }
1848
1849 static int
1850 sys_dyld_close (loader_data, module)
1851 lt_user_data loader_data;
1852 lt_module module;
1853 {
1854 int retCode = 0;
1855 int flags = 0;
1856 if (module == (lt_module)-1) return 0;
1857 #ifdef __BIG_ENDIAN__
1858 if (((struct mach_header *)module)->magic == MH_MAGIC)
1859 #else
1860 if (((struct mach_header *)module)->magic == MH_CIGAM)
1861 #endif
1862 {
1863 LT_DLMUTEX_SETERROR("Can not close a dylib");
1864 retCode = 1;
1865 }
1866 else
1867 {
1868 #if 1
1869 /* Currently, if a module contains c++ static destructors and it is unloaded, we
1870 get a segfault in atexit(), due to compiler and dynamic loader differences of
1871 opinion, this works around that.
1872 */
1873 if ((const struct section *)NULL !=
1874 getsectbynamefromheader(lt_int_dyld_get_mach_header_from_nsmodule(module),
1875 "__DATA","__mod_term_func"))
1876 {
1877 flags += NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED;
1878 }
1879 #endif
1880 #ifdef __ppc__
1881 flags += NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES;
1882 #endif
1883 if (!NSUnLinkModule(module,flags))
1884 {
1885 retCode=1;
1886 LT_DLMUTEX_SETERROR (lt_int_dyld_error(LT_DLSTRERROR(CANNOT_CLOSE)));
1887 }
1888 }
1889
1890 return retCode;
1891 }
1892
1893 static lt_ptr
1894 sys_dyld_sym (loader_data, module, symbol)
1895 lt_user_data loader_data;
1896 lt_module module;
1897 const char *symbol;
1898 {
1899 lt_ptr address = 0;
1900 NSSymbol *nssym = 0;
1901 void *unused;
1902 const struct mach_header *mh=NULL;
1903 char saveError[256] = "Symbol not found";
1904 if (module == (lt_module)-1)
1905 {
1906 _dyld_lookup_and_bind(symbol,(unsigned long*)&address,&unused);
1907 return address;
1908 }
1909 #ifdef __BIG_ENDIAN__
1910 if (((struct mach_header *)module)->magic == MH_MAGIC)
1911 #else
1912 if (((struct mach_header *)module)->magic == MH_CIGAM)
1913 #endif
1914 {
1915 if (ltdl_NSIsSymbolNameDefinedInImage && ltdl_NSLookupSymbolInImage)
1916 {
1917 mh=module;
1918 if (ltdl_NSIsSymbolNameDefinedInImage((struct mach_header*)module,symbol))
1919 {
1920 nssym = ltdl_NSLookupSymbolInImage((struct mach_header*)module,
1921 symbol,
1922 NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
1923 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
1924 );
1925 }
1926 }
1927
1928 }
1929 else {
1930 nssym = NSLookupSymbolInModule(module, symbol);
1931 }
1932 if (!nssym)
1933 {
1934 strncpy(saveError, lt_int_dyld_error(LT_DLSTRERROR(SYMBOL_NOT_FOUND)), 255);
1935 saveError[255] = 0;
1936 if (!mh) mh=lt_int_dyld_get_mach_header_from_nsmodule(module);
1937 nssym = lt_int_dyld_NSlookupSymbolInLinkedLibs(symbol,mh);
1938 }
1939 if (!nssym)
1940 {
1941 LT_DLMUTEX_SETERROR (saveError);
1942 return NULL;
1943 }
1944 return NSAddressOfSymbol(nssym);
1945 }
1946
1947 static struct lt_user_dlloader sys_dyld =
1948 { "_", sys_dyld_open, sys_dyld_close, sys_dyld_sym, 0, 0 };
1949
1950
1951 #endif /* HAVE_DYLD */
1952
1953 \f
1954 /* --- DLPREOPEN() INTERFACE LOADER --- */
1955
1956
1957 /* emulate dynamic linking using preloaded_symbols */
1958
1959 typedef struct lt_dlsymlists_t
1960 {
1961 struct lt_dlsymlists_t *next;
1962 const lt_dlsymlist *syms;
1963 } lt_dlsymlists_t;
1964
1965 static const lt_dlsymlist *default_preloaded_symbols = 0;
1966 static lt_dlsymlists_t *preloaded_symbols = 0;
1967
1968 static int
1969 presym_init (loader_data)
1970 lt_user_data loader_data;
1971 {
1972 int errors = 0;
1973
1974 LT_DLMUTEX_LOCK ();
1975
1976 preloaded_symbols = 0;
1977 if (default_preloaded_symbols)
1978 {
1979 errors = lt_dlpreload (default_preloaded_symbols);
1980 }
1981
1982 LT_DLMUTEX_UNLOCK ();
1983
1984 return errors;
1985 }
1986
1987 static int
1988 presym_free_symlists ()
1989 {
1990 lt_dlsymlists_t *lists;
1991
1992 LT_DLMUTEX_LOCK ();
1993
1994 lists = preloaded_symbols;
1995 while (lists)
1996 {
1997 lt_dlsymlists_t *tmp = lists;
1998
1999 lists = lists->next;
2000 LT_DLFREE (tmp);
2001 }
2002 preloaded_symbols = 0;
2003
2004 LT_DLMUTEX_UNLOCK ();
2005
2006 return 0;
2007 }
2008
2009 static int
2010 presym_exit (loader_data)
2011 lt_user_data loader_data;
2012 {
2013 presym_free_symlists ();
2014 return 0;
2015 }
2016
2017 static int
2018 presym_add_symlist (preloaded)
2019 const lt_dlsymlist *preloaded;
2020 {
2021 lt_dlsymlists_t *tmp;
2022 lt_dlsymlists_t *lists;
2023 int errors = 0;
2024
2025 LT_DLMUTEX_LOCK ();
2026
2027 lists = preloaded_symbols;
2028 while (lists)
2029 {
2030 if (lists->syms == preloaded)
2031 {
2032 goto done;
2033 }
2034 lists = lists->next;
2035 }
2036
2037 tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
2038 if (tmp)
2039 {
2040 memset (tmp, 0, sizeof(lt_dlsymlists_t));
2041 tmp->syms = preloaded;
2042 tmp->next = preloaded_symbols;
2043 preloaded_symbols = tmp;
2044 }
2045 else
2046 {
2047 ++errors;
2048 }
2049
2050 done:
2051 LT_DLMUTEX_UNLOCK ();
2052 return errors;
2053 }
2054
2055 static lt_module
2056 presym_open (loader_data, filename)
2057 lt_user_data loader_data;
2058 const char *filename;
2059 {
2060 lt_dlsymlists_t *lists;
2061 lt_module module = (lt_module) 0;
2062
2063 LT_DLMUTEX_LOCK ();
2064 lists = preloaded_symbols;
2065
2066 if (!lists)
2067 {
2068 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
2069 goto done;
2070 }
2071
2072 /* Can't use NULL as the reflective symbol header, as NULL is
2073 used to mark the end of the entire symbol list. Self-dlpreopened
2074 symbols follow this magic number, chosen to be an unlikely
2075 clash with a real module name. */
2076 if (!filename)
2077 {
2078 filename = "@PROGRAM@";
2079 }
2080
2081 while (lists)
2082 {
2083 const lt_dlsymlist *syms = lists->syms;
2084
2085 while (syms->name)
2086 {
2087 if (!syms->address && strcmp(syms->name, filename) == 0)
2088 {
2089 module = (lt_module) syms;
2090 goto done;
2091 }
2092 ++syms;
2093 }
2094
2095 lists = lists->next;
2096 }
2097
2098 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2099
2100 done:
2101 LT_DLMUTEX_UNLOCK ();
2102 return module;
2103 }
2104
2105 static int
2106 presym_close (loader_data, module)
2107 lt_user_data loader_data;
2108 lt_module module;
2109 {
2110 /* Just to silence gcc -Wall */
2111 module = 0;
2112 return 0;
2113 }
2114
2115 static lt_ptr
2116 presym_sym (loader_data, module, symbol)
2117 lt_user_data loader_data;
2118 lt_module module;
2119 const char *symbol;
2120 {
2121 lt_dlsymlist *syms = (lt_dlsymlist*) module;
2122
2123 ++syms;
2124 while (syms->address)
2125 {
2126 if (strcmp(syms->name, symbol) == 0)
2127 {
2128 return syms->address;
2129 }
2130
2131 ++syms;
2132 }
2133
2134 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
2135
2136 return 0;
2137 }
2138
2139 static struct lt_user_dlloader presym = {
2140 0, presym_open, presym_close, presym_sym, presym_exit, 0
2141 };
2142
2143
2144
2145
2146 \f
2147 /* --- DYNAMIC MODULE LOADING --- */
2148
2149
2150 /* The type of a function used at each iteration of foreach_dirinpath(). */
2151 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
2152 lt_ptr data2));
2153
2154 static int foreach_dirinpath LT_PARAMS((const char *search_path,
2155 const char *base_name,
2156 foreach_callback_func *func,
2157 lt_ptr data1, lt_ptr data2));
2158
2159 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
2160 lt_ptr ignored));
2161 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
2162 lt_ptr ignored));
2163 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
2164 lt_ptr data2));
2165
2166
2167 static int canonicalize_path LT_PARAMS((const char *path,
2168 char **pcanonical));
2169 static int argzize_path LT_PARAMS((const char *path,
2170 char **pargz,
2171 size_t *pargz_len));
2172 static FILE *find_file LT_PARAMS((const char *search_path,
2173 const char *base_name,
2174 char **pdir));
2175 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
2176 const char *base_name,
2177 lt_dlhandle *handle));
2178 static int find_module LT_PARAMS((lt_dlhandle *handle,
2179 const char *dir,
2180 const char *libdir,
2181 const char *dlname,
2182 const char *old_name,
2183 int installed));
2184 static int free_vars LT_PARAMS((char *dlname, char *oldname,
2185 char *libdir, char *deplibs));
2186 static int load_deplibs LT_PARAMS((lt_dlhandle handle,
2187 char *deplibs));
2188 static int trim LT_PARAMS((char **dest,
2189 const char *str));
2190 static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
2191 const char *filename));
2192 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
2193 const char *filename));
2194 static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
2195 static int lt_argz_insert LT_PARAMS((char **pargz,
2196 size_t *pargz_len,
2197 char *before,
2198 const char *entry));
2199 static int lt_argz_insertinorder LT_PARAMS((char **pargz,
2200 size_t *pargz_len,
2201 const char *entry));
2202 static int lt_argz_insertdir LT_PARAMS((char **pargz,
2203 size_t *pargz_len,
2204 const char *dirnam,
2205 struct dirent *dp));
2206 static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
2207 char *before,
2208 const char *dir));
2209 static int list_files_by_dir LT_PARAMS((const char *dirnam,
2210 char **pargz,
2211 size_t *pargz_len));
2212 static int file_not_found LT_PARAMS((void));
2213
2214 static char *user_search_path= 0;
2215 static lt_dlloader *loaders = 0;
2216 static lt_dlhandle handles = 0;
2217 static int initialized = 0;
2218
2219 /* Initialize libltdl. */
2220 int
2221 lt_dlinit ()
2222 {
2223 int errors = 0;
2224
2225 LT_DLMUTEX_LOCK ();
2226
2227 /* Initialize only at first call. */
2228 if (++initialized == 1)
2229 {
2230 handles = 0;
2231 user_search_path = 0; /* empty search path */
2232
2233 #if HAVE_LIBDL
2234 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
2235 #endif
2236 #if HAVE_SHL_LOAD
2237 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
2238 #endif
2239 #ifdef __WINDOWS__
2240 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
2241 #endif
2242 #ifdef __BEOS__
2243 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
2244 #endif
2245 #if HAVE_DLD
2246 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
2247 #endif
2248 #if HAVE_DYLD
2249 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dyld, "dyld");
2250 errors += sys_dyld_init();
2251 #endif
2252 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
2253
2254 if (presym_init (presym.dlloader_data))
2255 {
2256 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
2257 ++errors;
2258 }
2259 else if (errors != 0)
2260 {
2261 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
2262 ++errors;
2263 }
2264 }
2265
2266 LT_DLMUTEX_UNLOCK ();
2267
2268 return errors;
2269 }
2270
2271 int
2272 lt_dlpreload (preloaded)
2273 const lt_dlsymlist *preloaded;
2274 {
2275 int errors = 0;
2276
2277 if (preloaded)
2278 {
2279 errors = presym_add_symlist (preloaded);
2280 }
2281 else
2282 {
2283 presym_free_symlists();
2284
2285 LT_DLMUTEX_LOCK ();
2286 if (default_preloaded_symbols)
2287 {
2288 errors = lt_dlpreload (default_preloaded_symbols);
2289 }
2290 LT_DLMUTEX_UNLOCK ();
2291 }
2292
2293 return errors;
2294 }
2295
2296 int
2297 lt_dlpreload_default (preloaded)
2298 const lt_dlsymlist *preloaded;
2299 {
2300 LT_DLMUTEX_LOCK ();
2301 default_preloaded_symbols = preloaded;
2302 LT_DLMUTEX_UNLOCK ();
2303 return 0;
2304 }
2305
2306 int
2307 lt_dlexit ()
2308 {
2309 /* shut down libltdl */
2310 lt_dlloader *loader;
2311 int errors = 0;
2312
2313 LT_DLMUTEX_LOCK ();
2314 loader = loaders;
2315
2316 if (!initialized)
2317 {
2318 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
2319 ++errors;
2320 goto done;
2321 }
2322
2323 /* shut down only at last call. */
2324 if (--initialized == 0)
2325 {
2326 int level;
2327
2328 while (handles && LT_DLIS_RESIDENT (handles))
2329 {
2330 handles = handles->next;
2331 }
2332
2333 /* close all modules */
2334 for (level = 1; handles; ++level)
2335 {
2336 lt_dlhandle cur = handles;
2337 int saw_nonresident = 0;
2338
2339 while (cur)
2340 {
2341 lt_dlhandle tmp = cur;
2342 cur = cur->next;
2343 if (!LT_DLIS_RESIDENT (tmp))
2344 saw_nonresident = 1;
2345 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
2346 {
2347 if (lt_dlclose (tmp))
2348 {
2349 ++errors;
2350 }
2351 /* Make sure that the handle pointed to by 'cur' still exists.
2352 lt_dlclose recursively closes dependent libraries which removes
2353 them from the linked list. One of these might be the one
2354 pointed to by 'cur'. */
2355 if (cur)
2356 {
2357 for (tmp = handles; tmp; tmp = tmp->next)
2358 if (tmp == cur)
2359 break;
2360 if (! tmp)
2361 cur = handles;
2362 }
2363 }
2364 }
2365 /* done if only resident modules are left */
2366 if (!saw_nonresident)
2367 break;
2368 }
2369
2370 /* close all loaders */
2371 while (loader)
2372 {
2373 lt_dlloader *next = loader->next;
2374 lt_user_data data = loader->dlloader_data;
2375 if (loader->dlloader_exit && loader->dlloader_exit (data))
2376 {
2377 ++errors;
2378 }
2379
2380 LT_DLMEM_REASSIGN (loader, next);
2381 }
2382 loaders = 0;
2383 }
2384
2385 done:
2386 LT_DLMUTEX_UNLOCK ();
2387 return errors;
2388 }
2389
2390 static int
2391 tryall_dlopen (handle, filename)
2392 lt_dlhandle *handle;
2393 const char *filename;
2394 {
2395 lt_dlhandle cur;
2396 lt_dlloader *loader;
2397 const char *saved_error;
2398 int errors = 0;
2399
2400 LT_DLMUTEX_GETERROR (saved_error);
2401 LT_DLMUTEX_LOCK ();
2402
2403 cur = handles;
2404 loader = loaders;
2405
2406 /* check whether the module was already opened */
2407 while (cur)
2408 {
2409 /* try to dlopen the program itself? */
2410 if (!cur->info.filename && !filename)
2411 {
2412 break;
2413 }
2414
2415 if (cur->info.filename && filename
2416 && strcmp (cur->info.filename, filename) == 0)
2417 {
2418 break;
2419 }
2420
2421 cur = cur->next;
2422 }
2423
2424 if (cur)
2425 {
2426 ++cur->info.ref_count;
2427 *handle = cur;
2428 goto done;
2429 }
2430
2431 cur = *handle;
2432 if (filename)
2433 {
2434 /* Comment out the check of file permissions using access.
2435 This call seems to always return -1 with error EACCES.
2436 */
2437 /* We need to catch missing file errors early so that
2438 file_not_found() can detect what happened.
2439 if (access (filename, R_OK) != 0)
2440 {
2441 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2442 ++errors;
2443 goto done;
2444 } */
2445
2446 cur->info.filename = lt_estrdup (filename);
2447 if (!cur->info.filename)
2448 {
2449 ++errors;
2450 goto done;
2451 }
2452 }
2453 else
2454 {
2455 cur->info.filename = 0;
2456 }
2457
2458 while (loader)
2459 {
2460 lt_user_data data = loader->dlloader_data;
2461
2462 cur->module = loader->module_open (data, filename);
2463
2464 if (cur->module != 0)
2465 {
2466 break;
2467 }
2468 loader = loader->next;
2469 }
2470
2471 if (!loader)
2472 {
2473 LT_DLFREE (cur->info.filename);
2474 ++errors;
2475 goto done;
2476 }
2477
2478 cur->loader = loader;
2479 LT_DLMUTEX_SETERROR (saved_error);
2480
2481 done:
2482 LT_DLMUTEX_UNLOCK ();
2483
2484 return errors;
2485 }
2486
2487 static int
2488 tryall_dlopen_module (handle, prefix, dirname, dlname)
2489 lt_dlhandle *handle;
2490 const char *prefix;
2491 const char *dirname;
2492 const char *dlname;
2493 {
2494 int error = 0;
2495 char *filename = 0;
2496 size_t filename_len = 0;
2497 size_t dirname_len = LT_STRLEN (dirname);
2498
2499 assert (handle);
2500 assert (dirname);
2501 assert (dlname);
2502 #ifdef LT_DIRSEP_CHAR
2503 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2504 should make it into this function: */
2505 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
2506 #endif
2507
2508 if (dirname_len > 0)
2509 if (dirname[dirname_len -1] == '/')
2510 --dirname_len;
2511 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
2512
2513 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2514 The PREFIX (if any) is handled below. */
2515 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
2516 if (!filename)
2517 return 1;
2518
2519 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
2520
2521 /* Now that we have combined DIRNAME and MODULENAME, if there is
2522 also a PREFIX to contend with, simply recurse with the arguments
2523 shuffled. Otherwise, attempt to open FILENAME as a module. */
2524 if (prefix)
2525 {
2526 error += tryall_dlopen_module (handle,
2527 (const char *) 0, prefix, filename);
2528 }
2529 else if (tryall_dlopen (handle, filename) != 0)
2530 {
2531 ++error;
2532 }
2533
2534 LT_DLFREE (filename);
2535 return error;
2536 }
2537
2538 static int
2539 find_module (handle, dir, libdir, dlname, old_name, installed)
2540 lt_dlhandle *handle;
2541 const char *dir;
2542 const char *libdir;
2543 const char *dlname;
2544 const char *old_name;
2545 int installed;
2546 {
2547 /* Try to open the old library first; if it was dlpreopened,
2548 we want the preopened version of it, even if a dlopenable
2549 module is available. */
2550 if (old_name && tryall_dlopen (handle, old_name) == 0)
2551 {
2552 return 0;
2553 }
2554
2555 /* Try to open the dynamic library. */
2556 if (dlname)
2557 {
2558 /* try to open the installed module */
2559 if (installed && libdir)
2560 {
2561 if (tryall_dlopen_module (handle,
2562 (const char *) 0, libdir, dlname) == 0)
2563 return 0;
2564 }
2565
2566 /* try to open the not-installed module */
2567 if (!installed)
2568 {
2569 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2570 return 0;
2571 }
2572
2573 /* maybe it was moved to another directory */
2574 {
2575 if (dir && (tryall_dlopen_module (handle,
2576 (const char *) 0, dir, dlname) == 0))
2577 return 0;
2578 }
2579 }
2580
2581 return 1;
2582 }
2583
2584
2585 static int
2586 canonicalize_path (path, pcanonical)
2587 const char *path;
2588 char **pcanonical;
2589 {
2590 char *canonical = 0;
2591
2592 assert (path && *path);
2593 assert (pcanonical);
2594
2595 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2596 if (!canonical)
2597 return 1;
2598
2599 {
2600 size_t dest = 0;
2601 size_t src;
2602 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2603 {
2604 /* Path separators are not copied to the beginning or end of
2605 the destination, or if another separator would follow
2606 immediately. */
2607 if (path[src] == LT_PATHSEP_CHAR)
2608 {
2609 if ((dest == 0)
2610 || (path[1+ src] == LT_PATHSEP_CHAR)
2611 || (path[1+ src] == LT_EOS_CHAR))
2612 continue;
2613 }
2614
2615 /* Anything other than a directory separator is copied verbatim. */
2616 if ((path[src] != '/')
2617 #ifdef LT_DIRSEP_CHAR
2618 && (path[src] != LT_DIRSEP_CHAR)
2619 #endif
2620 )
2621 {
2622 canonical[dest++] = path[src];
2623 }
2624 /* Directory separators are converted and copied only if they are
2625 not at the end of a path -- i.e. before a path separator or
2626 NULL terminator. */
2627 else if ((path[1+ src] != LT_PATHSEP_CHAR)
2628 && (path[1+ src] != LT_EOS_CHAR)
2629 #ifdef LT_DIRSEP_CHAR
2630 && (path[1+ src] != LT_DIRSEP_CHAR)
2631 #endif
2632 && (path[1+ src] != '/'))
2633 {
2634 canonical[dest++] = '/';
2635 }
2636 }
2637
2638 /* Add an end-of-string marker at the end. */
2639 canonical[dest] = LT_EOS_CHAR;
2640 }
2641
2642 /* Assign new value. */
2643 *pcanonical = canonical;
2644
2645 return 0;
2646 }
2647
2648 static int
2649 argzize_path (path, pargz, pargz_len)
2650 const char *path;
2651 char **pargz;
2652 size_t *pargz_len;
2653 {
2654 error_t error;
2655
2656 assert (path);
2657 assert (pargz);
2658 assert (pargz_len);
2659
2660 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2661 {
2662 switch (error)
2663 {
2664 case ENOMEM:
2665 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2666 break;
2667 default:
2668 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2669 break;
2670 }
2671
2672 return 1;
2673 }
2674
2675 return 0;
2676 }
2677
2678 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2679 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2680 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2681 it is appended to each SEARCH_PATH element before FUNC is called. */
2682 static int
2683 foreach_dirinpath (search_path, base_name, func, data1, data2)
2684 const char *search_path;
2685 const char *base_name;
2686 foreach_callback_func *func;
2687 lt_ptr data1;
2688 lt_ptr data2;
2689 {
2690 int result = 0;
2691 int filenamesize = 0;
2692 size_t lenbase = LT_STRLEN (base_name);
2693 size_t argz_len = 0;
2694 char *argz = 0;
2695 char *filename = 0;
2696 char *canonical = 0;
2697
2698 LT_DLMUTEX_LOCK ();
2699
2700 if (!search_path || !*search_path)
2701 {
2702 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2703 goto cleanup;
2704 }
2705
2706 if (canonicalize_path (search_path, &canonical) != 0)
2707 goto cleanup;
2708
2709 if (argzize_path (canonical, &argz, &argz_len) != 0)
2710 goto cleanup;
2711
2712 {
2713 char *dir_name = 0;
2714 while ((dir_name = argz_next (argz, argz_len, dir_name)))
2715 {
2716 size_t lendir = LT_STRLEN (dir_name);
2717
2718 if (lendir +1 +lenbase >= filenamesize)
2719 {
2720 LT_DLFREE (filename);
2721 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2722 filename = LT_EMALLOC (char, filenamesize);
2723 if (!filename)
2724 goto cleanup;
2725 }
2726
2727 assert (filenamesize > lendir);
2728 strcpy (filename, dir_name);
2729
2730 if (base_name && *base_name)
2731 {
2732 if (filename[lendir -1] != '/')
2733 filename[lendir++] = '/';
2734 strcpy (filename +lendir, base_name);
2735 }
2736
2737 if ((result = (*func) (filename, data1, data2)))
2738 {
2739 break;
2740 }
2741 }
2742 }
2743
2744 cleanup:
2745 LT_DLFREE (argz);
2746 LT_DLFREE (canonical);
2747 LT_DLFREE (filename);
2748
2749 LT_DLMUTEX_UNLOCK ();
2750
2751 return result;
2752 }
2753
2754 /* If FILEPATH can be opened, store the name of the directory component
2755 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2756 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2757 static int
2758 find_file_callback (filename, data1, data2)
2759 char *filename;
2760 lt_ptr data1;
2761 lt_ptr data2;
2762 {
2763 char **pdir = (char **) data1;
2764 FILE **pfile = (FILE **) data2;
2765 int is_done = 0;
2766
2767 assert (filename && *filename);
2768 assert (pdir);
2769 assert (pfile);
2770
2771 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2772 {
2773 char *dirend = strrchr (filename, '/');
2774
2775 if (dirend > filename)
2776 *dirend = LT_EOS_CHAR;
2777
2778 LT_DLFREE (*pdir);
2779 *pdir = lt_estrdup (filename);
2780 is_done = (*pdir == 0) ? -1 : 1;
2781 }
2782
2783 return is_done;
2784 }
2785
2786 static FILE *
2787 find_file (search_path, base_name, pdir)
2788 const char *search_path;
2789 const char *base_name;
2790 char **pdir;
2791 {
2792 FILE *file = 0;
2793
2794 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2795
2796 return file;
2797 }
2798
2799 static int
2800 find_handle_callback (filename, data, ignored)
2801 char *filename;
2802 lt_ptr data;
2803 lt_ptr ignored;
2804 {
2805 lt_dlhandle *handle = (lt_dlhandle *) data;
2806 int notfound = access (filename, R_OK);
2807
2808 /* Bail out if file cannot be read... */
2809 if (notfound)
2810 return 0;
2811
2812 /* Try to dlopen the file, but do not continue searching in any
2813 case. */
2814 if (tryall_dlopen (handle, filename) != 0)
2815 *handle = 0;
2816
2817 return 1;
2818 }
2819
2820 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
2821 found but could not be opened, *HANDLE will be set to 0. */
2822 static lt_dlhandle *
2823 find_handle (search_path, base_name, handle)
2824 const char *search_path;
2825 const char *base_name;
2826 lt_dlhandle *handle;
2827 {
2828 if (!search_path)
2829 return 0;
2830
2831 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2832 handle, 0))
2833 return 0;
2834
2835 return handle;
2836 }
2837
2838 static int
2839 load_deplibs (handle, deplibs)
2840 lt_dlhandle handle;
2841 char *deplibs;
2842 {
2843 #if LTDL_DLOPEN_DEPLIBS
2844 char *p, *save_search_path = 0;
2845 int depcount = 0;
2846 int i;
2847 char **names = 0;
2848 #endif
2849 int errors = 0;
2850
2851 handle->depcount = 0;
2852
2853 #if LTDL_DLOPEN_DEPLIBS
2854 if (!deplibs)
2855 {
2856 return errors;
2857 }
2858 ++errors;
2859
2860 LT_DLMUTEX_LOCK ();
2861 if (user_search_path)
2862 {
2863 save_search_path = lt_estrdup (user_search_path);
2864 if (!save_search_path)
2865 goto cleanup;
2866 }
2867
2868 /* extract search paths and count deplibs */
2869 p = deplibs;
2870 while (*p)
2871 {
2872 if (!isspace ((int) *p))
2873 {
2874 char *end = p+1;
2875 while (*end && !isspace((int) *end))
2876 {
2877 ++end;
2878 }
2879
2880 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2881 {
2882 char save = *end;
2883 *end = 0; /* set a temporary string terminator */
2884 if (lt_dladdsearchdir(p+2))
2885 {
2886 goto cleanup;
2887 }
2888 *end = save;
2889 }
2890 else
2891 {
2892 ++depcount;
2893 }
2894
2895 p = end;
2896 }
2897 else
2898 {
2899 ++p;
2900 }
2901 }
2902
2903 if (!depcount)
2904 {
2905 errors = 0;
2906 goto cleanup;
2907 }
2908
2909 names = LT_EMALLOC (char *, depcount * sizeof (char*));
2910 if (!names)
2911 goto cleanup;
2912
2913 /* now only extract the actual deplibs */
2914 depcount = 0;
2915 p = deplibs;
2916 while (*p)
2917 {
2918 if (isspace ((int) *p))
2919 {
2920 ++p;
2921 }
2922 else
2923 {
2924 char *end = p+1;
2925 while (*end && !isspace ((int) *end))
2926 {
2927 ++end;
2928 }
2929
2930 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2931 {
2932 char *name;
2933 char save = *end;
2934 *end = 0; /* set a temporary string terminator */
2935 if (strncmp(p, "-l", 2) == 0)
2936 {
2937 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2938 name = LT_EMALLOC (char, 1+ name_len);
2939 if (name)
2940 sprintf (name, "lib%s", p+2);
2941 }
2942 else
2943 name = lt_estrdup(p);
2944
2945 if (!name)
2946 goto cleanup_names;
2947
2948 names[depcount++] = name;
2949 *end = save;
2950 }
2951 p = end;
2952 }
2953 }
2954
2955 /* load the deplibs (in reverse order)
2956 At this stage, don't worry if the deplibs do not load correctly,
2957 they may already be statically linked into the loading application
2958 for instance. There will be a more enlightening error message
2959 later on if the loaded module cannot resolve all of its symbols. */
2960 if (depcount)
2961 {
2962 int j = 0;
2963
2964 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2965 if (!handle->deplibs)
2966 goto cleanup_names;
2967
2968 for (i = 0; i < depcount; ++i)
2969 {
2970 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2971 if (handle->deplibs[j])
2972 {
2973 ++j;
2974 }
2975 }
2976
2977 handle->depcount = j; /* Number of successfully loaded deplibs */
2978 errors = 0;
2979 }
2980
2981 cleanup_names:
2982 for (i = 0; i < depcount; ++i)
2983 {
2984 LT_DLFREE (names[i]);
2985 }
2986
2987 cleanup:
2988 LT_DLFREE (names);
2989 /* restore the old search path */
2990 if (user_search_path) {
2991 LT_DLFREE (user_search_path);
2992 user_search_path = save_search_path;
2993 }
2994 LT_DLMUTEX_UNLOCK ();
2995
2996 #endif
2997
2998 return errors;
2999 }
3000
3001 static int
3002 unload_deplibs (handle)
3003 lt_dlhandle handle;
3004 {
3005 int i;
3006 int errors = 0;
3007
3008 if (handle->depcount)
3009 {
3010 for (i = 0; i < handle->depcount; ++i)
3011 {
3012 if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
3013 {
3014 errors += lt_dlclose (handle->deplibs[i]);
3015 }
3016 }
3017 LT_DLFREE (handle->deplibs);
3018 }
3019
3020 return errors;
3021 }
3022
3023 static int
3024 trim (dest, str)
3025 char **dest;
3026 const char *str;
3027 {
3028 /* remove the leading and trailing "'" from str
3029 and store the result in dest */
3030 const char *end = strrchr (str, '\'');
3031 size_t len = LT_STRLEN (str);
3032 char *tmp;
3033
3034 LT_DLFREE (*dest);
3035
3036 if (!end)
3037 return 1;
3038
3039 if (len > 3 && str[0] == '\'')
3040 {
3041 tmp = LT_EMALLOC (char, end - str);
3042 if (!tmp)
3043 return 1;
3044
3045 strncpy(tmp, &str[1], (end - str) - 1);
3046 tmp[len-3] = LT_EOS_CHAR;
3047 *dest = tmp;
3048 }
3049 else
3050 {
3051 *dest = 0;
3052 }
3053
3054 return 0;
3055 }
3056
3057 static int
3058 free_vars (dlname, oldname, libdir, deplibs)
3059 char *dlname;
3060 char *oldname;
3061 char *libdir;
3062 char *deplibs;
3063 {
3064 LT_DLFREE (dlname);
3065 LT_DLFREE (oldname);
3066 LT_DLFREE (libdir);
3067 LT_DLFREE (deplibs);
3068
3069 return 0;
3070 }
3071
3072 static int
3073 try_dlopen (phandle, filename)
3074 lt_dlhandle *phandle;
3075 const char *filename;
3076 {
3077 const char * ext = 0;
3078 const char * saved_error = 0;
3079 char * canonical = 0;
3080 char * base_name = 0;
3081 char * dir = 0;
3082 char * name = 0;
3083 int errors = 0;
3084 lt_dlhandle newhandle;
3085
3086 assert (phandle);
3087 assert (*phandle == 0);
3088
3089 LT_DLMUTEX_GETERROR (saved_error);
3090
3091 /* dlopen self? */
3092 if (!filename)
3093 {
3094 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3095 if (*phandle == 0)
3096 return 1;
3097
3098 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3099 newhandle = *phandle;
3100
3101 /* lt_dlclose()ing yourself is very bad! Disallow it. */
3102 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
3103
3104 if (tryall_dlopen (&newhandle, 0) != 0)
3105 {
3106 LT_DLFREE (*phandle);
3107 return 1;
3108 }
3109
3110 goto register_handle;
3111 }
3112
3113 assert (filename && *filename);
3114
3115 /* Doing this immediately allows internal functions to safely
3116 assume only canonicalized paths are passed. */
3117 if (canonicalize_path (filename, &canonical) != 0)
3118 {
3119 ++errors;
3120 goto cleanup;
3121 }
3122
3123 /* If the canonical module name is a path (relative or absolute)
3124 then split it into a directory part and a name part. */
3125 base_name = strrchr (canonical, '/');
3126 if (base_name)
3127 {
3128 size_t dirlen = (1+ base_name) - canonical;
3129
3130 dir = LT_EMALLOC (char, 1+ dirlen);
3131 if (!dir)
3132 {
3133 ++errors;
3134 goto cleanup;
3135 }
3136
3137 strncpy (dir, canonical, dirlen);
3138 dir[dirlen] = LT_EOS_CHAR;
3139
3140 ++base_name;
3141 }
3142 else
3143 base_name = canonical;
3144
3145 assert (base_name && *base_name);
3146
3147 /* Check whether we are opening a libtool module (.la extension). */
3148 ext = strrchr (base_name, '.');
3149 if (ext && strcmp (ext, archive_ext) == 0)
3150 {
3151 /* this seems to be a libtool module */
3152 FILE * file = 0;
3153 char * dlname = 0;
3154 char * old_name = 0;
3155 char * libdir = 0;
3156 char * deplibs = 0;
3157 char * line = 0;
3158 size_t line_len;
3159
3160 /* if we can't find the installed flag, it is probably an
3161 installed libtool archive, produced with an old version
3162 of libtool */
3163 int installed = 1;
3164
3165 /* extract the module name from the file name */
3166 name = LT_EMALLOC (char, ext - base_name + 1);
3167 if (!name)
3168 {
3169 ++errors;
3170 goto cleanup;
3171 }
3172
3173 /* canonicalize the module name */
3174 {
3175 size_t i;
3176 for (i = 0; i < ext - base_name; ++i)
3177 {
3178 if (isalnum ((int)(base_name[i])))
3179 {
3180 name[i] = base_name[i];
3181 }
3182 else
3183 {
3184 name[i] = '_';
3185 }
3186 }
3187 name[ext - base_name] = LT_EOS_CHAR;
3188 }
3189
3190 /* Now try to open the .la file. If there is no directory name
3191 component, try to find it first in user_search_path and then other
3192 prescribed paths. Otherwise (or in any case if the module was not
3193 yet found) try opening just the module name as passed. */
3194 if (!dir)
3195 {
3196 const char *search_path;
3197
3198 LT_DLMUTEX_LOCK ();
3199 search_path = user_search_path;
3200 if (search_path)
3201 file = find_file (user_search_path, base_name, &dir);
3202 LT_DLMUTEX_UNLOCK ();
3203
3204 if (!file)
3205 {
3206 search_path = getenv (LTDL_SEARCHPATH_VAR);
3207 if (search_path)
3208 file = find_file (search_path, base_name, &dir);
3209 }
3210
3211 #ifdef LTDL_SHLIBPATH_VAR
3212 if (!file)
3213 {
3214 search_path = getenv (LTDL_SHLIBPATH_VAR);
3215 if (search_path)
3216 file = find_file (search_path, base_name, &dir);
3217 }
3218 #endif
3219 #ifdef LTDL_SYSSEARCHPATH
3220 if (!file && sys_search_path)
3221 {
3222 file = find_file (sys_search_path, base_name, &dir);
3223 }
3224 #endif
3225 }
3226 if (!file)
3227 {
3228 /* don't open .la files in current directory, root might get tricked to run a binary in a prepared directory */
3229 if(!strncmp((filename + strlen(filename) - 3), LTDL_ARCHIVE_EXT,3) || strstr(filename,"/"))
3230 file = fopen (filename, LT_READTEXT_MODE);
3231 }
3232
3233 /* If we didn't find the file by now, it really isn't there. Set
3234 the status flag, and bail out. */
3235 if (!file)
3236 {
3237 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3238 ++errors;
3239 goto cleanup;
3240 }
3241
3242 line_len = LT_FILENAME_MAX;
3243 line = LT_EMALLOC (char, line_len);
3244 if (!line)
3245 {
3246 fclose (file);
3247 ++errors;
3248 goto cleanup;
3249 }
3250
3251 /* read the .la file */
3252 while (!feof (file))
3253 {
3254 if (!fgets (line, (int) line_len, file))
3255 {
3256 break;
3257 }
3258
3259 /* Handle the case where we occasionally need to read a line
3260 that is longer than the initial buffer size. */
3261 while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
3262 {
3263 line = LT_DLREALLOC (char, line, line_len *2);
3264 if (!fgets (&line[line_len -1], (int) line_len +1, file))
3265 {
3266 break;
3267 }
3268 line_len *= 2;
3269 }
3270
3271 if (line[0] == '\n' || line[0] == '#')
3272 {
3273 continue;
3274 }
3275
3276 #undef STR_DLNAME
3277 #define STR_DLNAME "dlname="
3278 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
3279 {
3280 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
3281 }
3282
3283 #undef STR_OLD_LIBRARY
3284 #define STR_OLD_LIBRARY "old_library="
3285 else if (strncmp (line, STR_OLD_LIBRARY,
3286 sizeof (STR_OLD_LIBRARY) - 1) == 0)
3287 {
3288 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
3289 }
3290 #undef STR_LIBDIR
3291 #define STR_LIBDIR "libdir="
3292 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
3293 {
3294 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
3295 }
3296
3297 #undef STR_DL_DEPLIBS
3298 #define STR_DL_DEPLIBS "dependency_libs="
3299 else if (strncmp (line, STR_DL_DEPLIBS,
3300 sizeof (STR_DL_DEPLIBS) - 1) == 0)
3301 {
3302 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
3303 }
3304 else if (strcmp (line, "installed=yes\n") == 0)
3305 {
3306 installed = 1;
3307 }
3308 else if (strcmp (line, "installed=no\n") == 0)
3309 {
3310 installed = 0;
3311 }
3312
3313 #undef STR_LIBRARY_NAMES
3314 #define STR_LIBRARY_NAMES "library_names="
3315 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
3316 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
3317 {
3318 char *last_libname;
3319 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
3320 if (!errors
3321 && dlname
3322 && (last_libname = strrchr (dlname, ' ')) != 0)
3323 {
3324 last_libname = lt_estrdup (last_libname + 1);
3325 if (!last_libname)
3326 {
3327 ++errors;
3328 goto cleanup;
3329 }
3330 LT_DLMEM_REASSIGN (dlname, last_libname);
3331 }
3332 }
3333
3334 if (errors)
3335 break;
3336 }
3337
3338 fclose (file);
3339 LT_DLFREE (line);
3340
3341 /* allocate the handle */
3342 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3343 if (*phandle == 0)
3344 ++errors;
3345
3346 if (errors)
3347 {
3348 free_vars (dlname, old_name, libdir, deplibs);
3349 LT_DLFREE (*phandle);
3350 goto cleanup;
3351 }
3352
3353 assert (*phandle);
3354
3355 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
3356 if (load_deplibs (*phandle, deplibs) == 0)
3357 {
3358 newhandle = *phandle;
3359 /* find_module may replace newhandle */
3360 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
3361 {
3362 unload_deplibs (*phandle);
3363 ++errors;
3364 }
3365 }
3366 else
3367 {
3368 ++errors;
3369 }
3370
3371 free_vars (dlname, old_name, libdir, deplibs);
3372 if (errors)
3373 {
3374 LT_DLFREE (*phandle);
3375 goto cleanup;
3376 }
3377
3378 if (*phandle != newhandle)
3379 {
3380 unload_deplibs (*phandle);
3381 }
3382 }
3383 else
3384 {
3385 /* not a libtool module */
3386 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
3387 if (*phandle == 0)
3388 {
3389 ++errors;
3390 goto cleanup;
3391 }
3392
3393 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
3394 newhandle = *phandle;
3395
3396 /* If the module has no directory name component, try to find it
3397 first in user_search_path and then other prescribed paths.
3398 Otherwise (or in any case if the module was not yet found) try
3399 opening just the module name as passed. */
3400 if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
3401 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
3402 &newhandle)
3403 #ifdef LTDL_SHLIBPATH_VAR
3404 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
3405 &newhandle)
3406 #endif
3407 #ifdef LTDL_SYSSEARCHPATH
3408 && !find_handle (sys_search_path, base_name, &newhandle)
3409 #endif
3410 )))
3411 {
3412 if (tryall_dlopen (&newhandle, filename) != 0)
3413 {
3414 newhandle = NULL;
3415 }
3416 }
3417
3418 if (!newhandle)
3419 {
3420 LT_DLFREE (*phandle);
3421 ++errors;
3422 goto cleanup;
3423 }
3424 }
3425
3426 register_handle:
3427 LT_DLMEM_REASSIGN (*phandle, newhandle);
3428
3429 if ((*phandle)->info.ref_count == 0)
3430 {
3431 (*phandle)->info.ref_count = 1;
3432 LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
3433
3434 LT_DLMUTEX_LOCK ();
3435 (*phandle)->next = handles;
3436 handles = *phandle;
3437 LT_DLMUTEX_UNLOCK ();
3438 }
3439
3440 LT_DLMUTEX_SETERROR (saved_error);
3441
3442 cleanup:
3443 LT_DLFREE (dir);
3444 LT_DLFREE (name);
3445 LT_DLFREE (canonical);
3446
3447 return errors;
3448 }
3449
3450 lt_dlhandle
3451 lt_dlopen (filename)
3452 const char *filename;
3453 {
3454 lt_dlhandle handle = 0;
3455
3456 /* Just incase we missed a code path in try_dlopen() that reports
3457 an error, but forgets to reset handle... */
3458 if (try_dlopen (&handle, filename) != 0)
3459 return 0;
3460
3461 return handle;
3462 }
3463
3464 /* If the last error messge store was `FILE_NOT_FOUND', then return
3465 non-zero. */
3466 static int
3467 file_not_found ()
3468 {
3469 const char *error = 0;
3470
3471 LT_DLMUTEX_GETERROR (error);
3472 if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
3473 return 1;
3474
3475 return 0;
3476 }
3477
3478 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3479 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
3480 and if a file is still not found try again with SHLIB_EXT appended
3481 instead. */
3482 lt_dlhandle
3483 lt_dlopenext (filename)
3484 const char *filename;
3485 {
3486 lt_dlhandle handle = 0;
3487 char * tmp = 0;
3488 char * ext = 0;
3489 size_t len;
3490 int errors = 0;
3491
3492 if (!filename)
3493 {
3494 return lt_dlopen (filename);
3495 }
3496
3497 assert (filename);
3498
3499 len = LT_STRLEN (filename);
3500 ext = strrchr (filename, '.');
3501
3502 /* If FILENAME already bears a suitable extension, there is no need
3503 to try appending additional extensions. */
3504 if (ext && ((strcmp (ext, archive_ext) == 0)
3505 #ifdef LTDL_SHLIB_EXT
3506 || (strcmp (ext, shlib_ext) == 0)
3507 #endif
3508 ))
3509 {
3510 return lt_dlopen (filename);
3511 }
3512
3513 /* First try appending ARCHIVE_EXT. */
3514 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
3515 if (!tmp)
3516 return 0;
3517
3518 strcpy (tmp, filename);
3519 strcat (tmp, archive_ext);
3520 errors = try_dlopen (&handle, tmp);
3521
3522 /* If we found FILENAME, stop searching -- whether we were able to
3523 load the file as a module or not. If the file exists but loading
3524 failed, it is better to return an error message here than to
3525 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3526 in the module search path. */
3527 if (handle || ((errors > 0) && !file_not_found ()))
3528 {
3529 LT_DLFREE (tmp);
3530 return handle;
3531 }
3532
3533 #ifdef LTDL_SHLIB_EXT
3534 /* Try appending SHLIB_EXT. */
3535 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
3536 {
3537 LT_DLFREE (tmp);
3538 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3539 if (!tmp)
3540 return 0;
3541
3542 strcpy (tmp, filename);
3543 }
3544 else
3545 {
3546 tmp[len] = LT_EOS_CHAR;
3547 }
3548
3549 strcat(tmp, shlib_ext);
3550 errors = try_dlopen (&handle, tmp);
3551
3552 /* As before, if the file was found but loading failed, return now
3553 with the current error message. */
3554 if (handle || ((errors > 0) && !file_not_found ()))
3555 {
3556 LT_DLFREE (tmp);
3557 return handle;
3558 }
3559 #endif
3560
3561 /* Still here? Then we really did fail to locate any of the file
3562 names we tried. */
3563 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3564 LT_DLFREE (tmp);
3565 return 0;
3566 }
3567
3568
3569 static int
3570 lt_argz_insert (pargz, pargz_len, before, entry)
3571 char **pargz;
3572 size_t *pargz_len;
3573 char *before;
3574 const char *entry;
3575 {
3576 error_t error;
3577
3578 /* Prior to Sep 8, 2005, newlib had a bug where argz_insert(pargz,
3579 pargz_len, NULL, entry) failed with EINVAL. */
3580 if (before)
3581 error = argz_insert (pargz, pargz_len, before, entry);
3582 else
3583 error = argz_append (pargz, pargz_len, entry, 1 + LT_STRLEN (entry));
3584
3585 if (error)
3586 {
3587 switch (error)
3588 {
3589 case ENOMEM:
3590 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3591 break;
3592 default:
3593 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3594 break;
3595 }
3596 return 1;
3597 }
3598
3599 return 0;
3600 }
3601
3602 static int
3603 lt_argz_insertinorder (pargz, pargz_len, entry)
3604 char **pargz;
3605 size_t *pargz_len;
3606 const char *entry;
3607 {
3608 char *before = 0;
3609
3610 assert (pargz);
3611 assert (pargz_len);
3612 assert (entry && *entry);
3613
3614 if (*pargz)
3615 while ((before = argz_next (*pargz, *pargz_len, before)))
3616 {
3617 int cmp = strcmp (entry, before);
3618
3619 if (cmp < 0) break;
3620 if (cmp == 0) return 0; /* No duplicates! */
3621 }
3622
3623 return lt_argz_insert (pargz, pargz_len, before, entry);
3624 }
3625
3626 static int
3627 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3628 char **pargz;
3629 size_t *pargz_len;
3630 const char *dirnam;
3631 struct dirent *dp;
3632 {
3633 char *buf = 0;
3634 size_t buf_len = 0;
3635 char *end = 0;
3636 size_t end_offset = 0;
3637 size_t dir_len = 0;
3638 int errors = 0;
3639
3640 assert (pargz);
3641 assert (pargz_len);
3642 assert (dp);
3643
3644 dir_len = LT_STRLEN (dirnam);
3645 end = dp->d_name + LT_D_NAMLEN(dp);
3646
3647 /* Ignore version numbers. */
3648 {
3649 char *p;
3650 for (p = end; p -1 > dp->d_name; --p)
3651 if (strchr (".0123456789", p[-1]) == 0)
3652 break;
3653
3654 if (*p == '.')
3655 end = p;
3656 }
3657
3658 /* Ignore filename extension. */
3659 {
3660 char *p;
3661 for (p = end -1; p > dp->d_name; --p)
3662 if (*p == '.')
3663 {
3664 end = p;
3665 break;
3666 }
3667 }
3668
3669 /* Prepend the directory name. */
3670 end_offset = end - dp->d_name;
3671 buf_len = dir_len + 1+ end_offset;
3672 buf = LT_EMALLOC (char, 1+ buf_len);
3673 if (!buf)
3674 return ++errors;
3675
3676 assert (buf);
3677
3678 strcpy (buf, dirnam);
3679 strcat (buf, "/");
3680 strncat (buf, dp->d_name, end_offset);
3681 buf[buf_len] = LT_EOS_CHAR;
3682
3683 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3684 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3685 ++errors;
3686
3687 LT_DLFREE (buf);
3688
3689 return errors;
3690 }
3691
3692 static int
3693 list_files_by_dir (dirnam, pargz, pargz_len)
3694 const char *dirnam;
3695 char **pargz;
3696 size_t *pargz_len;
3697 {
3698 DIR *dirp = 0;
3699 int errors = 0;
3700
3701 assert (dirnam && *dirnam);
3702 assert (pargz);
3703 assert (pargz_len);
3704 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3705
3706 dirp = opendir (dirnam);
3707 if (dirp)
3708 {
3709 struct dirent *dp = 0;
3710
3711 while ((dp = readdir (dirp)))
3712 if (dp->d_name[0] != '.')
3713 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3714 {
3715 ++errors;
3716 break;
3717 }
3718
3719 closedir (dirp);
3720 }
3721 else
3722 ++errors;
3723
3724 return errors;
3725 }
3726
3727
3728 /* If there are any files in DIRNAME, call the function passed in
3729 DATA1 (with the name of each file and DATA2 as arguments). */
3730 static int
3731 foreachfile_callback (dirname, data1, data2)
3732 char *dirname;
3733 lt_ptr data1;
3734 lt_ptr data2;
3735 {
3736 int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3737 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3738
3739 int is_done = 0;
3740 char *argz = 0;
3741 size_t argz_len = 0;
3742
3743 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3744 goto cleanup;
3745 if (!argz)
3746 goto cleanup;
3747
3748 {
3749 char *filename = 0;
3750 while ((filename = argz_next (argz, argz_len, filename)))
3751 if ((is_done = (*func) (filename, data2)))
3752 break;
3753 }
3754
3755 cleanup:
3756 LT_DLFREE (argz);
3757
3758 return is_done;
3759 }
3760
3761
3762 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3763 with DATA. The filenames passed to FUNC would be suitable for
3764 passing to lt_dlopenext. The extensions are stripped so that
3765 individual modules do not generate several entries (e.g. libfoo.la,
3766 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3767 then the same directories that lt_dlopen would search are examined. */
3768 int
3769 lt_dlforeachfile (search_path, func, data)
3770 const char *search_path;
3771 int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3772 lt_ptr data;
3773 {
3774 int is_done = 0;
3775
3776 if (search_path)
3777 {
3778 /* If a specific path was passed, search only the directories
3779 listed in it. */
3780 is_done = foreach_dirinpath (search_path, 0,
3781 foreachfile_callback, func, data);
3782 }
3783 else
3784 {
3785 /* Otherwise search the default paths. */
3786 is_done = foreach_dirinpath (user_search_path, 0,
3787 foreachfile_callback, func, data);
3788 if (!is_done)
3789 {
3790 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3791 foreachfile_callback, func, data);
3792 }
3793
3794 #ifdef LTDL_SHLIBPATH_VAR
3795 if (!is_done)
3796 {
3797 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3798 foreachfile_callback, func, data);
3799 }
3800 #endif
3801 #ifdef LTDL_SYSSEARCHPATH
3802 if (!is_done)
3803 {
3804 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3805 foreachfile_callback, func, data);
3806 }
3807 #endif
3808 }
3809
3810 return is_done;
3811 }
3812
3813 int
3814 lt_dlclose (handle)
3815 lt_dlhandle handle;
3816 {
3817 lt_dlhandle cur, last;
3818 int errors = 0;
3819
3820 LT_DLMUTEX_LOCK ();
3821
3822 /* check whether the handle is valid */
3823 last = cur = handles;
3824 while (cur && handle != cur)
3825 {
3826 last = cur;
3827 cur = cur->next;
3828 }
3829
3830 if (!cur)
3831 {
3832 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3833 ++errors;
3834 goto done;
3835 }
3836
3837 handle->info.ref_count--;
3838
3839 /* Note that even with resident modules, we must track the ref_count
3840 correctly incase the user decides to reset the residency flag
3841 later (even though the API makes no provision for that at the
3842 moment). */
3843 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3844 {
3845 lt_user_data data = handle->loader->dlloader_data;
3846
3847 if (handle != handles)
3848 {
3849 last->next = handle->next;
3850 }
3851 else
3852 {
3853 handles = handle->next;
3854 }
3855
3856 errors += handle->loader->module_close (data, handle->module);
3857 errors += unload_deplibs(handle);
3858
3859 /* It is up to the callers to free the data itself. */
3860 LT_DLFREE (handle->caller_data);
3861
3862 LT_DLFREE (handle->info.filename);
3863 LT_DLFREE (handle->info.name);
3864 LT_DLFREE (handle);
3865
3866 goto done;
3867 }
3868
3869 if (LT_DLIS_RESIDENT (handle))
3870 {
3871 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3872 ++errors;
3873 }
3874
3875 done:
3876 LT_DLMUTEX_UNLOCK ();
3877
3878 return errors;
3879 }
3880
3881 lt_ptr
3882 lt_dlsym (handle, symbol)
3883 lt_dlhandle handle;
3884 const char *symbol;
3885 {
3886 size_t lensym;
3887 char lsym[LT_SYMBOL_LENGTH];
3888 char *sym;
3889 lt_ptr address;
3890 lt_user_data data;
3891
3892 if (!handle)
3893 {
3894 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3895 return 0;
3896 }
3897
3898 if (!symbol)
3899 {
3900 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3901 return 0;
3902 }
3903
3904 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3905 + LT_STRLEN (handle->info.name);
3906
3907 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3908 {
3909 sym = lsym;
3910 }
3911 else
3912 {
3913 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3914 if (!sym)
3915 {
3916 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3917 return 0;
3918 }
3919 }
3920
3921 data = handle->loader->dlloader_data;
3922 if (handle->info.name)
3923 {
3924 const char *saved_error;
3925
3926 LT_DLMUTEX_GETERROR (saved_error);
3927
3928 /* this is a libtool module */
3929 if (handle->loader->sym_prefix)
3930 {
3931 strcpy(sym, handle->loader->sym_prefix);
3932 strcat(sym, handle->info.name);
3933 }
3934 else
3935 {
3936 strcpy(sym, handle->info.name);
3937 }
3938
3939 strcat(sym, "_LTX_");
3940 strcat(sym, symbol);
3941
3942 /* try "modulename_LTX_symbol" */
3943 address = handle->loader->find_sym (data, handle->module, sym);
3944 if (address)
3945 {
3946 if (sym != lsym)
3947 {
3948 LT_DLFREE (sym);
3949 }
3950 return address;
3951 }
3952 LT_DLMUTEX_SETERROR (saved_error);
3953 }
3954
3955 /* otherwise try "symbol" */
3956 if (handle->loader->sym_prefix)
3957 {
3958 strcpy(sym, handle->loader->sym_prefix);
3959 strcat(sym, symbol);
3960 }
3961 else
3962 {
3963 strcpy(sym, symbol);
3964 }
3965
3966 address = handle->loader->find_sym (data, handle->module, sym);
3967 if (sym != lsym)
3968 {
3969 LT_DLFREE (sym);
3970 }
3971
3972 return address;
3973 }
3974
3975 const char *
3976 lt_dlerror ()
3977 {
3978 const char *error;
3979
3980 LT_DLMUTEX_GETERROR (error);
3981 LT_DLMUTEX_SETERROR (0);
3982
3983 return error ? error : NULL;
3984 }
3985
3986 static int
3987 lt_dlpath_insertdir (ppath, before, dir)
3988 char **ppath;
3989 char *before;
3990 const char *dir;
3991 {
3992 int errors = 0;
3993 char *canonical = 0;
3994 char *argz = 0;
3995 size_t argz_len = 0;
3996
3997 assert (ppath);
3998 assert (dir && *dir);
3999
4000 if (canonicalize_path (dir, &canonical) != 0)
4001 {
4002 ++errors;
4003 goto cleanup;
4004 }
4005
4006 assert (canonical && *canonical);
4007
4008 /* If *PPATH is empty, set it to DIR. */
4009 if (*ppath == 0)
4010 {
4011 assert (!before); /* BEFORE cannot be set without PPATH. */
4012 assert (dir); /* Without DIR, don't call this function! */
4013
4014 *ppath = lt_estrdup (dir);
4015 if (*ppath == 0)
4016 ++errors;
4017
4018 return errors;
4019 }
4020
4021 assert (ppath && *ppath);
4022
4023 if (argzize_path (*ppath, &argz, &argz_len) != 0)
4024 {
4025 ++errors;
4026 goto cleanup;
4027 }
4028
4029 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
4030 if *PPATH is already canonicalized, and hence does not change length
4031 with respect to ARGZ. We canonicalize each entry as it is added to
4032 the search path, and don't call this function with (uncanonicalized)
4033 user paths, so this is a fair assumption. */
4034 if (before)
4035 {
4036 assert (*ppath <= before);
4037 assert (before - *ppath <= strlen (*ppath));
4038
4039 before = before - *ppath + argz;
4040 }
4041
4042 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
4043 {
4044 ++errors;
4045 goto cleanup;
4046 }
4047
4048 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
4049 LT_DLMEM_REASSIGN (*ppath, argz);
4050
4051 cleanup:
4052 LT_DLFREE (canonical);
4053 LT_DLFREE (argz);
4054
4055 return errors;
4056 }
4057
4058 int
4059 lt_dladdsearchdir (search_dir)
4060 const char *search_dir;
4061 {
4062 int errors = 0;
4063
4064 if (search_dir && *search_dir)
4065 {
4066 LT_DLMUTEX_LOCK ();
4067 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
4068 ++errors;
4069 LT_DLMUTEX_UNLOCK ();
4070 }
4071
4072 return errors;
4073 }
4074
4075 int
4076 lt_dlinsertsearchdir (before, search_dir)
4077 const char *before;
4078 const char *search_dir;
4079 {
4080 int errors = 0;
4081
4082 if (before)
4083 {
4084 LT_DLMUTEX_LOCK ();
4085 if ((before < user_search_path)
4086 || (before >= user_search_path + LT_STRLEN (user_search_path)))
4087 {
4088 LT_DLMUTEX_UNLOCK ();
4089 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
4090 return 1;
4091 }
4092 LT_DLMUTEX_UNLOCK ();
4093 }
4094
4095 if (search_dir && *search_dir)
4096 {
4097 LT_DLMUTEX_LOCK ();
4098 if (lt_dlpath_insertdir (&user_search_path,
4099 (char *) before, search_dir) != 0)
4100 {
4101 ++errors;
4102 }
4103 LT_DLMUTEX_UNLOCK ();
4104 }
4105
4106 return errors;
4107 }
4108
4109 int
4110 lt_dlsetsearchpath (search_path)
4111 const char *search_path;
4112 {
4113 int errors = 0;
4114
4115 LT_DLMUTEX_LOCK ();
4116 LT_DLFREE (user_search_path);
4117 LT_DLMUTEX_UNLOCK ();
4118
4119 if (!search_path || !LT_STRLEN (search_path))
4120 {
4121 return errors;
4122 }
4123
4124 LT_DLMUTEX_LOCK ();
4125 if (canonicalize_path (search_path, &user_search_path) != 0)
4126 ++errors;
4127 LT_DLMUTEX_UNLOCK ();
4128
4129 return errors;
4130 }
4131
4132 const char *
4133 lt_dlgetsearchpath ()
4134 {
4135 const char *saved_path;
4136
4137 LT_DLMUTEX_LOCK ();
4138 saved_path = user_search_path;
4139 LT_DLMUTEX_UNLOCK ();
4140
4141 return saved_path;
4142 }
4143
4144 int
4145 lt_dlmakeresident (handle)
4146 lt_dlhandle handle;
4147 {
4148 int errors = 0;
4149
4150 if (!handle)
4151 {
4152 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4153 ++errors;
4154 }
4155 else
4156 {
4157 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
4158 }
4159
4160 return errors;
4161 }
4162
4163 int
4164 lt_dlisresident (handle)
4165 lt_dlhandle handle;
4166 {
4167 if (!handle)
4168 {
4169 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4170 return -1;
4171 }
4172
4173 return LT_DLIS_RESIDENT (handle);
4174 }
4175
4176
4177
4178 \f
4179 /* --- MODULE INFORMATION --- */
4180
4181 const lt_dlinfo *
4182 lt_dlgetinfo (handle)
4183 lt_dlhandle handle;
4184 {
4185 if (!handle)
4186 {
4187 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
4188 return 0;
4189 }
4190
4191 return &(handle->info);
4192 }
4193
4194 lt_dlhandle
4195 lt_dlhandle_next (place)
4196 lt_dlhandle place;
4197 {
4198 return place ? place->next : handles;
4199 }
4200
4201 int
4202 lt_dlforeach (func, data)
4203 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
4204 lt_ptr data;
4205 {
4206 int errors = 0;
4207 lt_dlhandle cur;
4208
4209 LT_DLMUTEX_LOCK ();
4210
4211 cur = handles;
4212 while (cur)
4213 {
4214 lt_dlhandle tmp = cur;
4215
4216 cur = cur->next;
4217 if ((*func) (tmp, data))
4218 {
4219 ++errors;
4220 break;
4221 }
4222 }
4223
4224 LT_DLMUTEX_UNLOCK ();
4225
4226 return errors;
4227 }
4228
4229 lt_dlcaller_id
4230 lt_dlcaller_register ()
4231 {
4232 static lt_dlcaller_id last_caller_id = 0;
4233 int result;
4234
4235 LT_DLMUTEX_LOCK ();
4236 result = ++last_caller_id;
4237 LT_DLMUTEX_UNLOCK ();
4238
4239 return result;
4240 }
4241
4242 lt_ptr
4243 lt_dlcaller_set_data (key, handle, data)
4244 lt_dlcaller_id key;
4245 lt_dlhandle handle;
4246 lt_ptr data;
4247 {
4248 int n_elements = 0;
4249 lt_ptr stale = (lt_ptr) 0;
4250 int i;
4251
4252 /* This needs to be locked so that the caller data can be updated
4253 simultaneously by different threads. */
4254 LT_DLMUTEX_LOCK ();
4255
4256 if (handle->caller_data)
4257 while (handle->caller_data[n_elements].key)
4258 ++n_elements;
4259
4260 for (i = 0; i < n_elements; ++i)
4261 {
4262 if (handle->caller_data[i].key == key)
4263 {
4264 stale = handle->caller_data[i].data;
4265 break;
4266 }
4267 }
4268
4269 /* Ensure that there is enough room in this handle's caller_data
4270 array to accept a new element (and an empty end marker). */
4271 if (i == n_elements)
4272 {
4273 lt_caller_data *temp
4274 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
4275
4276 if (!temp)
4277 {
4278 stale = 0;
4279 goto done;
4280 }
4281
4282 handle->caller_data = temp;
4283
4284 /* We only need this if we needed to allocate a new caller_data. */
4285 handle->caller_data[i].key = key;
4286 handle->caller_data[1+ i].key = 0;
4287 }
4288
4289 handle->caller_data[i].data = data;
4290
4291 done:
4292 LT_DLMUTEX_UNLOCK ();
4293
4294 return stale;
4295 }
4296
4297 lt_ptr
4298 lt_dlcaller_get_data (key, handle)
4299 lt_dlcaller_id key;
4300 lt_dlhandle handle;
4301 {
4302 lt_ptr result = (lt_ptr) 0;
4303
4304 /* This needs to be locked so that the caller data isn't updated by
4305 another thread part way through this function. */
4306 LT_DLMUTEX_LOCK ();
4307
4308 /* Locate the index of the element with a matching KEY. */
4309 {
4310 int i;
4311 for (i = 0; handle->caller_data[i].key; ++i)
4312 {
4313 if (handle->caller_data[i].key == key)
4314 {
4315 result = handle->caller_data[i].data;
4316 break;
4317 }
4318 }
4319 }
4320
4321 LT_DLMUTEX_UNLOCK ();
4322
4323 return result;
4324 }
4325
4326
4327 \f
4328 /* --- USER MODULE LOADER API --- */
4329
4330
4331 int
4332 lt_dlloader_add (place, dlloader, loader_name)
4333 lt_dlloader *place;
4334 const struct lt_user_dlloader *dlloader;
4335 const char *loader_name;
4336 {
4337 int errors = 0;
4338 lt_dlloader *node = 0, *ptr = 0;
4339
4340 if ((dlloader == 0) /* diagnose null parameters */
4341 || (dlloader->module_open == 0)
4342 || (dlloader->module_close == 0)
4343 || (dlloader->find_sym == 0))
4344 {
4345 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4346 return 1;
4347 }
4348
4349 /* Create a new dlloader node with copies of the user callbacks. */
4350 node = LT_EMALLOC (lt_dlloader, 1);
4351 if (!node)
4352 return 1;
4353
4354 node->next = 0;
4355 node->loader_name = loader_name;
4356 node->sym_prefix = dlloader->sym_prefix;
4357 node->dlloader_exit = dlloader->dlloader_exit;
4358 node->module_open = dlloader->module_open;
4359 node->module_close = dlloader->module_close;
4360 node->find_sym = dlloader->find_sym;
4361 node->dlloader_data = dlloader->dlloader_data;
4362
4363 LT_DLMUTEX_LOCK ();
4364 if (!loaders)
4365 {
4366 /* If there are no loaders, NODE becomes the list! */
4367 loaders = node;
4368 }
4369 else if (!place)
4370 {
4371 /* If PLACE is not set, add NODE to the end of the
4372 LOADERS list. */
4373 for (ptr = loaders; ptr->next; ptr = ptr->next)
4374 {
4375 /*NOWORK*/;
4376 }
4377
4378 ptr->next = node;
4379 }
4380 else if (loaders == place)
4381 {
4382 /* If PLACE is the first loader, NODE goes first. */
4383 node->next = place;
4384 loaders = node;
4385 }
4386 else
4387 {
4388 /* Find the node immediately preceding PLACE. */
4389 for (ptr = loaders; ptr->next != place; ptr = ptr->next)
4390 {
4391 /*NOWORK*/;
4392 }
4393
4394 if (ptr->next != place)
4395 {
4396 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4397 ++errors;
4398 }
4399 else
4400 {
4401 /* Insert NODE between PTR and PLACE. */
4402 node->next = place;
4403 ptr->next = node;
4404 }
4405 }
4406
4407 LT_DLMUTEX_UNLOCK ();
4408
4409 return errors;
4410 }
4411
4412 int
4413 lt_dlloader_remove (loader_name)
4414 const char *loader_name;
4415 {
4416 lt_dlloader *place = lt_dlloader_find (loader_name);
4417 lt_dlhandle handle;
4418 int errors = 0;
4419
4420 if (!place)
4421 {
4422 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4423 return 1;
4424 }
4425
4426 LT_DLMUTEX_LOCK ();
4427
4428 /* Fail if there are any open modules which use this loader. */
4429 for (handle = handles; handle; handle = handle->next)
4430 {
4431 if (handle->loader == place)
4432 {
4433 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
4434 ++errors;
4435 goto done;
4436 }
4437 }
4438
4439 if (place == loaders)
4440 {
4441 /* PLACE is the first loader in the list. */
4442 loaders = loaders->next;
4443 }
4444 else
4445 {
4446 /* Find the loader before the one being removed. */
4447 lt_dlloader *prev;
4448 for (prev = loaders; prev->next; prev = prev->next)
4449 {
4450 if (!strcmp (prev->next->loader_name, loader_name))
4451 {
4452 break;
4453 }
4454 }
4455
4456 place = prev->next;
4457 prev->next = prev->next->next;
4458 }
4459
4460 if (place->dlloader_exit)
4461 {
4462 errors = place->dlloader_exit (place->dlloader_data);
4463 }
4464
4465 LT_DLFREE (place);
4466
4467 done:
4468 LT_DLMUTEX_UNLOCK ();
4469
4470 return errors;
4471 }
4472
4473 lt_dlloader *
4474 lt_dlloader_next (place)
4475 lt_dlloader *place;
4476 {
4477 lt_dlloader *next;
4478
4479 LT_DLMUTEX_LOCK ();
4480 next = place ? place->next : loaders;
4481 LT_DLMUTEX_UNLOCK ();
4482
4483 return next;
4484 }
4485
4486 const char *
4487 lt_dlloader_name (place)
4488 lt_dlloader *place;
4489 {
4490 const char *name = 0;
4491
4492 if (place)
4493 {
4494 LT_DLMUTEX_LOCK ();
4495 name = place ? place->loader_name : 0;
4496 LT_DLMUTEX_UNLOCK ();
4497 }
4498 else
4499 {
4500 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4501 }
4502
4503 return name;
4504 }
4505
4506 lt_user_data *
4507 lt_dlloader_data (place)
4508 lt_dlloader *place;
4509 {
4510 lt_user_data *data = 0;
4511
4512 if (place)
4513 {
4514 LT_DLMUTEX_LOCK ();
4515 data = place ? &(place->dlloader_data) : 0;
4516 LT_DLMUTEX_UNLOCK ();
4517 }
4518 else
4519 {
4520 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4521 }
4522
4523 return data;
4524 }
4525
4526 lt_dlloader *
4527 lt_dlloader_find (loader_name)
4528 const char *loader_name;
4529 {
4530 lt_dlloader *place = 0;
4531
4532 LT_DLMUTEX_LOCK ();
4533 for (place = loaders; place; place = place->next)
4534 {
4535 if (strcmp (place->loader_name, loader_name) == 0)
4536 {
4537 break;
4538 }
4539 }
4540 LT_DLMUTEX_UNLOCK ();
4541
4542 return place;
4543 }