Install msysDTK-1.0.1
[msysgit.git] / share / libtool / libltdl / ltdl.c
blobad6851e2d0cf42b95fa88eb14e6bae15bfb7aed5
1 /* ltdl.c -- system independent dlopen wrapper
2 Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
3 Originally by Thomas Tanner <tanner@ffii.org>
4 This file is part of GNU Libtool.
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 As a special exception to the GNU Lesser General Public License,
12 if you distribute this file as part of a program or library that
13 is built using GNU libtool, you may include it under the same
14 distribution terms that you use for the rest of that program.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 02111-1307 USA
28 #if HAVE_CONFIG_H
29 # include <config.h>
30 #endif
32 #if HAVE_UNISTD_H
33 # include <unistd.h>
34 #endif
36 #if HAVE_STDIO_H
37 # include <stdio.h>
38 #endif
40 #if HAVE_STDLIB_H
41 # include <stdlib.h>
42 #endif
44 #if HAVE_STRING_H
45 # include <string.h>
46 #else
47 # if HAVE_STRINGS_H
48 # include <strings.h>
49 # endif
50 #endif
52 #if HAVE_CTYPE_H
53 # include <ctype.h>
54 #endif
56 #if HAVE_MALLOC_H
57 # include <malloc.h>
58 #endif
60 #if HAVE_MEMORY_H
61 # include <memory.h>
62 #endif
64 #if HAVE_ERRNO_H
65 # include <errno.h>
66 #endif
69 #ifndef __WINDOWS__
70 # ifdef __WIN32__
71 # define __WINDOWS__
72 # endif
73 #endif
76 #undef LT_USE_POSIX_DIRENT
77 #ifdef HAVE_CLOSEDIR
78 # ifdef HAVE_OPENDIR
79 # ifdef HAVE_READDIR
80 # ifdef HAVE_DIRENT_H
81 # define LT_USE_POSIX_DIRENT
82 # endif /* HAVE_DIRENT_H */
83 # endif /* HAVE_READDIR */
84 # endif /* HAVE_OPENDIR */
85 #endif /* HAVE_CLOSEDIR */
88 #undef LT_USE_WINDOWS_DIRENT_EMULATION
89 #ifndef LT_USE_POSIX_DIRENT
90 # ifdef __WINDOWS__
91 # define LT_USE_WINDOWS_DIRENT_EMULATION
92 # endif /* __WINDOWS__ */
93 #endif /* LT_USE_POSIX_DIRENT */
96 #ifdef LT_USE_POSIX_DIRENT
97 # include <dirent.h>
98 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
99 #else
100 # ifdef LT_USE_WINDOWS_DIRENT_EMULATION
101 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
102 # else
103 # define dirent direct
104 # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
105 # if HAVE_SYS_NDIR_H
106 # include <sys/ndir.h>
107 # endif
108 # if HAVE_SYS_DIR_H
109 # include <sys/dir.h>
110 # endif
111 # if HAVE_NDIR_H
112 # include <ndir.h>
113 # endif
114 # endif
115 #endif
117 #if HAVE_ARGZ_H
118 # include <argz.h>
119 #endif
121 #if HAVE_ASSERT_H
122 # include <assert.h>
123 #else
124 # define assert(arg) ((void) 0)
125 #endif
127 #include "ltdl.h"
129 #if WITH_DMALLOC
130 # include <dmalloc.h>
131 #endif
136 /* --- WINDOWS SUPPORT --- */
139 #ifdef DLL_EXPORT
140 # define LT_GLOBAL_DATA __declspec(dllexport)
141 #else
142 # define LT_GLOBAL_DATA
143 #endif
145 /* fopen() mode flags for reading a text file */
146 #undef LT_READTEXT_MODE
147 #ifdef __WINDOWS__
148 # define LT_READTEXT_MODE "rt"
149 #else
150 # define LT_READTEXT_MODE "r"
151 #endif
153 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
155 #include <windows.h>
157 #define dirent lt_dirent
158 #define DIR lt_DIR
160 struct dirent
162 char d_name[2048];
163 int d_namlen;
166 typedef struct _DIR
168 HANDLE hSearch;
169 WIN32_FIND_DATA Win32FindData;
170 BOOL firsttime;
171 struct dirent file_info;
172 } DIR;
174 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
177 /* --- MANIFEST CONSTANTS --- */
180 /* Standard libltdl search path environment variable name */
181 #undef LTDL_SEARCHPATH_VAR
182 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
184 /* Standard libtool archive file extension. */
185 #undef LTDL_ARCHIVE_EXT
186 #define LTDL_ARCHIVE_EXT ".la"
188 /* max. filename length */
189 #ifndef LT_FILENAME_MAX
190 # define LT_FILENAME_MAX 1024
191 #endif
193 /* This is the maximum symbol size that won't require malloc/free */
194 #undef LT_SYMBOL_LENGTH
195 #define LT_SYMBOL_LENGTH 128
197 /* This accounts for the _LTX_ separator */
198 #undef LT_SYMBOL_OVERHEAD
199 #define LT_SYMBOL_OVERHEAD 5
204 /* --- MEMORY HANDLING --- */
207 /* These are the functions used internally. In addition to making
208 use of the associated function pointers above, they also perform
209 error handling. */
210 static char *lt_estrdup LT_PARAMS((const char *str));
211 static lt_ptr lt_emalloc LT_PARAMS((size_t size));
212 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
214 /* static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); */
215 #define rpl_realloc realloc
217 /* These are the pointers that can be changed by the caller: */
218 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
219 = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
220 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
221 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
222 LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
223 = (void (*) LT_PARAMS((lt_ptr))) free;
225 /* The following macros reduce the amount of typing needed to cast
226 assigned memory. */
227 #if WITH_DMALLOC
229 #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
230 #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
231 #define LT_DLFREE(p) \
232 LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
234 #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
235 #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
237 #else
239 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
240 #define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
241 #define LT_DLFREE(p) \
242 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
244 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
245 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
247 #endif
249 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
250 if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
251 } LT_STMT_END
254 /* --- REPLACEMENT FUNCTIONS --- */
257 #undef strdup
258 #define strdup rpl_strdup
260 static char *strdup LT_PARAMS((const char *str));
262 static char *
263 strdup(str)
264 const char *str;
266 char *tmp = 0;
268 if (str)
270 tmp = LT_DLMALLOC (char, 1+ strlen (str));
271 if (tmp)
273 strcpy(tmp, str);
277 return tmp;
281 #if ! HAVE_STRCMP
283 #undef strcmp
284 #define strcmp rpl_strcmp
286 static int strcmp LT_PARAMS((const char *str1, const char *str2));
288 static int
289 strcmp (str1, str2)
290 const char *str1;
291 const char *str2;
293 if (str1 == str2)
294 return 0;
295 if (str1 == 0)
296 return -1;
297 if (str2 == 0)
298 return 1;
300 for (;*str1 && *str2; ++str1, ++str2)
302 if (*str1 != *str2)
303 break;
306 return (int)(*str1 - *str2);
308 #endif
311 #if ! HAVE_STRCHR
313 # if HAVE_INDEX
314 # define strchr index
315 # else
316 # define strchr rpl_strchr
318 static const char *strchr LT_PARAMS((const char *str, int ch));
320 static const char*
321 strchr(str, ch)
322 const char *str;
323 int ch;
325 const char *p;
327 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
328 /*NOWORK*/;
330 return (*p == (char)ch) ? p : 0;
333 # endif
334 #endif /* !HAVE_STRCHR */
337 #if ! HAVE_STRRCHR
339 # if HAVE_RINDEX
340 # define strrchr rindex
341 # else
342 # define strrchr rpl_strrchr
344 static const char *strrchr LT_PARAMS((const char *str, int ch));
346 static const char*
347 strrchr(str, ch)
348 const char *str;
349 int ch;
351 const char *p, *q = 0;
353 for (p = str; *p != LT_EOS_CHAR; ++p)
355 if (*p == (char) ch)
357 q = p;
361 return q;
364 # endif
365 #endif
367 /* NOTE: Neither bcopy nor the memcpy implementation below can
368 reliably handle copying in overlapping areas of memory. Use
369 memmove (for which there is a fallback implmentation below)
370 if you need that behaviour. */
371 #if ! HAVE_MEMCPY
373 # if HAVE_BCOPY
374 # define memcpy(dest, src, size) bcopy (src, dest, size)
375 # else
376 # define memcpy rpl_memcpy
378 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
380 static lt_ptr
381 memcpy (dest, src, size)
382 lt_ptr dest;
383 const lt_ptr src;
384 size_t size;
386 size_t i = 0;
388 for (i = 0; i < size; ++i)
390 dest[i] = src[i];
393 return dest;
396 # endif /* !HAVE_BCOPY */
397 #endif /* !HAVE_MEMCPY */
399 #if ! HAVE_MEMMOVE
400 # define memmove rpl_memmove
402 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
404 static lt_ptr
405 memmove (dest, src, size)
406 lt_ptr dest;
407 const lt_ptr src;
408 size_t size;
410 size_t i;
412 if (dest < src)
413 for (i = 0; i < size; ++i)
415 dest[i] = src[i];
417 else if (dest > src)
418 for (i = size -1; i >= 0; --i)
420 dest[i] = src[i];
423 return dest;
426 #endif /* !HAVE_MEMMOVE */
428 #ifdef LT_USE_WINDOWS_DIRENT_EMULATION
430 static void closedir LT_PARAMS((DIR *entry));
432 static void
433 closedir(entry)
434 DIR *entry;
436 assert(entry != (DIR *) NULL);
437 FindClose(entry->hSearch);
438 lt_dlfree((lt_ptr)entry);
442 static DIR * opendir LT_PARAMS((const char *path));
444 static DIR*
445 opendir (path)
446 const char *path;
448 char file_specification[LT_FILENAME_MAX];
449 DIR *entry;
451 assert(path != (char *) NULL);
452 (void) strncpy(file_specification,path,LT_FILENAME_MAX-1);
453 (void) strcat(file_specification,"\\");
454 entry = LT_DLMALLOC (DIR,sizeof(DIR));
455 if (entry != (DIR *) 0)
457 entry->firsttime = TRUE;
458 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
460 if (entry->hSearch == INVALID_HANDLE_VALUE)
462 (void) strcat(file_specification,"\\*.*");
463 entry->hSearch = FindFirstFile(file_specification,&entry->Win32FindData);
464 if (entry->hSearch == INVALID_HANDLE_VALUE)
466 LT_DLFREE (entry);
467 return (DIR *) 0;
470 return(entry);
474 static struct dirent *readdir LT_PARAMS((DIR *entry));
476 static struct dirent *readdir(entry)
477 DIR *entry;
480 status;
482 if (entry == (DIR *) 0)
483 return((struct dirent *) 0);
484 if (!entry->firsttime)
486 status = FindNextFile(entry->hSearch,&entry->Win32FindData);
487 if (status == 0)
488 return((struct dirent *) 0);
490 entry->firsttime = FALSE;
491 (void) strncpy(entry->file_info.d_name,entry->Win32FindData.cFileName,
492 LT_FILENAME_MAX-1);
493 entry->file_info.d_namlen = strlen(entry->file_info.d_name);
494 return(&entry->file_info);
497 #endif /* LT_USE_WINDOWS_DIRENT_EMULATION */
499 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
500 ``realloc is not entirely portable''
501 In any case we want to use the allocator supplied by the user without
502 burdening them with an lt_dlrealloc function pointer to maintain.
503 Instead implement our own version (with known boundary conditions)
504 using lt_dlmalloc and lt_dlfree. */
506 /* #undef realloc
507 #define realloc rpl_realloc
509 #if 0
510 /* You can't (re)define realloc unless you also (re)define malloc.
511 Right now, this code uses the size of the *destination* to decide
512 how much to copy. That's not right, but you can't know the size
513 of the source unless you know enough about, or wrote malloc. So
514 this code is disabled... */
516 static lt_ptr
517 realloc (ptr, size)
518 lt_ptr ptr;
519 size_t size;
521 if (size == 0)
523 /* For zero or less bytes, free the original memory */
524 if (ptr != 0)
526 lt_dlfree (ptr);
529 return (lt_ptr) 0;
531 else if (ptr == 0)
533 /* Allow reallocation of a NULL pointer. */
534 return lt_dlmalloc (size);
536 else
538 /* Allocate a new block, copy and free the old block. */
539 lt_ptr mem = lt_dlmalloc (size);
541 if (mem)
543 memcpy (mem, ptr, size);
544 lt_dlfree (ptr);
547 /* Note that the contents of PTR are not damaged if there is
548 insufficient memory to realloc. */
549 return mem;
552 #endif
555 #if ! HAVE_ARGZ_APPEND
556 # define argz_append rpl_argz_append
558 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
559 const char *buf, size_t buf_len));
561 static error_t
562 argz_append (pargz, pargz_len, buf, buf_len)
563 char **pargz;
564 size_t *pargz_len;
565 const char *buf;
566 size_t buf_len;
568 size_t argz_len;
569 char *argz;
571 assert (pargz);
572 assert (pargz_len);
573 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
575 /* If nothing needs to be appended, no more work is required. */
576 if (buf_len == 0)
577 return 0;
579 /* Ensure there is enough room to append BUF_LEN. */
580 argz_len = *pargz_len + buf_len;
581 argz = LT_DLREALLOC (char, *pargz, argz_len);
582 if (!argz)
583 return ENOMEM;
585 /* Copy characters from BUF after terminating '\0' in ARGZ. */
586 memcpy (argz + *pargz_len, buf, buf_len);
588 /* Assign new values. */
589 *pargz = argz;
590 *pargz_len = argz_len;
592 return 0;
594 #endif /* !HAVE_ARGZ_APPEND */
597 #if ! HAVE_ARGZ_CREATE_SEP
598 # define argz_create_sep rpl_argz_create_sep
600 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
601 char **pargz, size_t *pargz_len));
603 static error_t
604 argz_create_sep (str, delim, pargz, pargz_len)
605 const char *str;
606 int delim;
607 char **pargz;
608 size_t *pargz_len;
610 size_t argz_len;
611 char *argz = 0;
613 assert (str);
614 assert (pargz);
615 assert (pargz_len);
617 /* Make a copy of STR, but replacing each occurence of
618 DELIM with '\0'. */
619 argz_len = 1+ LT_STRLEN (str);
620 if (argz_len)
622 const char *p;
623 char *q;
625 argz = LT_DLMALLOC (char, argz_len);
626 if (!argz)
627 return ENOMEM;
629 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
631 if (*p == delim)
633 /* Ignore leading delimiters, and fold consecutive
634 delimiters in STR into a single '\0' in ARGZ. */
635 if ((q > argz) && (q[-1] != LT_EOS_CHAR))
636 *q++ = LT_EOS_CHAR;
637 else
638 --argz_len;
640 else
641 *q++ = *p;
643 /* Copy terminating LT_EOS_CHAR. */
644 *q = *p;
647 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
648 if (!argz_len)
649 LT_DLFREE (argz);
651 /* Assign new values. */
652 *pargz = argz;
653 *pargz_len = argz_len;
655 return 0;
657 #endif /* !HAVE_ARGZ_CREATE_SEP */
660 #if ! HAVE_ARGZ_INSERT
661 # define argz_insert rpl_argz_insert
663 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
664 char *before, const char *entry));
666 static error_t
667 argz_insert (pargz, pargz_len, before, entry)
668 char **pargz;
669 size_t *pargz_len;
670 char *before;
671 const char *entry;
673 assert (pargz);
674 assert (pargz_len);
675 assert (entry && *entry);
677 /* No BEFORE address indicates ENTRY should be inserted after the
678 current last element. */
679 if (!before)
680 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
682 /* This probably indicates a programmer error, but to preserve
683 semantics, scan back to the start of an entry if BEFORE points
684 into the middle of it. */
685 while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR))
686 --before;
689 size_t entry_len = 1+ LT_STRLEN (entry);
690 size_t argz_len = *pargz_len + entry_len;
691 size_t offset = before - *pargz;
692 char *argz = LT_DLREALLOC (char, *pargz, argz_len);
694 if (!argz)
695 return ENOMEM;
697 /* Make BEFORE point to the equivalent offset in ARGZ that it
698 used to have in *PARGZ incase realloc() moved the block. */
699 before = argz + offset;
701 /* Move the ARGZ entries starting at BEFORE up into the new
702 space at the end -- making room to copy ENTRY into the
703 resulting gap. */
704 memmove (before + entry_len, before, *pargz_len - offset);
705 memcpy (before, entry, entry_len);
707 /* Assign new values. */
708 *pargz = argz;
709 *pargz_len = argz_len;
712 return 0;
714 #endif /* !HAVE_ARGZ_INSERT */
717 #if ! HAVE_ARGZ_NEXT
718 # define argz_next rpl_argz_next
720 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
721 const char *entry));
723 static char *
724 argz_next (argz, argz_len, entry)
725 char *argz;
726 size_t argz_len;
727 const char *entry;
729 assert ((argz && argz_len) || (!argz && !argz_len));
731 if (entry)
733 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
734 within the ARGZ vector. */
735 assert ((!argz && !argz_len)
736 || ((argz <= entry) && (entry < (argz + argz_len))));
738 /* Move to the char immediately after the terminating
739 '\0' of ENTRY. */
740 entry = 1+ strchr (entry, LT_EOS_CHAR);
742 /* Return either the new ENTRY, or else NULL if ARGZ is
743 exhausted. */
744 return (entry >= argz + argz_len) ? 0 : (char *) entry;
746 else
748 /* This should probably be flagged as a programmer error,
749 since starting an argz_next loop with the iterator set
750 to ARGZ is safer. To preserve semantics, handle the NULL
751 case by returning the start of ARGZ (if any). */
752 if (argz_len > 0)
753 return argz;
754 else
755 return 0;
758 #endif /* !HAVE_ARGZ_NEXT */
762 #if ! HAVE_ARGZ_STRINGIFY
763 # define argz_stringify rpl_argz_stringify
765 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
766 int sep));
768 static void
769 argz_stringify (argz, argz_len, sep)
770 char *argz;
771 size_t argz_len;
772 int sep;
774 assert ((argz && argz_len) || (!argz && !argz_len));
776 if (sep)
778 --argz_len; /* don't stringify the terminating EOS */
779 while (--argz_len > 0)
781 if (argz[argz_len] == LT_EOS_CHAR)
782 argz[argz_len] = sep;
786 #endif /* !HAVE_ARGZ_STRINGIFY */
791 /* --- TYPE DEFINITIONS -- */
794 /* This type is used for the array of caller data sets in each handler. */
795 typedef struct {
796 lt_dlcaller_id key;
797 lt_ptr data;
798 } lt_caller_data;
803 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
806 /* Extract the diagnostic strings from the error table macro in the same
807 order as the enumerated indices in ltdl.h. */
809 static const char *lt_dlerror_strings[] =
811 #define LT_ERROR(name, diagnostic) (diagnostic),
812 lt_dlerror_table
813 #undef LT_ERROR
818 /* This structure is used for the list of registered loaders. */
819 struct lt_dlloader {
820 struct lt_dlloader *next;
821 const char *loader_name; /* identifying name for each loader */
822 const char *sym_prefix; /* prefix for symbols */
823 lt_module_open *module_open;
824 lt_module_close *module_close;
825 lt_find_sym *find_sym;
826 lt_dlloader_exit *dlloader_exit;
827 lt_user_data dlloader_data;
830 struct lt_dlhandle_struct {
831 struct lt_dlhandle_struct *next;
832 lt_dlloader *loader; /* dlopening interface */
833 lt_dlinfo info;
834 int depcount; /* number of dependencies */
835 lt_dlhandle *deplibs; /* dependencies */
836 lt_module module; /* system module handle */
837 lt_ptr system; /* system specific data */
838 lt_caller_data *caller_data; /* per caller associated data */
839 int flags; /* various boolean stats */
842 /* Various boolean flags can be stored in the flags field of an
843 lt_dlhandle_struct... */
844 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
845 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
847 #define LT_DLRESIDENT_FLAG (0x01 << 0)
848 /* ...add more flags here... */
850 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
853 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
855 static const char objdir[] = LTDL_OBJDIR;
856 static const char archive_ext[] = LTDL_ARCHIVE_EXT;
857 #ifdef LTDL_SHLIB_EXT
858 static const char shlib_ext[] = LTDL_SHLIB_EXT;
859 #endif
860 #ifdef LTDL_SYSSEARCHPATH
861 static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
862 #endif
867 /* --- MUTEX LOCKING --- */
870 /* Macros to make it easier to run the lock functions only if they have
871 been registered. The reason for the complicated lock macro is to
872 ensure that the stored error message from the last error is not
873 accidentally erased if the current function doesn't generate an
874 error of its own. */
875 #define LT_DLMUTEX_LOCK() LT_STMT_START { \
876 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
877 } LT_STMT_END
878 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
879 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
880 } LT_STMT_END
881 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
882 if (lt_dlmutex_seterror_func) \
883 (*lt_dlmutex_seterror_func) (errormsg); \
884 else lt_dllast_error = (errormsg); } LT_STMT_END
885 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
886 if (lt_dlmutex_seterror_func) \
887 (errormsg) = (*lt_dlmutex_geterror_func) (); \
888 else (errormsg) = lt_dllast_error; } LT_STMT_END
890 /* The mutex functions stored here are global, and are necessarily the
891 same for all threads that wish to share access to libltdl. */
892 static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
893 static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
894 static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
895 static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
896 static const char *lt_dllast_error = 0;
899 /* Either set or reset the mutex functions. Either all the arguments must
900 be valid functions, or else all can be NULL to turn off locking entirely.
901 The registered functions should be manipulating a static global lock
902 from the lock() and unlock() callbacks, which needs to be reentrant. */
904 lt_dlmutex_register (lock, unlock, seterror, geterror)
905 lt_dlmutex_lock *lock;
906 lt_dlmutex_unlock *unlock;
907 lt_dlmutex_seterror *seterror;
908 lt_dlmutex_geterror *geterror;
910 lt_dlmutex_unlock *old_unlock = unlock;
911 int errors = 0;
913 /* Lock using the old lock() callback, if any. */
914 LT_DLMUTEX_LOCK ();
916 if ((lock && unlock && seterror && geterror)
917 || !(lock || unlock || seterror || geterror))
919 lt_dlmutex_lock_func = lock;
920 lt_dlmutex_unlock_func = unlock;
921 lt_dlmutex_geterror_func = geterror;
923 else
925 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
926 ++errors;
929 /* Use the old unlock() callback we saved earlier, if any. Otherwise
930 record any errors using internal storage. */
931 if (old_unlock)
932 (*old_unlock) ();
934 /* Return the number of errors encountered during the execution of
935 this function. */
936 return errors;
942 /* --- ERROR HANDLING --- */
945 static const char **user_error_strings = 0;
946 static int errorcount = LT_ERROR_MAX;
949 lt_dladderror (diagnostic)
950 const char *diagnostic;
952 int errindex = 0;
953 int result = -1;
954 const char **temp = (const char **) 0;
956 assert (diagnostic);
958 LT_DLMUTEX_LOCK ();
960 errindex = errorcount - LT_ERROR_MAX;
961 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
962 if (temp)
964 user_error_strings = temp;
965 user_error_strings[errindex] = diagnostic;
966 result = errorcount++;
969 LT_DLMUTEX_UNLOCK ();
971 return result;
975 lt_dlseterror (errindex)
976 int errindex;
978 int errors = 0;
980 LT_DLMUTEX_LOCK ();
982 if (errindex >= errorcount || errindex < 0)
984 /* Ack! Error setting the error message! */
985 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
986 ++errors;
988 else if (errindex < LT_ERROR_MAX)
990 /* No error setting the error message! */
991 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
993 else
995 /* No error setting the error message! */
996 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
999 LT_DLMUTEX_UNLOCK ();
1001 return errors;
1004 static lt_ptr
1005 lt_emalloc (size)
1006 size_t size;
1008 lt_ptr mem = lt_dlmalloc (size);
1009 if (size && !mem)
1010 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1011 return mem;
1014 static lt_ptr
1015 lt_erealloc (addr, size)
1016 lt_ptr addr;
1017 size_t size;
1019 lt_ptr mem = realloc (addr, size);
1020 if (size && !mem)
1021 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1022 return mem;
1025 static char *
1026 lt_estrdup (str)
1027 const char *str;
1029 char *copy = strdup (str);
1030 if (LT_STRLEN (str) && !copy)
1031 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
1032 return copy;
1038 /* --- DLOPEN() INTERFACE LOADER --- */
1041 #if HAVE_LIBDL
1043 /* dynamic linking with dlopen/dlsym */
1045 #if HAVE_DLFCN_H
1046 # include <dlfcn.h>
1047 #endif
1049 #if HAVE_SYS_DL_H
1050 # include <sys/dl.h>
1051 #endif
1053 #ifdef RTLD_GLOBAL
1054 # define LT_GLOBAL RTLD_GLOBAL
1055 #else
1056 # ifdef DL_GLOBAL
1057 # define LT_GLOBAL DL_GLOBAL
1058 # endif
1059 #endif /* !RTLD_GLOBAL */
1060 #ifndef LT_GLOBAL
1061 # define LT_GLOBAL 0
1062 #endif /* !LT_GLOBAL */
1064 /* We may have to define LT_LAZY_OR_NOW in the command line if we
1065 find out it does not work in some platform. */
1066 #ifndef LT_LAZY_OR_NOW
1067 # ifdef RTLD_LAZY
1068 # define LT_LAZY_OR_NOW RTLD_LAZY
1069 # else
1070 # ifdef DL_LAZY
1071 # define LT_LAZY_OR_NOW DL_LAZY
1072 # endif
1073 # endif /* !RTLD_LAZY */
1074 #endif
1075 #ifndef LT_LAZY_OR_NOW
1076 # ifdef RTLD_NOW
1077 # define LT_LAZY_OR_NOW RTLD_NOW
1078 # else
1079 # ifdef DL_NOW
1080 # define LT_LAZY_OR_NOW DL_NOW
1081 # endif
1082 # endif /* !RTLD_NOW */
1083 #endif
1084 #ifndef LT_LAZY_OR_NOW
1085 # define LT_LAZY_OR_NOW 0
1086 #endif /* !LT_LAZY_OR_NOW */
1088 #if HAVE_DLERROR
1089 # define DLERROR(arg) dlerror ()
1090 #else
1091 # define DLERROR(arg) LT_DLSTRERROR (arg)
1092 #endif
1094 static lt_module
1095 sys_dl_open (loader_data, filename)
1096 lt_user_data loader_data;
1097 const char *filename;
1099 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
1101 if (!module)
1103 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
1106 return module;
1109 static int
1110 sys_dl_close (loader_data, module)
1111 lt_user_data loader_data;
1112 lt_module module;
1114 int errors = 0;
1116 if (dlclose (module) != 0)
1118 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
1119 ++errors;
1122 return errors;
1125 static lt_ptr
1126 sys_dl_sym (loader_data, module, symbol)
1127 lt_user_data loader_data;
1128 lt_module module;
1129 const char *symbol;
1131 lt_ptr address = dlsym (module, symbol);
1133 if (!address)
1135 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1138 return address;
1141 static struct lt_user_dlloader sys_dl =
1143 # ifdef NEED_USCORE
1144 "_",
1145 # else
1147 # endif
1148 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1151 #endif /* HAVE_LIBDL */
1155 /* --- SHL_LOAD() INTERFACE LOADER --- */
1157 #if HAVE_SHL_LOAD
1159 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1161 #ifdef HAVE_DL_H
1162 # include <dl.h>
1163 #endif
1165 /* some flags are missing on some systems, so we provide
1166 * harmless defaults.
1168 * Mandatory:
1169 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
1170 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
1172 * Optionally:
1173 * BIND_FIRST - Place the library at the head of the symbol search
1174 * order.
1175 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
1176 * unsatisfied symbols as fatal. This flag allows
1177 * binding of unsatisfied code symbols to be deferred
1178 * until use.
1179 * [Perl: For certain libraries, like DCE, deferred
1180 * binding often causes run time problems. Adding
1181 * BIND_NONFATAL to BIND_IMMEDIATE still allows
1182 * unresolved references in situations like this.]
1183 * BIND_NOSTART - Do not call the initializer for the shared library
1184 * when the library is loaded, nor on a future call to
1185 * shl_unload().
1186 * BIND_VERBOSE - Print verbose messages concerning possible
1187 * unsatisfied symbols.
1189 * hp9000s700/hp9000s800:
1190 * BIND_RESTRICTED - Restrict symbols visible by the library to those
1191 * present at library load time.
1192 * DYNAMIC_PATH - Allow the loader to dynamically search for the
1193 * library specified by the path argument.
1196 #ifndef DYNAMIC_PATH
1197 # define DYNAMIC_PATH 0
1198 #endif
1199 #ifndef BIND_RESTRICTED
1200 # define BIND_RESTRICTED 0
1201 #endif
1203 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1205 static lt_module
1206 sys_shl_open (loader_data, filename)
1207 lt_user_data loader_data;
1208 const char *filename;
1210 static shl_t self = (shl_t) 0;
1211 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1213 /* Since searching for a symbol against a NULL module handle will also
1214 look in everything else that was already loaded and exported with
1215 the -E compiler flag, we always cache a handle saved before any
1216 modules are loaded. */
1217 if (!self)
1219 lt_ptr address;
1220 shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1223 if (!filename)
1225 module = self;
1227 else
1229 module = shl_load (filename, LT_BIND_FLAGS, 0L);
1231 if (!module)
1233 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1237 return module;
1240 static int
1241 sys_shl_close (loader_data, module)
1242 lt_user_data loader_data;
1243 lt_module module;
1245 int errors = 0;
1247 if (module && (shl_unload ((shl_t) (module)) != 0))
1249 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1250 ++errors;
1253 return errors;
1256 static lt_ptr
1257 sys_shl_sym (loader_data, module, symbol)
1258 lt_user_data loader_data;
1259 lt_module module;
1260 const char *symbol;
1262 lt_ptr address = 0;
1264 /* sys_shl_open should never return a NULL module handle */
1265 if (module == (lt_module) 0)
1267 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1269 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1271 if (!address)
1273 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1277 return address;
1280 static struct lt_user_dlloader sys_shl = {
1281 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1284 #endif /* HAVE_SHL_LOAD */
1289 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1291 #ifdef __WINDOWS__
1293 /* dynamic linking for Win32 */
1295 #include <windows.h>
1297 /* Forward declaration; required to implement handle search below. */
1298 static lt_dlhandle handles;
1300 static lt_module
1301 sys_wll_open (loader_data, filename)
1302 lt_user_data loader_data;
1303 const char *filename;
1305 lt_dlhandle cur;
1306 lt_module module = 0;
1307 const char *errormsg = 0;
1308 char *searchname = 0;
1309 char *ext;
1310 char self_name_buf[MAX_PATH];
1312 if (!filename)
1314 /* Get the name of main module */
1315 *self_name_buf = 0;
1316 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1317 filename = ext = self_name_buf;
1319 else
1321 ext = strrchr (filename, '.');
1324 if (ext)
1326 /* FILENAME already has an extension. */
1327 searchname = lt_estrdup (filename);
1329 else
1331 /* Append a `.' to stop Windows from adding an
1332 implicit `.dll' extension. */
1333 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1334 if (searchname)
1335 sprintf (searchname, "%s.", filename);
1337 if (!searchname)
1338 return 0;
1340 #if __CYGWIN__
1342 char wpath[MAX_PATH];
1343 cygwin_conv_to_full_win32_path(searchname, wpath);
1344 module = LoadLibrary(wpath);
1346 #else
1347 module = LoadLibrary (searchname);
1348 #endif
1349 LT_DLFREE (searchname);
1351 /* libltdl expects this function to fail if it is unable
1352 to physically load the library. Sadly, LoadLibrary
1353 will search the loaded libraries for a match and return
1354 one of them if the path search load fails.
1356 We check whether LoadLibrary is returning a handle to
1357 an already loaded module, and simulate failure if we
1358 find one. */
1359 LT_DLMUTEX_LOCK ();
1360 cur = handles;
1361 while (cur)
1363 if (!cur->module)
1365 cur = 0;
1366 break;
1369 if (cur->module == module)
1371 break;
1374 cur = cur->next;
1376 LT_DLMUTEX_UNLOCK ();
1378 if (cur || !module)
1380 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1381 module = 0;
1384 return module;
1387 static int
1388 sys_wll_close (loader_data, module)
1389 lt_user_data loader_data;
1390 lt_module module;
1392 int errors = 0;
1394 if (FreeLibrary(module) == 0)
1396 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1397 ++errors;
1400 return errors;
1403 static lt_ptr
1404 sys_wll_sym (loader_data, module, symbol)
1405 lt_user_data loader_data;
1406 lt_module module;
1407 const char *symbol;
1409 lt_ptr address = GetProcAddress (module, symbol);
1411 if (!address)
1413 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1416 return address;
1419 static struct lt_user_dlloader sys_wll = {
1420 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1423 #endif /* __WINDOWS__ */
1428 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1431 #ifdef __BEOS__
1433 /* dynamic linking for BeOS */
1435 #include <kernel/image.h>
1437 static lt_module
1438 sys_bedl_open (loader_data, filename)
1439 lt_user_data loader_data;
1440 const char *filename;
1442 image_id image = 0;
1444 if (filename)
1446 image = load_add_on (filename);
1448 else
1450 image_info info;
1451 int32 cookie = 0;
1452 if (get_next_image_info (0, &cookie, &info) == B_OK)
1453 image = load_add_on (info.name);
1456 if (image <= 0)
1458 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1459 image = 0;
1462 return (lt_module) image;
1465 static int
1466 sys_bedl_close (loader_data, module)
1467 lt_user_data loader_data;
1468 lt_module module;
1470 int errors = 0;
1472 if (unload_add_on ((image_id) module) != B_OK)
1474 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1475 ++errors;
1478 return errors;
1481 static lt_ptr
1482 sys_bedl_sym (loader_data, module, symbol)
1483 lt_user_data loader_data;
1484 lt_module module;
1485 const char *symbol;
1487 lt_ptr address = 0;
1488 image_id image = (image_id) module;
1490 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1492 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1493 address = 0;
1496 return address;
1499 static struct lt_user_dlloader sys_bedl = {
1500 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1503 #endif /* __BEOS__ */
1508 /* --- DLD_LINK() INTERFACE LOADER --- */
1511 #if HAVE_DLD
1513 /* dynamic linking with dld */
1515 #if HAVE_DLD_H
1516 #include <dld.h>
1517 #endif
1519 static lt_module
1520 sys_dld_open (loader_data, filename)
1521 lt_user_data loader_data;
1522 const char *filename;
1524 lt_module module = strdup (filename);
1526 if (dld_link (filename) != 0)
1528 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1529 LT_DLFREE (module);
1530 module = 0;
1533 return module;
1536 static int
1537 sys_dld_close (loader_data, module)
1538 lt_user_data loader_data;
1539 lt_module module;
1541 int errors = 0;
1543 if (dld_unlink_by_file ((char*)(module), 1) != 0)
1545 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1546 ++errors;
1548 else
1550 LT_DLFREE (module);
1553 return errors;
1556 static lt_ptr
1557 sys_dld_sym (loader_data, module, symbol)
1558 lt_user_data loader_data;
1559 lt_module module;
1560 const char *symbol;
1562 lt_ptr address = dld_get_func (symbol);
1564 if (!address)
1566 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1569 return address;
1572 static struct lt_user_dlloader sys_dld = {
1573 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1576 #endif /* HAVE_DLD */
1581 /* --- DLPREOPEN() INTERFACE LOADER --- */
1584 /* emulate dynamic linking using preloaded_symbols */
1586 typedef struct lt_dlsymlists_t
1588 struct lt_dlsymlists_t *next;
1589 const lt_dlsymlist *syms;
1590 } lt_dlsymlists_t;
1592 static const lt_dlsymlist *default_preloaded_symbols = 0;
1593 static lt_dlsymlists_t *preloaded_symbols = 0;
1595 static int
1596 presym_init (loader_data)
1597 lt_user_data loader_data;
1599 int errors = 0;
1601 LT_DLMUTEX_LOCK ();
1603 preloaded_symbols = 0;
1604 if (default_preloaded_symbols)
1606 errors = lt_dlpreload (default_preloaded_symbols);
1609 LT_DLMUTEX_UNLOCK ();
1611 return errors;
1614 static int
1615 presym_free_symlists ()
1617 lt_dlsymlists_t *lists;
1619 LT_DLMUTEX_LOCK ();
1621 lists = preloaded_symbols;
1622 while (lists)
1624 lt_dlsymlists_t *tmp = lists;
1626 lists = lists->next;
1627 LT_DLFREE (tmp);
1629 preloaded_symbols = 0;
1631 LT_DLMUTEX_UNLOCK ();
1633 return 0;
1636 static int
1637 presym_exit (loader_data)
1638 lt_user_data loader_data;
1640 presym_free_symlists ();
1641 return 0;
1644 static int
1645 presym_add_symlist (preloaded)
1646 const lt_dlsymlist *preloaded;
1648 lt_dlsymlists_t *tmp;
1649 lt_dlsymlists_t *lists;
1650 int errors = 0;
1652 LT_DLMUTEX_LOCK ();
1654 lists = preloaded_symbols;
1655 while (lists)
1657 if (lists->syms == preloaded)
1659 goto done;
1661 lists = lists->next;
1664 tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
1665 if (tmp)
1667 memset (tmp, 0, sizeof(lt_dlsymlists_t));
1668 tmp->syms = preloaded;
1669 tmp->next = preloaded_symbols;
1670 preloaded_symbols = tmp;
1672 else
1674 ++errors;
1677 done:
1678 LT_DLMUTEX_UNLOCK ();
1679 return errors;
1682 static lt_module
1683 presym_open (loader_data, filename)
1684 lt_user_data loader_data;
1685 const char *filename;
1687 lt_dlsymlists_t *lists;
1688 lt_module module = (lt_module) 0;
1690 LT_DLMUTEX_LOCK ();
1691 lists = preloaded_symbols;
1693 if (!lists)
1695 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
1696 goto done;
1699 /* Can't use NULL as the reflective symbol header, as NULL is
1700 used to mark the end of the entire symbol list. Self-dlpreopened
1701 symbols follow this magic number, chosen to be an unlikely
1702 clash with a real module name. */
1703 if (!filename)
1705 filename = "@PROGRAM@";
1708 while (lists)
1710 const lt_dlsymlist *syms = lists->syms;
1712 while (syms->name)
1714 if (!syms->address && strcmp(syms->name, filename) == 0)
1716 module = (lt_module) syms;
1717 goto done;
1719 ++syms;
1722 lists = lists->next;
1725 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
1727 done:
1728 LT_DLMUTEX_UNLOCK ();
1729 return module;
1732 static int
1733 presym_close (loader_data, module)
1734 lt_user_data loader_data;
1735 lt_module module;
1737 /* Just to silence gcc -Wall */
1738 module = 0;
1739 return 0;
1742 static lt_ptr
1743 presym_sym (loader_data, module, symbol)
1744 lt_user_data loader_data;
1745 lt_module module;
1746 const char *symbol;
1748 lt_dlsymlist *syms = (lt_dlsymlist*) module;
1750 ++syms;
1751 while (syms->address)
1753 if (strcmp(syms->name, symbol) == 0)
1755 return syms->address;
1758 ++syms;
1761 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1763 return 0;
1766 static struct lt_user_dlloader presym = {
1767 0, presym_open, presym_close, presym_sym, presym_exit, 0
1774 /* --- DYNAMIC MODULE LOADING --- */
1777 /* The type of a function used at each iteration of foreach_dirinpath(). */
1778 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
1779 lt_ptr data2));
1781 static int foreach_dirinpath LT_PARAMS((const char *search_path,
1782 const char *base_name,
1783 foreach_callback_func *func,
1784 lt_ptr data1, lt_ptr data2));
1786 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
1787 lt_ptr ignored));
1788 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
1789 lt_ptr ignored));
1790 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
1791 lt_ptr data2));
1794 static int canonicalize_path LT_PARAMS((const char *path,
1795 char **pcanonical));
1796 static int argzize_path LT_PARAMS((const char *path,
1797 char **pargz,
1798 size_t *pargz_len));
1799 static FILE *find_file LT_PARAMS((const char *search_path,
1800 const char *base_name,
1801 char **pdir));
1802 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
1803 const char *base_name,
1804 lt_dlhandle *handle));
1805 static int find_module LT_PARAMS((lt_dlhandle *handle,
1806 const char *dir,
1807 const char *libdir,
1808 const char *dlname,
1809 const char *old_name,
1810 int installed));
1811 static int free_vars LT_PARAMS((char *dlname, char *oldname,
1812 char *libdir, char *deplibs));
1813 static int load_deplibs LT_PARAMS((lt_dlhandle handle,
1814 char *deplibs));
1815 static int trim LT_PARAMS((char **dest,
1816 const char *str));
1817 static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
1818 const char *filename));
1819 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
1820 const char *filename));
1821 static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
1822 static int lt_argz_insert LT_PARAMS((char **pargz,
1823 size_t *pargz_len,
1824 char *before,
1825 const char *entry));
1826 static int lt_argz_insertinorder LT_PARAMS((char **pargz,
1827 size_t *pargz_len,
1828 const char *entry));
1829 static int lt_argz_insertdir LT_PARAMS((char **pargz,
1830 size_t *pargz_len,
1831 const char *dirnam,
1832 struct dirent *dp));
1833 static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
1834 char *before,
1835 const char *dir));
1836 static int list_files_by_dir LT_PARAMS((const char *dirnam,
1837 char **pargz,
1838 size_t *pargz_len));
1839 static int file_not_found LT_PARAMS((void));
1841 static char *user_search_path= 0;
1842 static lt_dlloader *loaders = 0;
1843 static lt_dlhandle handles = 0;
1844 static int initialized = 0;
1846 /* Initialize libltdl. */
1848 lt_dlinit ()
1850 int errors = 0;
1852 LT_DLMUTEX_LOCK ();
1854 /* Initialize only at first call. */
1855 if (++initialized == 1)
1857 handles = 0;
1858 user_search_path = 0; /* empty search path */
1860 #if HAVE_LIBDL
1861 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
1862 #endif
1863 #if HAVE_SHL_LOAD
1864 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
1865 #endif
1866 #ifdef __WINDOWS__
1867 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
1868 #endif
1869 #ifdef __BEOS__
1870 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
1871 #endif
1872 #if HAVE_DLD
1873 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
1874 #endif
1875 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
1877 if (presym_init (presym.dlloader_data))
1879 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
1880 ++errors;
1882 else if (errors != 0)
1884 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
1885 ++errors;
1889 LT_DLMUTEX_UNLOCK ();
1891 return errors;
1895 lt_dlpreload (preloaded)
1896 const lt_dlsymlist *preloaded;
1898 int errors = 0;
1900 if (preloaded)
1902 errors = presym_add_symlist (preloaded);
1904 else
1906 presym_free_symlists();
1908 LT_DLMUTEX_LOCK ();
1909 if (default_preloaded_symbols)
1911 errors = lt_dlpreload (default_preloaded_symbols);
1913 LT_DLMUTEX_UNLOCK ();
1916 return errors;
1920 lt_dlpreload_default (preloaded)
1921 const lt_dlsymlist *preloaded;
1923 LT_DLMUTEX_LOCK ();
1924 default_preloaded_symbols = preloaded;
1925 LT_DLMUTEX_UNLOCK ();
1926 return 0;
1930 lt_dlexit ()
1932 /* shut down libltdl */
1933 lt_dlloader *loader;
1934 int errors = 0;
1936 LT_DLMUTEX_LOCK ();
1937 loader = loaders;
1939 if (!initialized)
1941 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
1942 ++errors;
1943 goto done;
1946 /* shut down only at last call. */
1947 if (--initialized == 0)
1949 int level;
1951 while (handles && LT_DLIS_RESIDENT (handles))
1953 handles = handles->next;
1956 /* close all modules */
1957 for (level = 1; handles; ++level)
1959 lt_dlhandle cur = handles;
1960 int saw_nonresident = 0;
1962 while (cur)
1964 lt_dlhandle tmp = cur;
1965 cur = cur->next;
1966 if (!LT_DLIS_RESIDENT (tmp))
1967 saw_nonresident = 1;
1968 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
1970 if (lt_dlclose (tmp))
1972 ++errors;
1976 /* done if only resident modules are left */
1977 if (!saw_nonresident)
1978 break;
1981 /* close all loaders */
1982 while (loader)
1984 lt_dlloader *next = loader->next;
1985 lt_user_data data = loader->dlloader_data;
1986 if (loader->dlloader_exit && loader->dlloader_exit (data))
1988 ++errors;
1991 LT_DLMEM_REASSIGN (loader, next);
1993 loaders = 0;
1996 done:
1997 LT_DLMUTEX_UNLOCK ();
1998 return errors;
2001 static int
2002 tryall_dlopen (handle, filename)
2003 lt_dlhandle *handle;
2004 const char *filename;
2006 lt_dlhandle cur;
2007 lt_dlloader *loader;
2008 const char *saved_error;
2009 int errors = 0;
2011 LT_DLMUTEX_GETERROR (saved_error);
2012 LT_DLMUTEX_LOCK ();
2014 cur = handles;
2015 loader = loaders;
2017 /* check whether the module was already opened */
2018 while (cur)
2020 /* try to dlopen the program itself? */
2021 if (!cur->info.filename && !filename)
2023 break;
2026 if (cur->info.filename && filename
2027 && strcmp (cur->info.filename, filename) == 0)
2029 break;
2032 cur = cur->next;
2035 if (cur)
2037 ++cur->info.ref_count;
2038 *handle = cur;
2039 goto done;
2042 cur = *handle;
2043 if (filename)
2045 /* Comment out the check of file permissions using access.
2046 This call seems to always return -1 with error EACCES.
2048 /* We need to catch missing file errors early so that
2049 file_not_found() can detect what happened.
2050 if (access (filename, R_OK) != 0)
2052 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2053 ++errors;
2054 goto done;
2055 } */
2057 cur->info.filename = lt_estrdup (filename);
2058 if (!cur->info.filename)
2060 ++errors;
2061 goto done;
2064 else
2066 cur->info.filename = 0;
2069 while (loader)
2071 lt_user_data data = loader->dlloader_data;
2073 cur->module = loader->module_open (data, filename);
2075 if (cur->module != 0)
2077 break;
2079 loader = loader->next;
2082 if (!loader)
2084 LT_DLFREE (cur->info.filename);
2085 ++errors;
2086 goto done;
2089 cur->loader = loader;
2090 LT_DLMUTEX_SETERROR (saved_error);
2092 done:
2093 LT_DLMUTEX_UNLOCK ();
2095 return errors;
2098 static int
2099 tryall_dlopen_module (handle, prefix, dirname, dlname)
2100 lt_dlhandle *handle;
2101 const char *prefix;
2102 const char *dirname;
2103 const char *dlname;
2105 int error = 0;
2106 char *filename = 0;
2107 size_t filename_len = 0;
2108 size_t dirname_len = LT_STRLEN (dirname);
2110 assert (handle);
2111 assert (dirname);
2112 assert (dlname);
2113 #ifdef LT_DIRSEP_CHAR
2114 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
2115 should make it into this function: */
2116 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
2117 #endif
2119 if (dirname_len > 0)
2120 if (dirname[dirname_len -1] == '/')
2121 --dirname_len;
2122 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
2124 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
2125 The PREFIX (if any) is handled below. */
2126 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
2127 if (!filename)
2128 return 1;
2130 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
2132 /* Now that we have combined DIRNAME and MODULENAME, if there is
2133 also a PREFIX to contend with, simply recurse with the arguments
2134 shuffled. Otherwise, attempt to open FILENAME as a module. */
2135 if (prefix)
2137 error += tryall_dlopen_module (handle,
2138 (const char *) 0, prefix, filename);
2140 else if (tryall_dlopen (handle, filename) != 0)
2142 ++error;
2145 LT_DLFREE (filename);
2146 return error;
2149 static int
2150 find_module (handle, dir, libdir, dlname, old_name, installed)
2151 lt_dlhandle *handle;
2152 const char *dir;
2153 const char *libdir;
2154 const char *dlname;
2155 const char *old_name;
2156 int installed;
2158 /* Try to open the old library first; if it was dlpreopened,
2159 we want the preopened version of it, even if a dlopenable
2160 module is available. */
2161 if (old_name && tryall_dlopen (handle, old_name) == 0)
2163 return 0;
2166 /* Try to open the dynamic library. */
2167 if (dlname)
2169 /* try to open the installed module */
2170 if (installed && libdir)
2172 if (tryall_dlopen_module (handle,
2173 (const char *) 0, libdir, dlname) == 0)
2174 return 0;
2177 /* try to open the not-installed module */
2178 if (!installed)
2180 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2181 return 0;
2184 /* maybe it was moved to another directory */
2186 if (tryall_dlopen_module (handle,
2187 (const char *) 0, dir, dlname) == 0)
2188 return 0;
2192 return 1;
2196 static int
2197 canonicalize_path (path, pcanonical)
2198 const char *path;
2199 char **pcanonical;
2201 char *canonical = 0;
2203 assert (path && *path);
2204 assert (pcanonical);
2206 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2207 if (!canonical)
2208 return 1;
2211 size_t dest = 0;
2212 size_t src;
2213 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2215 /* Path separators are not copied to the beginning or end of
2216 the destination, or if another separator would follow
2217 immediately. */
2218 if (path[src] == LT_PATHSEP_CHAR)
2220 if ((dest == 0)
2221 || (path[1+ src] == LT_PATHSEP_CHAR)
2222 || (path[1+ src] == LT_EOS_CHAR))
2223 continue;
2226 /* Anything other than a directory separator is copied verbatim. */
2227 if ((path[src] != '/')
2228 #ifdef LT_DIRSEP_CHAR
2229 && (path[src] != LT_DIRSEP_CHAR)
2230 #endif
2233 canonical[dest++] = path[src];
2235 /* Directory separators are converted and copied only if they are
2236 not at the end of a path -- i.e. before a path separator or
2237 NULL terminator. */
2238 else if ((path[1+ src] != LT_PATHSEP_CHAR)
2239 && (path[1+ src] != LT_EOS_CHAR)
2240 #ifdef LT_DIRSEP_CHAR
2241 && (path[1+ src] != LT_DIRSEP_CHAR)
2242 #endif
2243 && (path[1+ src] != '/'))
2245 canonical[dest++] = '/';
2249 /* Add an end-of-string marker at the end. */
2250 canonical[dest] = LT_EOS_CHAR;
2253 /* Assign new value. */
2254 *pcanonical = canonical;
2256 return 0;
2259 static int
2260 argzize_path (path, pargz, pargz_len)
2261 const char *path;
2262 char **pargz;
2263 size_t *pargz_len;
2265 error_t error;
2267 assert (path);
2268 assert (pargz);
2269 assert (pargz_len);
2271 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2273 switch (error)
2275 case ENOMEM:
2276 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2277 break;
2278 default:
2279 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2280 break;
2283 return 1;
2286 return 0;
2289 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2290 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2291 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2292 it is appended to each SEARCH_PATH element before FUNC is called. */
2293 static int
2294 foreach_dirinpath (search_path, base_name, func, data1, data2)
2295 const char *search_path;
2296 const char *base_name;
2297 foreach_callback_func *func;
2298 lt_ptr data1;
2299 lt_ptr data2;
2301 int result = 0;
2302 int filenamesize = 0;
2303 size_t lenbase = LT_STRLEN (base_name);
2304 size_t argz_len = 0;
2305 char *argz = 0;
2306 char *filename = 0;
2307 char *canonical = 0;
2309 LT_DLMUTEX_LOCK ();
2311 if (!search_path || !*search_path)
2313 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2314 goto cleanup;
2317 if (canonicalize_path (search_path, &canonical) != 0)
2318 goto cleanup;
2320 if (argzize_path (canonical, &argz, &argz_len) != 0)
2321 goto cleanup;
2324 char *dir_name = 0;
2325 while ((dir_name = argz_next (argz, argz_len, dir_name)))
2327 size_t lendir = LT_STRLEN (dir_name);
2329 if (lendir +1 +lenbase >= filenamesize)
2331 LT_DLFREE (filename);
2332 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2333 filename = LT_EMALLOC (char, filenamesize);
2334 if (!filename)
2335 goto cleanup;
2338 assert (filenamesize > lendir);
2339 strcpy (filename, dir_name);
2341 if (base_name && *base_name)
2343 if (filename[lendir -1] != '/')
2344 filename[lendir++] = '/';
2345 strcpy (filename +lendir, base_name);
2348 if ((result = (*func) (filename, data1, data2)))
2350 break;
2355 cleanup:
2356 LT_DLFREE (argz);
2357 LT_DLFREE (canonical);
2358 LT_DLFREE (filename);
2360 LT_DLMUTEX_UNLOCK ();
2362 return result;
2365 /* If FILEPATH can be opened, store the name of the directory component
2366 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2367 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2368 static int
2369 find_file_callback (filename, data1, data2)
2370 char *filename;
2371 lt_ptr data1;
2372 lt_ptr data2;
2374 char **pdir = (char **) data1;
2375 FILE **pfile = (FILE **) data2;
2376 int is_done = 0;
2378 assert (filename && *filename);
2379 assert (pdir);
2380 assert (pfile);
2382 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2384 char *dirend = strrchr (filename, '/');
2386 if (dirend > filename)
2387 *dirend = LT_EOS_CHAR;
2389 LT_DLFREE (*pdir);
2390 *pdir = lt_estrdup (filename);
2391 is_done = (*pdir == 0) ? -1 : 1;
2394 return is_done;
2397 static FILE *
2398 find_file (search_path, base_name, pdir)
2399 const char *search_path;
2400 const char *base_name;
2401 char **pdir;
2403 FILE *file = 0;
2405 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2407 return file;
2410 static int
2411 find_handle_callback (filename, data, ignored)
2412 char *filename;
2413 lt_ptr data;
2414 lt_ptr ignored;
2416 lt_dlhandle *handle = (lt_dlhandle *) data;
2417 int notfound = access (filename, R_OK);
2419 /* Bail out if file cannot be read... */
2420 if (notfound)
2421 return 0;
2423 /* Try to dlopen the file, but do not continue searching in any
2424 case. */
2425 if (tryall_dlopen (handle, filename) != 0)
2426 *handle = 0;
2428 return 1;
2431 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
2432 found but could not be opened, *HANDLE will be set to 0. */
2433 static lt_dlhandle *
2434 find_handle (search_path, base_name, handle)
2435 const char *search_path;
2436 const char *base_name;
2437 lt_dlhandle *handle;
2439 if (!search_path)
2440 return 0;
2442 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2443 handle, 0))
2444 return 0;
2446 return handle;
2449 static int
2450 load_deplibs (handle, deplibs)
2451 lt_dlhandle handle;
2452 char *deplibs;
2454 #if LTDL_DLOPEN_DEPLIBS
2455 char *p, *save_search_path = 0;
2456 int depcount = 0;
2457 int i;
2458 char **names = 0;
2459 #endif
2460 int errors = 0;
2462 handle->depcount = 0;
2464 #if LTDL_DLOPEN_DEPLIBS
2465 if (!deplibs)
2467 return errors;
2469 ++errors;
2471 LT_DLMUTEX_LOCK ();
2472 if (user_search_path)
2474 save_search_path = lt_estrdup (user_search_path);
2475 if (!save_search_path)
2476 goto cleanup;
2479 /* extract search paths and count deplibs */
2480 p = deplibs;
2481 while (*p)
2483 if (!isspace ((int) *p))
2485 char *end = p+1;
2486 while (*end && !isspace((int) *end))
2488 ++end;
2491 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2493 char save = *end;
2494 *end = 0; /* set a temporary string terminator */
2495 if (lt_dladdsearchdir(p+2))
2497 goto cleanup;
2499 *end = save;
2501 else
2503 ++depcount;
2506 p = end;
2508 else
2510 ++p;
2514 /* restore the old search path */
2515 LT_DLFREE (user_search_path);
2516 user_search_path = save_search_path;
2518 LT_DLMUTEX_UNLOCK ();
2520 if (!depcount)
2522 errors = 0;
2523 goto cleanup;
2526 names = LT_EMALLOC (char *, depcount * sizeof (char*));
2527 if (!names)
2528 goto cleanup;
2530 /* now only extract the actual deplibs */
2531 depcount = 0;
2532 p = deplibs;
2533 while (*p)
2535 if (isspace ((int) *p))
2537 ++p;
2539 else
2541 char *end = p+1;
2542 while (*end && !isspace ((int) *end))
2544 ++end;
2547 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2549 char *name;
2550 char save = *end;
2551 *end = 0; /* set a temporary string terminator */
2552 if (strncmp(p, "-l", 2) == 0)
2554 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2555 name = LT_EMALLOC (char, 1+ name_len);
2556 if (name)
2557 sprintf (name, "lib%s", p+2);
2559 else
2560 name = lt_estrdup(p);
2562 if (!name)
2563 goto cleanup_names;
2565 names[depcount++] = name;
2566 *end = save;
2568 p = end;
2572 /* load the deplibs (in reverse order)
2573 At this stage, don't worry if the deplibs do not load correctly,
2574 they may already be statically linked into the loading application
2575 for instance. There will be a more enlightening error message
2576 later on if the loaded module cannot resolve all of its symbols. */
2577 if (depcount)
2579 int j = 0;
2581 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2582 if (!handle->deplibs)
2583 goto cleanup;
2585 for (i = 0; i < depcount; ++i)
2587 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2588 if (handle->deplibs[j])
2590 ++j;
2594 handle->depcount = j; /* Number of successfully loaded deplibs */
2595 errors = 0;
2598 cleanup_names:
2599 for (i = 0; i < depcount; ++i)
2601 LT_DLFREE (names[i]);
2604 cleanup:
2605 LT_DLFREE (names);
2606 #endif
2608 return errors;
2611 static int
2612 unload_deplibs (handle)
2613 lt_dlhandle handle;
2615 int i;
2616 int errors = 0;
2618 if (handle->depcount)
2620 for (i = 0; i < handle->depcount; ++i)
2622 if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
2624 errors += lt_dlclose (handle->deplibs[i]);
2629 return errors;
2632 static int
2633 trim (dest, str)
2634 char **dest;
2635 const char *str;
2637 /* remove the leading and trailing "'" from str
2638 and store the result in dest */
2639 const char *end = strrchr (str, '\'');
2640 size_t len = LT_STRLEN (str);
2641 char *tmp;
2643 LT_DLFREE (*dest);
2645 if (len > 3 && str[0] == '\'')
2647 tmp = LT_EMALLOC (char, end - str);
2648 if (!tmp)
2649 return 1;
2651 strncpy(tmp, &str[1], (end - str) - 1);
2652 tmp[len-3] = LT_EOS_CHAR;
2653 *dest = tmp;
2655 else
2657 *dest = 0;
2660 return 0;
2663 static int
2664 free_vars (dlname, oldname, libdir, deplibs)
2665 char *dlname;
2666 char *oldname;
2667 char *libdir;
2668 char *deplibs;
2670 LT_DLFREE (dlname);
2671 LT_DLFREE (oldname);
2672 LT_DLFREE (libdir);
2673 LT_DLFREE (deplibs);
2675 return 0;
2678 static int
2679 try_dlopen (phandle, filename)
2680 lt_dlhandle *phandle;
2681 const char *filename;
2683 const char * ext = 0;
2684 const char * saved_error = 0;
2685 char * canonical = 0;
2686 char * base_name = 0;
2687 char * dir = 0;
2688 char * name = 0;
2689 int errors = 0;
2690 lt_dlhandle newhandle;
2692 assert (phandle);
2693 assert (*phandle == 0);
2695 LT_DLMUTEX_GETERROR (saved_error);
2697 /* dlopen self? */
2698 if (!filename)
2700 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2701 if (*phandle == 0)
2702 return 1;
2704 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
2705 newhandle = *phandle;
2707 /* lt_dlclose()ing yourself is very bad! Disallow it. */
2708 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
2710 if (tryall_dlopen (&newhandle, 0) != 0)
2712 LT_DLFREE (*phandle);
2713 return 1;
2716 goto register_handle;
2719 assert (filename && *filename);
2721 /* Doing this immediately allows internal functions to safely
2722 assume only canonicalized paths are passed. */
2723 if (canonicalize_path (filename, &canonical) != 0)
2725 ++errors;
2726 goto cleanup;
2729 /* If the canonical module name is a path (relative or absolute)
2730 then split it into a directory part and a name part. */
2731 base_name = strrchr (canonical, '/');
2732 if (base_name)
2734 size_t dirlen = (1+ base_name) - canonical;
2736 dir = LT_EMALLOC (char, 1+ dirlen);
2737 if (!dir)
2739 ++errors;
2740 goto cleanup;
2743 strncpy (dir, canonical, dirlen);
2744 dir[dirlen] = LT_EOS_CHAR;
2746 ++base_name;
2748 else
2749 LT_DLMEM_REASSIGN (base_name, canonical);
2751 assert (base_name && *base_name);
2753 /* Check whether we are opening a libtool module (.la extension). */
2754 ext = strrchr (base_name, '.');
2755 if (ext && strcmp (ext, archive_ext) == 0)
2757 /* this seems to be a libtool module */
2758 FILE * file = 0;
2759 char * dlname = 0;
2760 char * old_name = 0;
2761 char * libdir = 0;
2762 char * deplibs = 0;
2763 char * line = 0;
2764 size_t line_len;
2766 /* if we can't find the installed flag, it is probably an
2767 installed libtool archive, produced with an old version
2768 of libtool */
2769 int installed = 1;
2771 /* extract the module name from the file name */
2772 name = LT_EMALLOC (char, ext - base_name + 1);
2773 if (!name)
2775 ++errors;
2776 goto cleanup;
2779 /* canonicalize the module name */
2781 size_t i;
2782 for (i = 0; i < ext - base_name; ++i)
2784 if (isalnum ((int)(base_name[i])))
2786 name[i] = base_name[i];
2788 else
2790 name[i] = '_';
2793 name[ext - base_name] = LT_EOS_CHAR;
2796 /* Now try to open the .la file. If there is no directory name
2797 component, try to find it first in user_search_path and then other
2798 prescribed paths. Otherwise (or in any case if the module was not
2799 yet found) try opening just the module name as passed. */
2800 if (!dir)
2802 const char *search_path;
2804 LT_DLMUTEX_LOCK ();
2805 search_path = user_search_path;
2806 if (search_path)
2807 file = find_file (user_search_path, base_name, &dir);
2808 LT_DLMUTEX_UNLOCK ();
2810 if (!file)
2812 search_path = getenv (LTDL_SEARCHPATH_VAR);
2813 if (search_path)
2814 file = find_file (search_path, base_name, &dir);
2817 #ifdef LTDL_SHLIBPATH_VAR
2818 if (!file)
2820 search_path = getenv (LTDL_SHLIBPATH_VAR);
2821 if (search_path)
2822 file = find_file (search_path, base_name, &dir);
2824 #endif
2825 #ifdef LTDL_SYSSEARCHPATH
2826 if (!file && sys_search_path)
2828 file = find_file (sys_search_path, base_name, &dir);
2830 #endif
2832 if (!file)
2834 file = fopen (filename, LT_READTEXT_MODE);
2837 /* If we didn't find the file by now, it really isn't there. Set
2838 the status flag, and bail out. */
2839 if (!file)
2841 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2842 ++errors;
2843 goto cleanup;
2846 line_len = LT_FILENAME_MAX;
2847 line = LT_EMALLOC (char, line_len);
2848 if (!line)
2850 fclose (file);
2851 ++errors;
2852 goto cleanup;
2855 /* read the .la file */
2856 while (!feof (file))
2858 if (!fgets (line, (int) line_len, file))
2860 break;
2863 /* Handle the case where we occasionally need to read a line
2864 that is longer than the initial buffer size. */
2865 while ((line[LT_STRLEN(line) -1] != '\n') && (!feof (file)))
2867 line = LT_DLREALLOC (char, line, line_len *2);
2868 if (!fgets (&line[line_len -1], (int) line_len +1, file))
2870 break;
2872 line_len *= 2;
2875 if (line[0] == '\n' || line[0] == '#')
2877 continue;
2880 #undef STR_DLNAME
2881 #define STR_DLNAME "dlname="
2882 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
2884 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
2887 #undef STR_OLD_LIBRARY
2888 #define STR_OLD_LIBRARY "old_library="
2889 else if (strncmp (line, STR_OLD_LIBRARY,
2890 sizeof (STR_OLD_LIBRARY) - 1) == 0)
2892 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
2894 #undef STR_LIBDIR
2895 #define STR_LIBDIR "libdir="
2896 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
2898 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
2901 #undef STR_DL_DEPLIBS
2902 #define STR_DL_DEPLIBS "dependency_libs="
2903 else if (strncmp (line, STR_DL_DEPLIBS,
2904 sizeof (STR_DL_DEPLIBS) - 1) == 0)
2906 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
2908 else if (strcmp (line, "installed=yes\n") == 0)
2910 installed = 1;
2912 else if (strcmp (line, "installed=no\n") == 0)
2914 installed = 0;
2917 #undef STR_LIBRARY_NAMES
2918 #define STR_LIBRARY_NAMES "library_names="
2919 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
2920 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
2922 char *last_libname;
2923 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
2924 if (!errors
2925 && dlname
2926 && (last_libname = strrchr (dlname, ' ')) != 0)
2928 last_libname = lt_estrdup (last_libname + 1);
2929 if (!last_libname)
2931 ++errors;
2932 goto cleanup;
2934 LT_DLMEM_REASSIGN (dlname, last_libname);
2938 if (errors)
2939 break;
2942 fclose (file);
2943 LT_DLFREE (line);
2945 /* allocate the handle */
2946 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2947 if (*phandle == 0)
2948 ++errors;
2950 if (errors)
2952 free_vars (dlname, old_name, libdir, deplibs);
2953 LT_DLFREE (*phandle);
2954 goto cleanup;
2957 assert (*phandle);
2959 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
2960 if (load_deplibs (*phandle, deplibs) == 0)
2962 newhandle = *phandle;
2963 /* find_module may replace newhandle */
2964 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
2966 unload_deplibs (*phandle);
2967 ++errors;
2970 else
2972 ++errors;
2975 free_vars (dlname, old_name, libdir, deplibs);
2976 if (errors)
2978 LT_DLFREE (*phandle);
2979 goto cleanup;
2982 if (*phandle != newhandle)
2984 unload_deplibs (*phandle);
2987 else
2989 /* not a libtool module */
2990 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2991 if (*phandle == 0)
2993 ++errors;
2994 goto cleanup;
2997 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
2998 newhandle = *phandle;
3000 /* If the module has no directory name component, try to find it
3001 first in user_search_path and then other prescribed paths.
3002 Otherwise (or in any case if the module was not yet found) try
3003 opening just the module name as passed. */
3004 if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
3005 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
3006 &newhandle)
3007 #ifdef LTDL_SHLIBPATH_VAR
3008 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
3009 &newhandle)
3010 #endif
3011 #ifdef LTDL_SYSSEARCHPATH
3012 && !find_handle (sys_search_path, base_name, &newhandle)
3013 #endif
3016 if (tryall_dlopen (&newhandle, filename) != 0)
3018 newhandle = NULL;
3022 if (!newhandle)
3024 LT_DLFREE (*phandle);
3025 ++errors;
3026 goto cleanup;
3030 register_handle:
3031 LT_DLMEM_REASSIGN (*phandle, newhandle);
3033 if ((*phandle)->info.ref_count == 0)
3035 (*phandle)->info.ref_count = 1;
3036 LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
3038 LT_DLMUTEX_LOCK ();
3039 (*phandle)->next = handles;
3040 handles = *phandle;
3041 LT_DLMUTEX_UNLOCK ();
3044 LT_DLMUTEX_SETERROR (saved_error);
3046 cleanup:
3047 LT_DLFREE (dir);
3048 LT_DLFREE (name);
3049 LT_DLFREE (canonical);
3051 return errors;
3054 lt_dlhandle
3055 lt_dlopen (filename)
3056 const char *filename;
3058 lt_dlhandle handle = 0;
3060 /* Just incase we missed a code path in try_dlopen() that reports
3061 an error, but forgets to reset handle... */
3062 if (try_dlopen (&handle, filename) != 0)
3063 return 0;
3065 return handle;
3068 /* If the last error messge store was `FILE_NOT_FOUND', then return
3069 non-zero. */
3070 static int
3071 file_not_found ()
3073 const char *error = 0;
3075 LT_DLMUTEX_GETERROR (error);
3076 if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
3077 return 1;
3079 return 0;
3082 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
3083 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
3084 and if a file is still not found try again with SHLIB_EXT appended
3085 instead. */
3086 lt_dlhandle
3087 lt_dlopenext (filename)
3088 const char *filename;
3090 lt_dlhandle handle = 0;
3091 char * tmp = 0;
3092 char * ext = 0;
3093 size_t len;
3094 int errors = 0;
3096 if (!filename)
3098 return lt_dlopen (filename);
3101 assert (filename);
3103 len = LT_STRLEN (filename);
3104 ext = strrchr (filename, '.');
3106 /* If FILENAME already bears a suitable extension, there is no need
3107 to try appending additional extensions. */
3108 if (ext && ((strcmp (ext, archive_ext) == 0)
3109 #ifdef LTDL_SHLIB_EXT
3110 || (strcmp (ext, shlib_ext) == 0)
3111 #endif
3114 return lt_dlopen (filename);
3117 /* First try appending ARCHIVE_EXT. */
3118 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
3119 if (!tmp)
3120 return 0;
3122 strcpy (tmp, filename);
3123 strcat (tmp, archive_ext);
3124 errors = try_dlopen (&handle, tmp);
3126 /* If we found FILENAME, stop searching -- whether we were able to
3127 load the file as a module or not. If the file exists but loading
3128 failed, it is better to return an error message here than to
3129 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
3130 in the module search path. */
3131 if (handle || ((errors > 0) && !file_not_found ()))
3133 LT_DLFREE (tmp);
3134 return handle;
3137 #ifdef LTDL_SHLIB_EXT
3138 /* Try appending SHLIB_EXT. */
3139 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
3141 LT_DLFREE (tmp);
3142 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3143 if (!tmp)
3144 return 0;
3146 strcpy (tmp, filename);
3148 else
3150 tmp[len] = LT_EOS_CHAR;
3153 strcat(tmp, shlib_ext);
3154 errors = try_dlopen (&handle, tmp);
3156 /* As before, if the file was found but loading failed, return now
3157 with the current error message. */
3158 if (handle || ((errors > 0) && !file_not_found ()))
3160 LT_DLFREE (tmp);
3161 return handle;
3163 #endif
3165 /* Still here? Then we really did fail to locate any of the file
3166 names we tried. */
3167 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3168 LT_DLFREE (tmp);
3169 return 0;
3173 static int
3174 lt_argz_insert (pargz, pargz_len, before, entry)
3175 char **pargz;
3176 size_t *pargz_len;
3177 char *before;
3178 const char *entry;
3180 error_t error;
3182 if ((error = argz_insert (pargz, pargz_len, before, entry)))
3184 switch (error)
3186 case ENOMEM:
3187 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3188 break;
3189 default:
3190 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3191 break;
3193 return 1;
3196 return 0;
3199 static int
3200 lt_argz_insertinorder (pargz, pargz_len, entry)
3201 char **pargz;
3202 size_t *pargz_len;
3203 const char *entry;
3205 char *before = 0;
3207 assert (pargz);
3208 assert (pargz_len);
3209 assert (entry && *entry);
3211 if (*pargz)
3212 while ((before = argz_next (*pargz, *pargz_len, before)))
3214 int cmp = strcmp (entry, before);
3216 if (cmp < 0) break;
3217 if (cmp == 0) return 0; /* No duplicates! */
3220 return lt_argz_insert (pargz, pargz_len, before, entry);
3223 static int
3224 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3225 char **pargz;
3226 size_t *pargz_len;
3227 const char *dirnam;
3228 struct dirent *dp;
3230 char *buf = 0;
3231 size_t buf_len = 0;
3232 char *end = 0;
3233 size_t end_offset = 0;
3234 size_t dir_len = 0;
3235 int errors = 0;
3237 assert (pargz);
3238 assert (pargz_len);
3239 assert (dp);
3241 dir_len = LT_STRLEN (dirnam);
3242 end = dp->d_name + LT_D_NAMLEN(dp);
3244 /* Ignore version numbers. */
3246 char *p;
3247 for (p = end; p -1 > dp->d_name; --p)
3248 if (strchr (".0123456789", p[-1]) == 0)
3249 break;
3251 if (*p == '.')
3252 end = p;
3255 /* Ignore filename extension. */
3257 char *p;
3258 for (p = end -1; p > dp->d_name; --p)
3259 if (*p == '.')
3261 end = p;
3262 break;
3266 /* Prepend the directory name. */
3267 end_offset = end - dp->d_name;
3268 buf_len = dir_len + 1+ end_offset;
3269 buf = LT_EMALLOC (char, 1+ buf_len);
3270 if (!buf)
3271 return ++errors;
3273 assert (buf);
3275 strcpy (buf, dirnam);
3276 strcat (buf, "/");
3277 strncat (buf, dp->d_name, end_offset);
3278 buf[buf_len] = LT_EOS_CHAR;
3280 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3281 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3282 ++errors;
3284 LT_DLFREE (buf);
3286 return errors;
3289 static int
3290 list_files_by_dir (dirnam, pargz, pargz_len)
3291 const char *dirnam;
3292 char **pargz;
3293 size_t *pargz_len;
3295 DIR *dirp = 0;
3296 int errors = 0;
3298 assert (dirnam && *dirnam);
3299 assert (pargz);
3300 assert (pargz_len);
3301 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3303 dirp = opendir (dirnam);
3304 if (dirp)
3306 struct dirent *dp = 0;
3308 while ((dp = readdir (dirp)))
3309 if (dp->d_name[0] != '.')
3310 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3312 ++errors;
3313 break;
3316 closedir (dirp);
3318 else
3319 ++errors;
3321 return errors;
3325 /* If there are any files in DIRNAME, call the function passed in
3326 DATA1 (with the name of each file and DATA2 as arguments). */
3327 static int
3328 foreachfile_callback (dirname, data1, data2)
3329 char *dirname;
3330 lt_ptr data1;
3331 lt_ptr data2;
3333 int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3334 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3336 int is_done = 0;
3337 char *argz = 0;
3338 size_t argz_len = 0;
3340 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3341 goto cleanup;
3342 if (!argz)
3343 goto cleanup;
3346 char *filename = 0;
3347 while ((filename = argz_next (argz, argz_len, filename)))
3348 if ((is_done = (*func) (filename, data2)))
3349 break;
3352 cleanup:
3353 LT_DLFREE (argz);
3355 return is_done;
3359 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3360 with DATA. The filenames passed to FUNC would be suitable for
3361 passing to lt_dlopenext. The extensions are stripped so that
3362 individual modules do not generate several entries (e.g. libfoo.la,
3363 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3364 then the same directories that lt_dlopen would search are examined. */
3366 lt_dlforeachfile (search_path, func, data)
3367 const char *search_path;
3368 int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3369 lt_ptr data;
3371 int is_done = 0;
3373 if (search_path)
3375 /* If a specific path was passed, search only the directories
3376 listed in it. */
3377 is_done = foreach_dirinpath (search_path, 0,
3378 foreachfile_callback, func, data);
3380 else
3382 /* Otherwise search the default paths. */
3383 is_done = foreach_dirinpath (user_search_path, 0,
3384 foreachfile_callback, func, data);
3385 if (!is_done)
3387 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3388 foreachfile_callback, func, data);
3391 #ifdef LTDL_SHLIBPATH_VAR
3392 if (!is_done)
3394 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3395 foreachfile_callback, func, data);
3397 #endif
3398 #ifdef LTDL_SYSSEARCHPATH
3399 if (!is_done)
3401 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3402 foreachfile_callback, func, data);
3404 #endif
3407 return is_done;
3411 lt_dlclose (handle)
3412 lt_dlhandle handle;
3414 lt_dlhandle cur, last;
3415 int errors = 0;
3417 LT_DLMUTEX_LOCK ();
3419 /* check whether the handle is valid */
3420 last = cur = handles;
3421 while (cur && handle != cur)
3423 last = cur;
3424 cur = cur->next;
3427 if (!cur)
3429 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3430 ++errors;
3431 goto done;
3434 handle->info.ref_count--;
3436 /* Note that even with resident modules, we must track the ref_count
3437 correctly incase the user decides to reset the residency flag
3438 later (even though the API makes no provision for that at the
3439 moment). */
3440 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3442 lt_user_data data = handle->loader->dlloader_data;
3444 if (handle != handles)
3446 last->next = handle->next;
3448 else
3450 handles = handle->next;
3453 errors += handle->loader->module_close (data, handle->module);
3454 errors += unload_deplibs(handle);
3456 /* It is up to the callers to free the data itself. */
3457 LT_DLFREE (handle->caller_data);
3459 LT_DLFREE (handle->info.filename);
3460 LT_DLFREE (handle->info.name);
3461 LT_DLFREE (handle);
3463 goto done;
3466 if (LT_DLIS_RESIDENT (handle))
3468 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3469 ++errors;
3472 done:
3473 LT_DLMUTEX_UNLOCK ();
3475 return errors;
3478 lt_ptr
3479 lt_dlsym (handle, symbol)
3480 lt_dlhandle handle;
3481 const char *symbol;
3483 size_t lensym;
3484 char lsym[LT_SYMBOL_LENGTH];
3485 char *sym;
3486 lt_ptr address;
3487 lt_user_data data;
3489 if (!handle)
3491 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3492 return 0;
3495 if (!symbol)
3497 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3498 return 0;
3501 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3502 + LT_STRLEN (handle->info.name);
3504 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3506 sym = lsym;
3508 else
3510 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3511 if (!sym)
3513 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3514 return 0;
3518 data = handle->loader->dlloader_data;
3519 if (handle->info.name)
3521 const char *saved_error;
3523 LT_DLMUTEX_GETERROR (saved_error);
3525 /* this is a libtool module */
3526 if (handle->loader->sym_prefix)
3528 strcpy(sym, handle->loader->sym_prefix);
3529 strcat(sym, handle->info.name);
3531 else
3533 strcpy(sym, handle->info.name);
3536 strcat(sym, "_LTX_");
3537 strcat(sym, symbol);
3539 /* try "modulename_LTX_symbol" */
3540 address = handle->loader->find_sym (data, handle->module, sym);
3541 if (address)
3543 if (sym != lsym)
3545 LT_DLFREE (sym);
3547 return address;
3549 LT_DLMUTEX_SETERROR (saved_error);
3552 /* otherwise try "symbol" */
3553 if (handle->loader->sym_prefix)
3555 strcpy(sym, handle->loader->sym_prefix);
3556 strcat(sym, symbol);
3558 else
3560 strcpy(sym, symbol);
3563 address = handle->loader->find_sym (data, handle->module, sym);
3564 if (sym != lsym)
3566 LT_DLFREE (sym);
3569 return address;
3572 const char *
3573 lt_dlerror ()
3575 const char *error;
3577 LT_DLMUTEX_GETERROR (error);
3578 LT_DLMUTEX_SETERROR (0);
3580 return error ? error : LT_DLSTRERROR (UNKNOWN);
3583 static int
3584 lt_dlpath_insertdir (ppath, before, dir)
3585 char **ppath;
3586 char *before;
3587 const char *dir;
3589 int errors = 0;
3590 char *canonical = 0;
3591 char *argz = 0;
3592 size_t argz_len = 0;
3594 assert (ppath);
3595 assert (dir && *dir);
3597 if (canonicalize_path (dir, &canonical) != 0)
3599 ++errors;
3600 goto cleanup;
3603 assert (canonical && *canonical);
3605 /* If *PPATH is empty, set it to DIR. */
3606 if (*ppath == 0)
3608 assert (!before); /* BEFORE cannot be set without PPATH. */
3609 assert (dir); /* Without DIR, don't call this function! */
3611 *ppath = lt_estrdup (dir);
3612 if (*ppath == 0)
3613 ++errors;
3615 return errors;
3618 assert (ppath && *ppath);
3620 if (argzize_path (*ppath, &argz, &argz_len) != 0)
3622 ++errors;
3623 goto cleanup;
3626 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
3627 if *PPATH is already canonicalized, and hence does not change length
3628 with respect to ARGZ. We canonicalize each entry as it is added to
3629 the search path, and don't call this function with (uncanonicalized)
3630 user paths, so this is a fair assumption. */
3631 if (before)
3633 assert (*ppath <= before);
3634 assert (before - *ppath <= strlen (*ppath));
3636 before = before - *ppath + argz;
3639 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
3641 ++errors;
3642 goto cleanup;
3645 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
3646 LT_DLMEM_REASSIGN (*ppath, argz);
3648 cleanup:
3649 LT_DLFREE (canonical);
3650 LT_DLFREE (argz);
3652 return errors;
3656 lt_dladdsearchdir (search_dir)
3657 const char *search_dir;
3659 int errors = 0;
3661 if (search_dir && *search_dir)
3663 LT_DLMUTEX_LOCK ();
3664 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
3665 ++errors;
3666 LT_DLMUTEX_UNLOCK ();
3669 return errors;
3673 lt_dlinsertsearchdir (before, search_dir)
3674 const char *before;
3675 const char *search_dir;
3677 int errors = 0;
3679 if (before)
3681 LT_DLMUTEX_LOCK ();
3682 if ((before < user_search_path)
3683 || (before >= user_search_path + LT_STRLEN (user_search_path)))
3685 LT_DLMUTEX_UNLOCK ();
3686 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
3687 return 1;
3689 LT_DLMUTEX_UNLOCK ();
3692 if (search_dir && *search_dir)
3694 LT_DLMUTEX_LOCK ();
3695 if (lt_dlpath_insertdir (&user_search_path,
3696 (char *) before, search_dir) != 0)
3698 ++errors;
3700 LT_DLMUTEX_UNLOCK ();
3703 return errors;
3707 lt_dlsetsearchpath (search_path)
3708 const char *search_path;
3710 int errors = 0;
3712 LT_DLMUTEX_LOCK ();
3713 LT_DLFREE (user_search_path);
3714 LT_DLMUTEX_UNLOCK ();
3716 if (!search_path || !LT_STRLEN (search_path))
3718 return errors;
3721 LT_DLMUTEX_LOCK ();
3722 if (canonicalize_path (search_path, &user_search_path) != 0)
3723 ++errors;
3724 LT_DLMUTEX_UNLOCK ();
3726 return errors;
3729 const char *
3730 lt_dlgetsearchpath ()
3732 const char *saved_path;
3734 LT_DLMUTEX_LOCK ();
3735 saved_path = user_search_path;
3736 LT_DLMUTEX_UNLOCK ();
3738 return saved_path;
3742 lt_dlmakeresident (handle)
3743 lt_dlhandle handle;
3745 int errors = 0;
3747 if (!handle)
3749 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3750 ++errors;
3752 else
3754 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
3757 return errors;
3761 lt_dlisresident (handle)
3762 lt_dlhandle handle;
3764 if (!handle)
3766 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3767 return -1;
3770 return LT_DLIS_RESIDENT (handle);
3776 /* --- MODULE INFORMATION --- */
3778 const lt_dlinfo *
3779 lt_dlgetinfo (handle)
3780 lt_dlhandle handle;
3782 if (!handle)
3784 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3785 return 0;
3788 return &(handle->info);
3791 lt_dlhandle
3792 lt_dlhandle_next (place)
3793 lt_dlhandle place;
3795 return place ? place->next : handles;
3799 lt_dlforeach (func, data)
3800 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
3801 lt_ptr data;
3803 int errors = 0;
3804 lt_dlhandle cur;
3806 LT_DLMUTEX_LOCK ();
3808 cur = handles;
3809 while (cur)
3811 lt_dlhandle tmp = cur;
3813 cur = cur->next;
3814 if ((*func) (tmp, data))
3816 ++errors;
3817 break;
3821 LT_DLMUTEX_UNLOCK ();
3823 return errors;
3826 lt_dlcaller_id
3827 lt_dlcaller_register ()
3829 static lt_dlcaller_id last_caller_id = 0;
3830 int result;
3832 LT_DLMUTEX_LOCK ();
3833 result = ++last_caller_id;
3834 LT_DLMUTEX_UNLOCK ();
3836 return result;
3839 lt_ptr
3840 lt_dlcaller_set_data (key, handle, data)
3841 lt_dlcaller_id key;
3842 lt_dlhandle handle;
3843 lt_ptr data;
3845 int n_elements = 0;
3846 lt_ptr stale = (lt_ptr) 0;
3847 int i;
3849 /* This needs to be locked so that the caller data can be updated
3850 simultaneously by different threads. */
3851 LT_DLMUTEX_LOCK ();
3853 if (handle->caller_data)
3854 while (handle->caller_data[n_elements].key)
3855 ++n_elements;
3857 for (i = 0; i < n_elements; ++i)
3859 if (handle->caller_data[i].key == key)
3861 stale = handle->caller_data[i].data;
3862 break;
3866 /* Ensure that there is enough room in this handle's caller_data
3867 array to accept a new element (and an empty end marker). */
3868 if (i == n_elements)
3870 lt_caller_data *temp
3871 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
3873 if (!temp)
3875 stale = 0;
3876 goto done;
3879 handle->caller_data = temp;
3881 /* We only need this if we needed to allocate a new caller_data. */
3882 handle->caller_data[i].key = key;
3883 handle->caller_data[1+ i].key = 0;
3886 handle->caller_data[i].data = data;
3888 done:
3889 LT_DLMUTEX_UNLOCK ();
3891 return stale;
3894 lt_ptr
3895 lt_dlcaller_get_data (key, handle)
3896 lt_dlcaller_id key;
3897 lt_dlhandle handle;
3899 lt_ptr result = (lt_ptr) 0;
3901 /* This needs to be locked so that the caller data isn't updated by
3902 another thread part way through this function. */
3903 LT_DLMUTEX_LOCK ();
3905 /* Locate the index of the element with a matching KEY. */
3907 int i;
3908 for (i = 0; handle->caller_data[i].key; ++i)
3910 if (handle->caller_data[i].key == key)
3912 result = handle->caller_data[i].data;
3913 break;
3918 LT_DLMUTEX_UNLOCK ();
3920 return result;
3925 /* --- USER MODULE LOADER API --- */
3929 lt_dlloader_add (place, dlloader, loader_name)
3930 lt_dlloader *place;
3931 const struct lt_user_dlloader *dlloader;
3932 const char *loader_name;
3934 int errors = 0;
3935 lt_dlloader *node = 0, *ptr = 0;
3937 if ((dlloader == 0) /* diagnose null parameters */
3938 || (dlloader->module_open == 0)
3939 || (dlloader->module_close == 0)
3940 || (dlloader->find_sym == 0))
3942 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3943 return 1;
3946 /* Create a new dlloader node with copies of the user callbacks. */
3947 node = LT_EMALLOC (lt_dlloader, 1);
3948 if (!node)
3949 return 1;
3951 node->next = 0;
3952 node->loader_name = loader_name;
3953 node->sym_prefix = dlloader->sym_prefix;
3954 node->dlloader_exit = dlloader->dlloader_exit;
3955 node->module_open = dlloader->module_open;
3956 node->module_close = dlloader->module_close;
3957 node->find_sym = dlloader->find_sym;
3958 node->dlloader_data = dlloader->dlloader_data;
3960 LT_DLMUTEX_LOCK ();
3961 if (!loaders)
3963 /* If there are no loaders, NODE becomes the list! */
3964 loaders = node;
3966 else if (!place)
3968 /* If PLACE is not set, add NODE to the end of the
3969 LOADERS list. */
3970 for (ptr = loaders; ptr->next; ptr = ptr->next)
3972 /*NOWORK*/;
3975 ptr->next = node;
3977 else if (loaders == place)
3979 /* If PLACE is the first loader, NODE goes first. */
3980 node->next = place;
3981 loaders = node;
3983 else
3985 /* Find the node immediately preceding PLACE. */
3986 for (ptr = loaders; ptr->next != place; ptr = ptr->next)
3988 /*NOWORK*/;
3991 if (ptr->next != place)
3993 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3994 ++errors;
3996 else
3998 /* Insert NODE between PTR and PLACE. */
3999 node->next = place;
4000 ptr->next = node;
4004 LT_DLMUTEX_UNLOCK ();
4006 return errors;
4010 lt_dlloader_remove (loader_name)
4011 const char *loader_name;
4013 lt_dlloader *place = lt_dlloader_find (loader_name);
4014 lt_dlhandle handle;
4015 int errors = 0;
4017 if (!place)
4019 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4020 return 1;
4023 LT_DLMUTEX_LOCK ();
4025 /* Fail if there are any open modules which use this loader. */
4026 for (handle = handles; handle; handle = handle->next)
4028 if (handle->loader == place)
4030 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
4031 ++errors;
4032 goto done;
4036 if (place == loaders)
4038 /* PLACE is the first loader in the list. */
4039 loaders = loaders->next;
4041 else
4043 /* Find the loader before the one being removed. */
4044 lt_dlloader *prev;
4045 for (prev = loaders; prev->next; prev = prev->next)
4047 if (!strcmp (prev->next->loader_name, loader_name))
4049 break;
4053 place = prev->next;
4054 prev->next = prev->next->next;
4057 if (place->dlloader_exit)
4059 errors = place->dlloader_exit (place->dlloader_data);
4062 LT_DLFREE (place);
4064 done:
4065 LT_DLMUTEX_UNLOCK ();
4067 return errors;
4070 lt_dlloader *
4071 lt_dlloader_next (place)
4072 lt_dlloader *place;
4074 lt_dlloader *next;
4076 LT_DLMUTEX_LOCK ();
4077 next = place ? place->next : loaders;
4078 LT_DLMUTEX_UNLOCK ();
4080 return next;
4083 const char *
4084 lt_dlloader_name (place)
4085 lt_dlloader *place;
4087 const char *name = 0;
4089 if (place)
4091 LT_DLMUTEX_LOCK ();
4092 name = place ? place->loader_name : 0;
4093 LT_DLMUTEX_UNLOCK ();
4095 else
4097 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4100 return name;
4103 lt_user_data *
4104 lt_dlloader_data (place)
4105 lt_dlloader *place;
4107 lt_user_data *data = 0;
4109 if (place)
4111 LT_DLMUTEX_LOCK ();
4112 data = place ? &(place->dlloader_data) : 0;
4113 LT_DLMUTEX_UNLOCK ();
4115 else
4117 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
4120 return data;
4123 lt_dlloader *
4124 lt_dlloader_find (loader_name)
4125 const char *loader_name;
4127 lt_dlloader *place = 0;
4129 LT_DLMUTEX_LOCK ();
4130 for (place = loaders; place; place = place->next)
4132 if (strcmp (place->loader_name, loader_name) == 0)
4134 break;
4137 LT_DLMUTEX_UNLOCK ();
4139 return place;