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