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