/[svn]/ircd-hybrid-7.2/libltdl/ltdl.c
ViewVC logotype

Contents of /ircd-hybrid-7.2/libltdl/ltdl.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 912 - (show annotations)
Wed Nov 7 22:47:44 2007 UTC (12 years, 5 months ago) by michael
File MIME type: text/x-chdr
File size: 99390 byte(s)
- Implemented libtool-ltdl. Only shared modules are supported currently
- Several build fixes and cleanups. ircd now builds and runs without any problems
- Added back all files to SVN that are needed to built the daemon
  I really don't want to force other people that want to test the snapshots
  or svn versions to install yyacc, lex, automake, autoconf and libtool...
  No problem having required files in svn
- Removed some automake maintainer stuff which is kinda useless for us

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