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
70 # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name))
72 # define dirent direct
73 # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen)
75 # include <sys/ndir.h>
92 # define assert(arg) ((void) 0)
104 /* --- WINDOWS SUPPORT --- */
108 # define LT_GLOBAL_DATA __declspec(dllexport)
110 # define LT_GLOBAL_DATA
113 /* fopen() mode flags for reading a text file */
114 #undef LT_READTEXT_MODE
116 # define LT_READTEXT_MODE "rt"
118 # define LT_READTEXT_MODE "r"
124 /* --- MANIFEST CONSTANTS --- */
127 /* Standard libltdl search path environment variable name */
128 #undef LTDL_SEARCHPATH_VAR
129 #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH"
131 /* Standard libtool archive file extension. */
132 #undef LTDL_ARCHIVE_EXT
133 #define LTDL_ARCHIVE_EXT ".la"
135 /* max. filename length */
136 #ifndef LT_FILENAME_MAX
137 # define LT_FILENAME_MAX 1024
140 /* This is the maximum symbol size that won't require malloc/free */
141 #undef LT_SYMBOL_LENGTH
142 #define LT_SYMBOL_LENGTH 128
144 /* This accounts for the _LTX_ separator */
145 #undef LT_SYMBOL_OVERHEAD
146 #define LT_SYMBOL_OVERHEAD 5
151 /* --- MEMORY HANDLING --- */
154 /* These are the functions used internally. In addition to making
155 use of the associated function pointers above, they also perform
157 static char *lt_estrdup LT_PARAMS((const char *str));
158 static lt_ptr lt_emalloc LT_PARAMS((size_t size));
159 static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size));
161 static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size));
163 /* These are the pointers that can be changed by the caller: */
164 LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size))
165 = (lt_ptr (*) LT_PARAMS((size_t))) malloc;
166 LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size))
167 = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc;
168 LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr))
169 = (void (*) LT_PARAMS((lt_ptr))) free;
171 /* The following macros reduce the amount of typing needed to cast
175 #define LT_DLMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
176 #define LT_DLREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
177 #define LT_DLFREE(p) \
178 LT_STMT_START { if (p) (p) = (xfree (p), (lt_ptr) 0); } LT_STMT_END
180 #define LT_EMALLOC(tp, n) ((tp *) xmalloc ((n) * sizeof(tp)))
181 #define LT_EREALLOC(tp, p, n) ((tp *) xrealloc ((p), (n) * sizeof(tp)))
185 #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp)))
186 #define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp)))
187 #define LT_DLFREE(p) \
188 LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END
190 #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp)))
191 #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp)))
195 #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \
196 if ((p) != (q)) { if (p) lt_dlfree (p); (p) = (q); (q) = 0; } \
200 /* --- REPLACEMENT FUNCTIONS --- */
204 #define strdup rpl_strdup
206 static char *strdup LT_PARAMS((const char *str));
216 tmp = LT_DLMALLOC (char, 1+ strlen (str));
230 #define strcmp rpl_strcmp
232 static int strcmp LT_PARAMS((const char *str1, const char *str2));
246 for (;*str1 && *str2; ++str1, ++str2)
252 return (int)(*str1 - *str2);
260 # define strchr index
262 # define strchr rpl_strchr
264 static const char *strchr LT_PARAMS((const char *str, int ch));
273 for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p)
276 return (*p == (char)ch) ? p : 0;
280 #endif /* !HAVE_STRCHR */
286 # define strrchr rindex
288 # define strrchr rpl_strrchr
290 static const char *strrchr LT_PARAMS((const char *str, int ch));
297 const char *p, *q = 0;
299 for (p = str; *p != LT_EOS_CHAR; ++p)
313 /* NOTE: Neither bcopy nor the memcpy implementation below can
314 reliably handle copying in overlapping areas of memory. Use
315 memmove (for which there is a fallback implmentation below)
316 if you need that behaviour. */
320 # define memcpy(dest, src, size) bcopy (src, dest, size)
322 # define memcpy rpl_memcpy
324 static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
327 memcpy (dest, src, size)
334 for (i = 0; i < size; ++i)
342 # endif /* !HAVE_BCOPY */
343 #endif /* !HAVE_MEMCPY */
346 # define memmove rpl_memmove
348 static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size));
351 memmove (dest, src, size)
359 for (i = 0; i < size; ++i)
364 for (i = size -1; i >= 0; --i)
372 #endif /* !HAVE_MEMMOVE */
375 /* According to Alexandre Oliva <oliva@lsd.ic.unicamp.br>,
376 ``realloc is not entirely portable''
377 In any case we want to use the allocator supplied by the user without
378 burdening them with an lt_dlrealloc function pointer to maintain.
379 Instead implement our own version (with known boundary conditions)
380 using lt_dlmalloc and lt_dlfree. */
383 #define realloc rpl_realloc
392 /* For zero or less bytes, free the original memory */
402 /* Allow reallocation of a NULL pointer. */
403 return lt_dlmalloc (size);
407 /* Allocate a new block, copy and free the old block. */
408 lt_ptr mem = lt_dlmalloc (size);
412 memcpy (mem, ptr, size);
416 /* Note that the contents of PTR are not damaged if there is
417 insufficient memory to realloc. */
423 #if ! HAVE_ARGZ_APPEND
424 # define argz_append rpl_argz_append
426 static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len,
427 const char *buf, size_t buf_len));
430 argz_append (pargz, pargz_len, buf, buf_len)
441 assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len));
443 /* If nothing needs to be appended, no more work is required. */
447 /* Ensure there is enough room to append BUF_LEN. */
448 argz_len = *pargz_len + buf_len;
449 argz = LT_DLREALLOC (char, *pargz, argz_len);
453 /* Copy characters from BUF after terminating '\0' in ARGZ. */
454 memcpy (argz + *pargz_len, buf, buf_len);
456 /* Assign new values. */
458 *pargz_len = argz_len;
462 #endif /* !HAVE_ARGZ_APPEND */
465 #if ! HAVE_ARGZ_CREATE_SEP
466 # define argz_create_sep rpl_argz_create_sep
468 static error_t argz_create_sep LT_PARAMS((const char *str, int delim,
469 char **pargz, size_t *pargz_len));
472 argz_create_sep (str, delim, pargz, pargz_len)
485 /* Make a copy of STR, but replacing each occurence of
487 argz_len = 1+ LT_STRLEN (str);
493 argz = LT_DLMALLOC (char, argz_len);
497 for (p = str, q = argz; *p != LT_EOS_CHAR; ++p)
501 /* Ignore leading delimiters, and fold consecutive
502 delimiters in STR into a single '\0' in ARGZ. */
503 if ((q > argz) && (q[-1] != LT_EOS_CHAR))
511 /* Copy terminating LT_EOS_CHAR. */
515 /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */
519 /* Assign new values. */
521 *pargz_len = argz_len;
525 #endif /* !HAVE_ARGZ_CREATE_SEP */
528 #if ! HAVE_ARGZ_INSERT
529 # define argz_insert rpl_argz_insert
531 static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len,
532 char *before, const char *entry));
535 argz_insert (pargz, pargz_len, before, entry)
543 assert (entry && *entry);
545 /* Either PARGZ/PARGZ_LEN is empty and BEFORE is NULL,
546 or BEFORE points into an address within the ARGZ vector. */
547 assert ((!*pargz && !*pargz_len && !before)
548 || ((*pargz <= before) && (before < (*pargz + *pargz_len))));
550 /* No BEFORE address indicates ENTRY should be inserted after the
551 current last element. */
553 return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry));
555 /* This probably indicates a programmer error, but to preserve
556 semantics, scan back to the start of an entry if BEFORE points
557 into the middle of it. */
558 while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR))
562 size_t entry_len = 1+ LT_STRLEN (entry);
563 size_t argz_len = *pargz_len + entry_len;
564 size_t offset = before - *pargz;
565 char *argz = LT_DLREALLOC (char, *pargz, argz_len);
570 /* Make BEFORE point to the equivalent offset in ARGZ that it
571 used to have in *PARGZ incase realloc() moved the block. */
572 before = argz + offset;
574 /* Move the ARGZ entries starting at BEFORE up into the new
575 space at the end -- making room to copy ENTRY into the
577 memmove (before + entry_len, before, *pargz_len - offset);
578 memcpy (before, entry, entry_len);
580 /* Assign new values. */
582 *pargz_len = argz_len;
587 #endif /* !HAVE_ARGZ_INSERT */
591 # define argz_next rpl_argz_next
593 static char *argz_next LT_PARAMS((char *argz, size_t argz_len,
597 argz_next (argz, argz_len, entry)
602 assert ((argz && argz_len) || (!argz && !argz_len));
606 /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address
607 within the ARGZ vector. */
608 assert ((!argz && !argz_len)
609 || ((argz <= entry) && (entry < (argz + argz_len))));
611 /* Move to the char immediately after the terminating
613 entry = 1+ strchr (entry, LT_EOS_CHAR);
615 /* Return either the new ENTRY, or else NULL if ARGZ is
617 return (entry >= argz + argz_len) ? 0 : (char *) entry;
621 /* This should probably be flagged as a programmer error,
622 since starting an argz_next loop with the iterator set
623 to ARGZ is safer. To preserve semantics, handle the NULL
624 case by returning the start of ARGZ (if any). */
631 #endif /* !HAVE_ARGZ_NEXT */
635 #if ! HAVE_ARGZ_STRINGIFY
636 # define argz_stringify rpl_argz_stringify
638 static void argz_stringify LT_PARAMS((char *argz, size_t argz_len,
642 argz_stringify (argz, argz_len, sep)
647 assert ((argz && argz_len) || (!argz && !argz_len));
651 --argz_len; /* don't stringify the terminating EOS */
652 while (--argz_len > 0)
654 if (argz[argz_len] == LT_EOS_CHAR)
655 argz[argz_len] = sep;
659 #endif /* !HAVE_ARGZ_STRINGIFY */
664 /* --- TYPE DEFINITIONS -- */
667 /* This type is used for the array of caller data sets in each handler. */
676 /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */
679 /* Extract the diagnostic strings from the error table macro in the same
680 order as the enumerated indices in ltdl.h. */
682 static const char *lt_dlerror_strings[] =
684 #define LT_ERROR(name, diagnostic) (diagnostic),
691 /* This structure is used for the list of registered loaders. */
693 struct lt_dlloader *next;
694 const char *loader_name; /* identifying name for each loader */
695 const char *sym_prefix; /* prefix for symbols */
696 lt_module_open *module_open;
697 lt_module_close *module_close;
698 lt_find_sym *find_sym;
699 lt_dlloader_exit *dlloader_exit;
700 lt_user_data dlloader_data;
703 struct lt_dlhandle_struct {
704 struct lt_dlhandle_struct *next;
705 lt_dlloader *loader; /* dlopening interface */
707 int depcount; /* number of dependencies */
708 lt_dlhandle *deplibs; /* dependencies */
709 lt_module module; /* system module handle */
710 lt_ptr system; /* system specific data */
711 lt_caller_data *caller_data; /* per caller associated data */
712 int flags; /* various boolean stats */
715 /* Various boolean flags can be stored in the flags field of an
716 lt_dlhandle_struct... */
717 #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag))
718 #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag))
720 #define LT_DLRESIDENT_FLAG (0x01 << 0)
721 /* ...add more flags here... */
723 #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG)
726 #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)]
728 static const char objdir[] = LTDL_OBJDIR;
729 static const char archive_ext[] = LTDL_ARCHIVE_EXT;
730 #ifdef LTDL_SHLIB_EXT
731 static const char shlib_ext[] = LTDL_SHLIB_EXT;
733 #ifdef LTDL_SYSSEARCHPATH
734 static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
740 /* --- MUTEX LOCKING --- */
743 /* Macros to make it easier to run the lock functions only if they have
744 been registered. The reason for the complicated lock macro is to
745 ensure that the stored error message from the last error is not
746 accidentally erased if the current function doesn't generate an
748 #define LT_DLMUTEX_LOCK() LT_STMT_START { \
749 if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \
751 #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \
752 if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\
754 #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \
755 if (lt_dlmutex_seterror_func) \
756 (*lt_dlmutex_seterror_func) (errormsg); \
757 else lt_dllast_error = (errormsg); } LT_STMT_END
758 #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \
759 if (lt_dlmutex_seterror_func) \
760 (errormsg) = (*lt_dlmutex_geterror_func) (); \
761 else (errormsg) = lt_dllast_error; } LT_STMT_END
763 /* The mutex functions stored here are global, and are necessarily the
764 same for all threads that wish to share access to libltdl. */
765 static lt_dlmutex_lock *lt_dlmutex_lock_func = 0;
766 static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0;
767 static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0;
768 static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0;
769 static const char *lt_dllast_error = 0;
772 /* Either set or reset the mutex functions. Either all the arguments must
773 be valid functions, or else all can be NULL to turn off locking entirely.
774 The registered functions should be manipulating a static global lock
775 from the lock() and unlock() callbacks, which needs to be reentrant. */
777 lt_dlmutex_register (lock, unlock, seterror, geterror)
778 lt_dlmutex_lock *lock;
779 lt_dlmutex_unlock *unlock;
780 lt_dlmutex_seterror *seterror;
781 lt_dlmutex_geterror *geterror;
783 lt_dlmutex_unlock *old_unlock = unlock;
786 /* Lock using the old lock() callback, if any. */
789 if ((lock && unlock && seterror && geterror)
790 || !(lock || unlock || seterror || geterror))
792 lt_dlmutex_lock_func = lock;
793 lt_dlmutex_unlock_func = unlock;
794 lt_dlmutex_geterror_func = geterror;
798 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS));
802 /* Use the old unlock() callback we saved earlier, if any. Otherwise
803 record any errors using internal storage. */
807 /* Return the number of errors encountered during the execution of
815 /* --- ERROR HANDLING --- */
818 static const char **user_error_strings = 0;
819 static int errorcount = LT_ERROR_MAX;
822 lt_dladderror (diagnostic)
823 const char *diagnostic;
827 const char **temp = (const char **) 0;
833 errindex = errorcount - LT_ERROR_MAX;
834 temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex);
837 user_error_strings = temp;
838 user_error_strings[errindex] = diagnostic;
839 result = errorcount++;
842 LT_DLMUTEX_UNLOCK ();
848 lt_dlseterror (errindex)
855 if (errindex >= errorcount || errindex < 0)
857 /* Ack! Error setting the error message! */
858 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE));
861 else if (errindex < LT_ERROR_MAX)
863 /* No error setting the error message! */
864 LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]);
868 /* No error setting the error message! */
869 LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]);
872 LT_DLMUTEX_UNLOCK ();
881 lt_ptr mem = lt_dlmalloc (size);
883 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
888 lt_erealloc (addr, size)
892 lt_ptr mem = realloc (addr, size);
894 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
902 char *copy = strdup (str);
903 if (LT_STRLEN (str) && !copy)
904 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
911 /* --- DLOPEN() INTERFACE LOADER --- */
914 /* The Cygwin dlopen implementation prints a spurious error message to
915 stderr if its call to LoadLibrary() fails for any reason. We can
916 mitigate this by not using the Cygwin implementation, and falling
917 back to our own LoadLibrary() wrapper. */
918 #if HAVE_LIBDL && !defined(__CYGWIN__)
920 /* dynamic linking with dlopen/dlsym */
931 # define LT_GLOBAL RTLD_GLOBAL
934 # define LT_GLOBAL DL_GLOBAL
936 #endif /* !RTLD_GLOBAL */
939 #endif /* !LT_GLOBAL */
941 /* We may have to define LT_LAZY_OR_NOW in the command line if we
942 find out it does not work in some platform. */
943 #ifndef LT_LAZY_OR_NOW
945 # define LT_LAZY_OR_NOW RTLD_LAZY
948 # define LT_LAZY_OR_NOW DL_LAZY
950 # endif /* !RTLD_LAZY */
952 #ifndef LT_LAZY_OR_NOW
954 # define LT_LAZY_OR_NOW RTLD_NOW
957 # define LT_LAZY_OR_NOW DL_NOW
959 # endif /* !RTLD_NOW */
961 #ifndef LT_LAZY_OR_NOW
962 # define LT_LAZY_OR_NOW 0
963 #endif /* !LT_LAZY_OR_NOW */
966 # define DLERROR(arg) dlerror ()
968 # define DLERROR(arg) LT_DLSTRERROR (arg)
972 sys_dl_open (loader_data, filename)
973 lt_user_data loader_data;
974 const char *filename;
976 lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW);
980 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN));
987 sys_dl_close (loader_data, module)
988 lt_user_data loader_data;
993 if (dlclose (module) != 0)
995 LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE));
1003 sys_dl_sym (loader_data, module, symbol)
1004 lt_user_data loader_data;
1008 lt_ptr address = dlsym (module, symbol);
1012 LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND));
1018 static struct lt_user_dlloader sys_dl =
1025 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
1028 #endif /* HAVE_LIBDL */
1032 /* --- SHL_LOAD() INTERFACE LOADER --- */
1036 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
1042 /* some flags are missing on some systems, so we provide
1043 * harmless defaults.
1046 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
1047 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
1050 * BIND_FIRST - Place the library at the head of the symbol search
1052 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all
1053 * unsatisfied symbols as fatal. This flag allows
1054 * binding of unsatisfied code symbols to be deferred
1056 * [Perl: For certain libraries, like DCE, deferred
1057 * binding often causes run time problems. Adding
1058 * BIND_NONFATAL to BIND_IMMEDIATE still allows
1059 * unresolved references in situations like this.]
1060 * BIND_NOSTART - Do not call the initializer for the shared library
1061 * when the library is loaded, nor on a future call to
1063 * BIND_VERBOSE - Print verbose messages concerning possible
1064 * unsatisfied symbols.
1066 * hp9000s700/hp9000s800:
1067 * BIND_RESTRICTED - Restrict symbols visible by the library to those
1068 * present at library load time.
1069 * DYNAMIC_PATH - Allow the loader to dynamically search for the
1070 * library specified by the path argument.
1073 #ifndef DYNAMIC_PATH
1074 # define DYNAMIC_PATH 0
1076 #ifndef BIND_RESTRICTED
1077 # define BIND_RESTRICTED 0
1080 #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
1083 sys_shl_open (loader_data, filename)
1084 lt_user_data loader_data;
1085 const char *filename;
1087 static shl_t self = (shl_t) 0;
1088 lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L);
1090 /* Since searching for a symbol against a NULL module handle will also
1091 look in everything else that was already loaded and exported with
1092 the -E compiler flag, we always cache a handle saved before any
1093 modules are loaded. */
1097 shl_findsym (&self, "main", TYPE_UNDEFINED, &address);
1106 module = shl_load (filename, LT_BIND_FLAGS, 0L);
1110 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1118 sys_shl_close (loader_data, module)
1119 lt_user_data loader_data;
1124 if (module && (shl_unload ((shl_t) (module)) != 0))
1126 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1134 sys_shl_sym (loader_data, module, symbol)
1135 lt_user_data loader_data;
1141 /* sys_shl_open should never return a NULL module handle */
1142 if (module == (lt_module) 0)
1144 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
1146 else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address))
1150 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1157 static struct lt_user_dlloader sys_shl = {
1158 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0
1161 #endif /* HAVE_SHL_LOAD */
1166 /* --- LOADLIBRARY() INTERFACE LOADER --- */
1170 /* dynamic linking for Win32 */
1172 #include <windows.h>
1174 /* Forward declaration; required to implement handle search below. */
1175 static lt_dlhandle handles;
1178 sys_wll_open (loader_data, filename)
1179 lt_user_data loader_data;
1180 const char *filename;
1183 lt_module module = 0;
1184 const char *errormsg = 0;
1185 char *searchname = 0;
1187 char self_name_buf[MAX_PATH];
1191 /* Get the name of main module */
1193 GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf));
1194 filename = ext = self_name_buf;
1198 ext = strrchr (filename, '.');
1203 /* FILENAME already has an extension. */
1204 searchname = lt_estrdup (filename);
1208 /* Append a `.' to stop Windows from adding an
1209 implicit `.dll' extension. */
1210 searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename));
1212 sprintf (searchname, "%s.", filename);
1219 char wpath[MAX_PATH];
1220 cygwin_conv_to_full_win32_path(searchname, wpath);
1221 module = LoadLibrary(wpath);
1224 module = LoadLibrary (searchname);
1226 LT_DLFREE (searchname);
1228 /* libltdl expects this function to fail if it is unable
1229 to physically load the library. Sadly, LoadLibrary
1230 will search the loaded libraries for a match and return
1231 one of them if the path search load fails.
1233 We check whether LoadLibrary is returning a handle to
1234 an already loaded module, and simulate failure if we
1246 if (cur->module == module)
1253 LT_DLMUTEX_UNLOCK ();
1257 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1265 sys_wll_close (loader_data, module)
1266 lt_user_data loader_data;
1271 if (FreeLibrary(module) == 0)
1273 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1281 sys_wll_sym (loader_data, module, symbol)
1282 lt_user_data loader_data;
1286 lt_ptr address = GetProcAddress (module, symbol);
1290 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1296 static struct lt_user_dlloader sys_wll = {
1297 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0
1300 #endif /* __WINDOWS__ */
1305 /* --- LOAD_ADD_ON() INTERFACE LOADER --- */
1310 /* dynamic linking for BeOS */
1312 #include <kernel/image.h>
1315 sys_bedl_open (loader_data, filename)
1316 lt_user_data loader_data;
1317 const char *filename;
1323 image = load_add_on (filename);
1329 if (get_next_image_info (0, &cookie, &info) == B_OK)
1330 image = load_add_on (info.name);
1335 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1339 return (lt_module) image;
1343 sys_bedl_close (loader_data, module)
1344 lt_user_data loader_data;
1349 if (unload_add_on ((image_id) module) != B_OK)
1351 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1359 sys_bedl_sym (loader_data, module, symbol)
1360 lt_user_data loader_data;
1365 image_id image = (image_id) module;
1367 if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK)
1369 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1376 static struct lt_user_dlloader sys_bedl = {
1377 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0
1380 #endif /* __BEOS__ */
1385 /* --- DLD_LINK() INTERFACE LOADER --- */
1390 /* dynamic linking with dld */
1397 sys_dld_open (loader_data, filename)
1398 lt_user_data loader_data;
1399 const char *filename;
1401 lt_module module = strdup (filename);
1403 if (dld_link (filename) != 0)
1405 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN));
1414 sys_dld_close (loader_data, module)
1415 lt_user_data loader_data;
1420 if (dld_unlink_by_file ((char*)(module), 1) != 0)
1422 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE));
1434 sys_dld_sym (loader_data, module, symbol)
1435 lt_user_data loader_data;
1439 lt_ptr address = dld_get_func (symbol);
1443 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1449 static struct lt_user_dlloader sys_dld = {
1450 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0
1453 #endif /* HAVE_DLD */
1458 /* --- DLPREOPEN() INTERFACE LOADER --- */
1461 /* emulate dynamic linking using preloaded_symbols */
1463 typedef struct lt_dlsymlists_t
1465 struct lt_dlsymlists_t *next;
1466 const lt_dlsymlist *syms;
1469 static const lt_dlsymlist *default_preloaded_symbols = 0;
1470 static lt_dlsymlists_t *preloaded_symbols = 0;
1473 presym_init (loader_data)
1474 lt_user_data loader_data;
1480 preloaded_symbols = 0;
1481 if (default_preloaded_symbols)
1483 errors = lt_dlpreload (default_preloaded_symbols);
1486 LT_DLMUTEX_UNLOCK ();
1492 presym_free_symlists ()
1494 lt_dlsymlists_t *lists;
1498 lists = preloaded_symbols;
1501 lt_dlsymlists_t *tmp = lists;
1503 lists = lists->next;
1506 preloaded_symbols = 0;
1508 LT_DLMUTEX_UNLOCK ();
1514 presym_exit (loader_data)
1515 lt_user_data loader_data;
1517 presym_free_symlists ();
1522 presym_add_symlist (preloaded)
1523 const lt_dlsymlist *preloaded;
1525 lt_dlsymlists_t *tmp;
1526 lt_dlsymlists_t *lists;
1531 lists = preloaded_symbols;
1534 if (lists->syms == preloaded)
1538 lists = lists->next;
1541 tmp = LT_EMALLOC (lt_dlsymlists_t, 1);
1544 memset (tmp, 0, sizeof(lt_dlsymlists_t));
1545 tmp->syms = preloaded;
1546 tmp->next = preloaded_symbols;
1547 preloaded_symbols = tmp;
1555 LT_DLMUTEX_UNLOCK ();
1560 presym_open (loader_data, filename)
1561 lt_user_data loader_data;
1562 const char *filename;
1564 lt_dlsymlists_t *lists;
1565 lt_module module = (lt_module) 0;
1568 lists = preloaded_symbols;
1572 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS));
1576 /* Can't use NULL as the reflective symbol header, as NULL is
1577 used to mark the end of the entire symbol list. Self-dlpreopened
1578 symbols follow this magic number, chosen to be an unlikely
1579 clash with a real module name. */
1582 filename = "@PROGRAM@";
1587 const lt_dlsymlist *syms = lists->syms;
1591 if (!syms->address && strcmp(syms->name, filename) == 0)
1593 module = (lt_module) syms;
1599 lists = lists->next;
1602 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
1605 LT_DLMUTEX_UNLOCK ();
1610 presym_close (loader_data, module)
1611 lt_user_data loader_data;
1614 /* Just to silence gcc -Wall */
1620 presym_sym (loader_data, module, symbol)
1621 lt_user_data loader_data;
1625 lt_dlsymlist *syms = (lt_dlsymlist*) module;
1628 while (syms->address)
1630 if (strcmp(syms->name, symbol) == 0)
1632 return syms->address;
1638 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
1643 static struct lt_user_dlloader presym = {
1644 0, presym_open, presym_close, presym_sym, presym_exit, 0
1651 /* --- DYNAMIC MODULE LOADING --- */
1654 /* The type of a function used at each iteration of foreach_dirinpath(). */
1655 typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1,
1658 static int foreach_dirinpath LT_PARAMS((const char *search_path,
1659 const char *base_name,
1660 foreach_callback_func *func,
1661 lt_ptr data1, lt_ptr data2));
1663 static int find_file_callback LT_PARAMS((char *filename, lt_ptr data,
1665 static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data,
1667 static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1,
1671 static int canonicalize_path LT_PARAMS((const char *path,
1672 char **pcanonical));
1673 static int argzize_path LT_PARAMS((const char *path,
1675 size_t *pargz_len));
1676 static FILE *find_file LT_PARAMS((const char *search_path,
1677 const char *base_name,
1679 static lt_dlhandle *find_handle LT_PARAMS((const char *search_path,
1680 const char *base_name,
1681 lt_dlhandle *handle));
1682 static int find_module LT_PARAMS((lt_dlhandle *handle,
1686 const char *old_name,
1688 static int free_vars LT_PARAMS((char *dlname, char *oldname,
1689 char *libdir, char *deplibs));
1690 static int load_deplibs LT_PARAMS((lt_dlhandle handle,
1692 static int trim LT_PARAMS((char **dest,
1694 static int try_dlopen LT_PARAMS((lt_dlhandle *handle,
1695 const char *filename));
1696 static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle,
1697 const char *filename));
1698 static int unload_deplibs LT_PARAMS((lt_dlhandle handle));
1699 static int lt_argz_insert LT_PARAMS((char **pargz,
1702 const char *entry));
1703 static int lt_argz_insertinorder LT_PARAMS((char **pargz,
1705 const char *entry));
1706 static int lt_argz_insertdir LT_PARAMS((char **pargz,
1709 struct dirent *dp));
1710 static int lt_dlpath_insertdir LT_PARAMS((char **ppath,
1713 static int list_files_by_dir LT_PARAMS((const char *dirnam,
1715 size_t *pargz_len));
1716 static int file_not_found LT_PARAMS((void));
1718 static char *user_search_path= 0;
1719 static lt_dlloader *loaders = 0;
1720 static lt_dlhandle handles = 0;
1721 static int initialized = 0;
1723 /* Initialize libltdl. */
1731 /* Initialize only at first call. */
1732 if (++initialized == 1)
1735 user_search_path = 0; /* empty search path */
1737 #if HAVE_LIBDL && !defined(__CYGWIN__)
1738 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen");
1741 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen");
1744 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen");
1747 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen");
1750 errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld");
1752 errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload");
1754 if (presym_init (presym.dlloader_data))
1756 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER));
1759 else if (errors != 0)
1761 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED));
1766 LT_DLMUTEX_UNLOCK ();
1772 lt_dlpreload (preloaded)
1773 const lt_dlsymlist *preloaded;
1779 errors = presym_add_symlist (preloaded);
1783 presym_free_symlists();
1786 if (default_preloaded_symbols)
1788 errors = lt_dlpreload (default_preloaded_symbols);
1790 LT_DLMUTEX_UNLOCK ();
1797 lt_dlpreload_default (preloaded)
1798 const lt_dlsymlist *preloaded;
1801 default_preloaded_symbols = preloaded;
1802 LT_DLMUTEX_UNLOCK ();
1809 /* shut down libltdl */
1810 lt_dlloader *loader;
1818 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN));
1823 /* shut down only at last call. */
1824 if (--initialized == 0)
1828 while (handles && LT_DLIS_RESIDENT (handles))
1830 handles = handles->next;
1833 /* close all modules */
1834 for (level = 1; handles; ++level)
1836 lt_dlhandle cur = handles;
1837 int saw_nonresident = 0;
1841 lt_dlhandle tmp = cur;
1843 if (!LT_DLIS_RESIDENT (tmp))
1844 saw_nonresident = 1;
1845 if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level)
1847 if (lt_dlclose (tmp))
1853 /* done if only resident modules are left */
1854 if (!saw_nonresident)
1858 /* close all loaders */
1861 lt_dlloader *next = loader->next;
1862 lt_user_data data = loader->dlloader_data;
1863 if (loader->dlloader_exit && loader->dlloader_exit (data))
1868 LT_DLMEM_REASSIGN (loader, next);
1874 LT_DLMUTEX_UNLOCK ();
1879 tryall_dlopen (handle, filename)
1880 lt_dlhandle *handle;
1881 const char *filename;
1884 lt_dlloader *loader;
1885 const char *saved_error;
1888 LT_DLMUTEX_GETERROR (saved_error);
1894 /* check whether the module was already opened */
1897 /* try to dlopen the program itself? */
1898 if (!cur->info.filename && !filename)
1903 if (cur->info.filename && filename
1904 && strcmp (cur->info.filename, filename) == 0)
1914 ++cur->info.ref_count;
1922 cur->info.filename = lt_estrdup (filename);
1923 if (!cur->info.filename)
1931 cur->info.filename = 0;
1936 lt_user_data data = loader->dlloader_data;
1938 cur->module = loader->module_open (data, filename);
1940 if (cur->module != 0)
1944 loader = loader->next;
1949 LT_DLFREE (cur->info.filename);
1954 cur->loader = loader;
1955 LT_DLMUTEX_SETERROR (saved_error);
1958 LT_DLMUTEX_UNLOCK ();
1964 tryall_dlopen_module (handle, prefix, dirname, dlname)
1965 lt_dlhandle *handle;
1967 const char *dirname;
1972 size_t filename_len = 0;
1973 size_t dirname_len = LT_STRLEN (dirname);
1978 #ifdef LT_DIRSEP_CHAR
1979 /* Only canonicalized names (i.e. with DIRSEP chars already converted)
1980 should make it into this function: */
1981 assert (strchr (dirname, LT_DIRSEP_CHAR) == 0);
1984 if (dirname[dirname_len -1] == '/')
1986 filename_len = dirname_len + 1 + LT_STRLEN (dlname);
1988 /* Allocate memory, and combine DIRNAME and MODULENAME into it.
1989 The PREFIX (if any) is handled below. */
1990 filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1);
1994 sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname);
1996 /* Now that we have combined DIRNAME and MODULENAME, if there is
1997 also a PREFIX to contend with, simply recurse with the arguments
1998 shuffled. Otherwise, attempt to open FILENAME as a module. */
2001 error += tryall_dlopen_module (handle,
2002 (const char *) 0, prefix, filename);
2004 else if (tryall_dlopen (handle, filename) != 0)
2009 LT_DLFREE (filename);
2014 find_module (handle, dir, libdir, dlname, old_name, installed)
2015 lt_dlhandle *handle;
2019 const char *old_name;
2022 /* Try to open the old library first; if it was dlpreopened,
2023 we want the preopened version of it, even if a dlopenable
2024 module is available. */
2025 if (old_name && tryall_dlopen (handle, old_name) == 0)
2030 /* Try to open the dynamic library. */
2033 /* try to open the installed module */
2034 if (installed && libdir)
2036 if (tryall_dlopen_module (handle,
2037 (const char *) 0, libdir, dlname) == 0)
2041 /* try to open the not-installed module */
2044 if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0)
2048 /* maybe it was moved to another directory */
2050 if (tryall_dlopen_module (handle,
2051 (const char *) 0, dir, dlname) == 0)
2061 canonicalize_path (path, pcanonical)
2065 char *canonical = 0;
2067 assert (path && *path);
2068 assert (pcanonical);
2070 canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path));
2077 for (src = 0; path[src] != LT_EOS_CHAR; ++src)
2079 /* Path separators are not copied to the beginning or end of
2080 the destination, or if another separator would follow
2082 if (path[src] == LT_PATHSEP_CHAR)
2085 || (path[1+ src] == LT_PATHSEP_CHAR)
2086 || (path[1+ src] == LT_EOS_CHAR))
2090 /* Anything other than a directory separator is copied verbatim. */
2091 if ((path[src] != '/')
2092 #ifdef LT_DIRSEP_CHAR
2093 && (path[src] != LT_DIRSEP_CHAR)
2097 canonical[dest++] = path[src];
2099 /* Directory separators are converted and copied only if they are
2100 not at the end of a path -- i.e. before a path separator or
2102 else if ((path[1+ src] != LT_PATHSEP_CHAR)
2103 && (path[1+ src] != LT_EOS_CHAR)
2104 #ifdef LT_DIRSEP_CHAR
2105 && (path[1+ src] != LT_DIRSEP_CHAR)
2107 && (path[1+ src] != '/'))
2109 canonical[dest++] = '/';
2113 /* Add an end-of-string marker at the end. */
2114 canonical[dest] = LT_EOS_CHAR;
2117 /* Assign new value. */
2118 *pcanonical = canonical;
2124 argzize_path (path, pargz, pargz_len)
2135 if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len)))
2140 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
2143 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
2153 /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element
2154 of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns
2155 non-zero or all elements are exhausted. If BASE_NAME is non-NULL,
2156 it is appended to each SEARCH_PATH element before FUNC is called. */
2158 foreach_dirinpath (search_path, base_name, func, data1, data2)
2159 const char *search_path;
2160 const char *base_name;
2161 foreach_callback_func *func;
2166 int filenamesize = 0;
2167 size_t lenbase = LT_STRLEN (base_name);
2168 size_t argz_len = 0;
2171 char *canonical = 0;
2175 if (!search_path || !*search_path)
2177 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2181 if (canonicalize_path (search_path, &canonical) != 0)
2184 if (argzize_path (canonical, &argz, &argz_len) != 0)
2189 while ((dir_name = argz_next (argz, argz_len, dir_name)))
2191 size_t lendir = LT_STRLEN (dir_name);
2193 if (lendir +1 +lenbase >= filenamesize)
2195 LT_DLFREE (filename);
2196 filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */
2197 filename = LT_EMALLOC (char, filenamesize);
2202 strncpy (filename, dir_name, lendir);
2203 if (base_name && *base_name)
2205 if (filename[lendir -1] != '/')
2206 filename[lendir++] = '/';
2207 strcpy (filename +lendir, base_name);
2210 if ((result = (*func) (filename, data1, data2)))
2219 LT_DLFREE (canonical);
2220 LT_DLFREE (filename);
2222 LT_DLMUTEX_UNLOCK ();
2227 /* If FILEPATH can be opened, store the name of the directory component
2228 in DATA1, and the opened FILE* structure address in DATA2. Otherwise
2229 DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */
2231 find_file_callback (filename, data1, data2)
2236 char **pdir = (char **) data1;
2237 FILE **pfile = (FILE **) data2;
2240 assert (filename && *filename);
2244 if ((*pfile = fopen (filename, LT_READTEXT_MODE)))
2246 char *dirend = strrchr (filename, '/');
2248 if (dirend > filename)
2249 *dirend = LT_EOS_CHAR;
2252 *pdir = lt_estrdup (filename);
2253 is_done = (*pdir == 0) ? -1 : 1;
2260 find_file (search_path, base_name, pdir)
2261 const char *search_path;
2262 const char *base_name;
2267 foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file);
2273 find_handle_callback (filename, data, ignored)
2278 lt_dlhandle *handle = (lt_dlhandle *) data;
2279 int found = access (filename, R_OK);
2281 /* Bail out if file cannot be read... */
2285 /* Try to dlopen the file, but do not continue searching in any
2287 if (tryall_dlopen (handle, filename) != 0)
2293 /* If HANDLE was found return it, otherwise return 0. If HANDLE was
2294 found but could not be opened, *HANDLE will be set to 0. */
2295 static lt_dlhandle *
2296 find_handle (search_path, base_name, handle)
2297 const char *search_path;
2298 const char *base_name;
2299 lt_dlhandle *handle;
2304 if (!foreach_dirinpath (search_path, base_name, find_handle_callback,
2312 load_deplibs (handle, deplibs)
2316 #if LTDL_DLOPEN_DEPLIBS
2317 char *p, *save_search_path = 0;
2324 handle->depcount = 0;
2326 #if LTDL_DLOPEN_DEPLIBS
2334 if (user_search_path)
2336 save_search_path = lt_estrdup (user_search_path);
2337 if (!save_search_path)
2341 /* extract search paths and count deplibs */
2345 if (!isspace ((int) *p))
2348 while (*end && !isspace((int) *end))
2353 if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
2356 *end = 0; /* set a temporary string terminator */
2357 if (lt_dladdsearchdir(p+2))
2376 /* restore the old search path */
2377 LT_DLFREE (user_search_path);
2378 user_search_path = save_search_path;
2380 LT_DLMUTEX_UNLOCK ();
2388 names = LT_EMALLOC (char *, depcount * sizeof (char*));
2392 /* now only extract the actual deplibs */
2397 if (isspace ((unsigned char) *p))
2404 while (*end && !isspace ((unsigned char) *end))
2409 if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0)
2413 *end = 0; /* set a temporary string terminator */
2414 if (strncmp(p, "-l", 2) == 0)
2416 size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2);
2417 name = LT_EMALLOC (char, 1+ name_len);
2419 sprintf (name, "lib%s", p+2);
2422 name = lt_estrdup(p);
2427 names[depcount++] = name;
2434 /* load the deplibs (in reverse order)
2435 At this stage, don't worry if the deplibs do not load correctly,
2436 they may already be statically linked into the loading application
2437 for instance. There will be a more enlightening error message
2438 later on if the loaded module cannot resolve all of its symbols. */
2443 handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount);
2444 if (!handle->deplibs)
2447 for (i = 0; i < depcount; ++i)
2449 handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]);
2450 if (handle->deplibs[j])
2456 handle->depcount = j; /* Number of successfully loaded deplibs */
2461 for (i = 0; i < depcount; ++i)
2463 LT_DLFREE (names[i]);
2474 unload_deplibs (handle)
2480 if (handle->depcount)
2482 for (i = 0; i < handle->depcount; ++i)
2484 if (!LT_DLIS_RESIDENT (handle->deplibs[i]))
2486 errors += lt_dlclose (handle->deplibs[i]);
2499 /* remove the leading and trailing "'" from str
2500 and store the result in dest */
2501 const char *end = strrchr (str, '\'');
2502 size_t len = LT_STRLEN (str);
2507 if (len > 3 && str[0] == '\'')
2509 tmp = LT_EMALLOC (char, end - str);
2513 strncpy(tmp, &str[1], (end - str) - 1);
2514 tmp[len-3] = LT_EOS_CHAR;
2526 free_vars (dlname, oldname, libdir, deplibs)
2533 LT_DLFREE (oldname);
2535 LT_DLFREE (deplibs);
2541 try_dlopen (phandle, filename)
2542 lt_dlhandle *phandle;
2543 const char *filename;
2545 const char * ext = 0;
2546 const char * saved_error = 0;
2547 char * canonical = 0;
2548 char * base_name = 0;
2552 lt_dlhandle newhandle;
2555 assert (*phandle == 0);
2557 LT_DLMUTEX_GETERROR (saved_error);
2562 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2566 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
2567 newhandle = *phandle;
2569 /* lt_dlclose()ing yourself is very bad! Disallow it. */
2570 LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG);
2572 if (tryall_dlopen (&newhandle, 0) != 0)
2574 LT_DLFREE (*phandle);
2578 goto register_handle;
2581 assert (filename && *filename);
2583 /* Doing this immediately allows internal functions to safely
2584 assume only canonicalized paths are passed. */
2585 if (canonicalize_path (filename, &canonical) != 0)
2591 /* If the canonical module name is a path (relative or absolute)
2592 then split it into a directory part and a name part. */
2593 base_name = strrchr (canonical, '/');
2596 size_t dirlen = (1+ base_name) - canonical;
2598 dir = LT_EMALLOC (char, 1+ dirlen);
2605 strncpy (dir, canonical, dirlen);
2606 dir[dirlen] = LT_EOS_CHAR;
2611 LT_DLMEM_REASSIGN (base_name, canonical);
2613 assert (base_name && *base_name);
2615 /* Check whether we are opening a libtool module (.la extension). */
2616 ext = strrchr (base_name, '.');
2617 if (ext && strcmp (ext, archive_ext) == 0)
2619 /* this seems to be a libtool module */
2622 char * old_name = 0;
2628 /* if we can't find the installed flag, it is probably an
2629 installed libtool archive, produced with an old version
2633 /* extract the module name from the file name */
2634 name = LT_EMALLOC (char, ext - base_name + 1);
2641 /* canonicalize the module name */
2644 for (i = 0; i < ext - base_name; ++i)
2646 if (isalnum ((unsigned char)(base_name[i])))
2648 name[i] = base_name[i];
2655 name[ext - base_name] = LT_EOS_CHAR;
2658 /* Now try to open the .la file. If there is no directory name
2659 component, try to find it first in user_search_path and then other
2660 prescribed paths. Otherwise (or in any case if the module was not
2661 yet found) try opening just the module name as passed. */
2664 const char *search_path;
2667 search_path = user_search_path;
2669 file = find_file (user_search_path, base_name, &dir);
2670 LT_DLMUTEX_UNLOCK ();
2674 search_path = getenv (LTDL_SEARCHPATH_VAR);
2676 file = find_file (search_path, base_name, &dir);
2679 #ifdef LTDL_SHLIBPATH_VAR
2682 search_path = getenv (LTDL_SHLIBPATH_VAR);
2684 file = find_file (search_path, base_name, &dir);
2687 #ifdef LTDL_SYSSEARCHPATH
2688 if (!file && sys_search_path)
2690 file = find_file (sys_search_path, base_name, &dir);
2696 file = fopen (filename, LT_READTEXT_MODE);
2699 /* If we didn't find the file by now, it really isn't there. Set
2700 the status flag, and bail out. */
2703 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
2708 line_len = LT_FILENAME_MAX;
2709 line = LT_EMALLOC (char, line_len);
2717 /* read the .la file */
2718 while (!feof (file))
2720 if (!fgets (line, (int) line_len, file))
2725 /* Handle the case where we occasionally need to read a line
2726 that is longer than the initial buffer size. */
2727 while (line[LT_STRLEN(line) -1] != '\n')
2729 line = LT_DLREALLOC (char, line, line_len *2);
2730 if (!fgets (&line[line_len -1], (int) line_len +1, file))
2737 if (line[0] == '\n' || line[0] == '#')
2743 #define STR_DLNAME "dlname="
2744 if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0)
2746 errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]);
2749 #undef STR_OLD_LIBRARY
2750 #define STR_OLD_LIBRARY "old_library="
2751 else if (strncmp (line, STR_OLD_LIBRARY,
2752 sizeof (STR_OLD_LIBRARY) - 1) == 0)
2754 errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]);
2757 #define STR_LIBDIR "libdir="
2758 else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0)
2760 errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]);
2763 #undef STR_DL_DEPLIBS
2764 #define STR_DL_DEPLIBS "dependency_libs="
2765 else if (strncmp (line, STR_DL_DEPLIBS,
2766 sizeof (STR_DL_DEPLIBS) - 1) == 0)
2768 errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]);
2770 else if (strcmp (line, "installed=yes\n") == 0)
2774 else if (strcmp (line, "installed=no\n") == 0)
2779 #undef STR_LIBRARY_NAMES
2780 #define STR_LIBRARY_NAMES "library_names="
2781 else if (! dlname && strncmp (line, STR_LIBRARY_NAMES,
2782 sizeof (STR_LIBRARY_NAMES) - 1) == 0)
2785 errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]);
2788 && (last_libname = strrchr (dlname, ' ')) != 0)
2790 last_libname = lt_estrdup (last_libname + 1);
2796 LT_DLMEM_REASSIGN (dlname, last_libname);
2807 /* allocate the handle */
2808 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2814 free_vars (dlname, old_name, libdir, deplibs);
2815 LT_DLFREE (*phandle);
2821 memset (*phandle, 0, sizeof(struct lt_dlhandle_struct));
2822 if (load_deplibs (*phandle, deplibs) == 0)
2824 newhandle = *phandle;
2825 /* find_module may replace newhandle */
2826 if (find_module (&newhandle, dir, libdir, dlname, old_name, installed))
2828 unload_deplibs (*phandle);
2837 free_vars (dlname, old_name, libdir, deplibs);
2840 LT_DLFREE (*phandle);
2844 if (*phandle != newhandle)
2846 unload_deplibs (*phandle);
2851 /* not a libtool module */
2852 *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1);
2859 memset (*phandle, 0, sizeof (struct lt_dlhandle_struct));
2860 newhandle = *phandle;
2862 /* If the module has no directory name component, try to find it
2863 first in user_search_path and then other prescribed paths.
2864 Otherwise (or in any case if the module was not yet found) try
2865 opening just the module name as passed. */
2866 if ((dir || (!find_handle (user_search_path, base_name, &newhandle)
2867 && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name,
2869 #ifdef LTDL_SHLIBPATH_VAR
2870 && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name,
2873 #ifdef LTDL_SYSSEARCHPATH
2874 && !find_handle (sys_search_path, base_name, &newhandle)
2878 tryall_dlopen (&newhandle, filename);
2883 LT_DLFREE (*phandle);
2890 LT_DLMEM_REASSIGN (*phandle, newhandle);
2892 if ((*phandle)->info.ref_count == 0)
2894 (*phandle)->info.ref_count = 1;
2895 LT_DLMEM_REASSIGN ((*phandle)->info.name, name);
2898 (*phandle)->next = handles;
2900 LT_DLMUTEX_UNLOCK ();
2903 LT_DLMUTEX_SETERROR (saved_error);
2908 LT_DLFREE (canonical);
2914 lt_dlopen (filename)
2915 const char *filename;
2917 lt_dlhandle handle = 0;
2919 /* Just incase we missed a code path in try_dlopen() that reports
2920 an error, but forgets to reset handle... */
2921 if (try_dlopen (&handle, filename) != 0)
2927 /* If the last error messge store was `FILE_NOT_FOUND', then return
2932 const char *error = 0;
2934 LT_DLMUTEX_GETERROR (error);
2935 if (error == LT_DLSTRERROR (FILE_NOT_FOUND))
2941 /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to
2942 open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT,
2943 and if a file is still not found try again with SHLIB_EXT appended
2946 lt_dlopenext (filename)
2947 const char *filename;
2949 lt_dlhandle handle = 0;
2957 return lt_dlopen (filename);
2962 len = LT_STRLEN (filename);
2963 ext = strrchr (filename, '.');
2965 /* If FILENAME already bears a suitable extension, there is no need
2966 to try appending additional extensions. */
2967 if (ext && ((strcmp (ext, archive_ext) == 0)
2968 #ifdef LTDL_SHLIB_EXT
2969 || (strcmp (ext, shlib_ext) == 0)
2973 return lt_dlopen (filename);
2976 /* First try appending ARCHIVE_EXT. */
2977 tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1);
2981 strcpy (tmp, filename);
2982 strcat (tmp, archive_ext);
2983 errors = try_dlopen (&handle, tmp);
2985 /* If we found FILENAME, stop searching -- whether we were able to
2986 load the file as a module or not. If the file exists but loading
2987 failed, it is better to return an error message here than to
2988 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
2989 in the module search path. */
2990 if (handle || ((errors > 0) && file_not_found ()))
2996 #ifdef LTDL_SHLIB_EXT
2997 /* Try appending SHLIB_EXT. */
2998 if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext))
3001 tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1);
3005 strcpy (tmp, filename);
3009 tmp[len] = LT_EOS_CHAR;
3012 strcat(tmp, shlib_ext);
3013 errors = try_dlopen (&handle, tmp);
3015 /* As before, if the file was found but loading failed, return now
3016 with the current error message. */
3017 if (handle || ((errors > 0) && file_not_found ()))
3024 /* Still here? Then we really did fail to locate any of the file
3026 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND));
3033 lt_argz_insert (pargz, pargz_len, before, entry)
3041 if ((error = argz_insert (pargz, pargz_len, before, entry)))
3046 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY));
3049 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN));
3059 lt_argz_insertinorder (pargz, pargz_len, entry)
3068 assert (entry && *entry);
3071 while ((before = argz_next (*pargz, *pargz_len, before)))
3073 int cmp = strcmp (entry, before);
3076 if (cmp == 0) return 0; /* No duplicates! */
3079 return lt_argz_insert (pargz, pargz_len, before, entry);
3083 lt_argz_insertdir (pargz, pargz_len, dirnam, dp)
3092 size_t end_offset = 0;
3100 dir_len = LT_STRLEN (dirnam);
3101 end = dp->d_name + LT_D_NAMLEN(dp);
3103 /* Ignore version numbers. */
3106 for (p = end; p -1 > dp->d_name; --p)
3107 if (strchr (".0123456789", p[-1]) == 0)
3114 /* Ignore filename extension. */
3117 for (p = end -1; p > dp->d_name; --p)
3125 /* Prepend the directory name. */
3126 end_offset = end - dp->d_name;
3127 buf_len = dir_len + 1+ end_offset;
3128 buf = LT_EMALLOC (char, 1+ buf_len);
3134 strcpy (buf, dirnam);
3136 strncat (buf, dp->d_name, end_offset);
3137 buf[buf_len] = LT_EOS_CHAR;
3139 /* Try to insert (in order) into ARGZ/ARGZ_LEN. */
3140 if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0)
3149 list_files_by_dir (dirnam, pargz, pargz_len)
3157 assert (dirnam && *dirnam);
3160 assert (dirnam[LT_STRLEN(dirnam) -1] != '/');
3162 dirp = opendir (dirnam);
3165 struct dirent *dp = 0;
3167 while ((dp = readdir (dirp)))
3168 if (dp->d_name[0] != '.')
3169 if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp))
3184 /* If there are any files in DIRNAME, call the function passed in
3185 DATA1 (with the name of each file and DATA2 as arguments). */
3187 foreachfile_callback (dirname, data1, data2)
3192 int (*func) LT_PARAMS((const char *filename, lt_ptr data))
3193 = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1;
3197 size_t argz_len = 0;
3199 if (list_files_by_dir (dirname, &argz, &argz_len) != 0)
3206 while ((filename = argz_next (argz, argz_len, filename)))
3207 if ((is_done = (*func) (filename, data2)))
3218 /* Call FUNC for each unique extensionless file in SEARCH_PATH, along
3219 with DATA. The filenames passed to FUNC would be suitable for
3220 passing to lt_dlopenext. The extensions are stripped so that
3221 individual modules do not generate several entries (e.g. libfoo.la,
3222 libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL,
3223 then the same directories that lt_dlopen would search are examined. */
3225 lt_dlforeachfile (search_path, func, data)
3226 const char *search_path;
3227 int (*func) LT_PARAMS ((const char *filename, lt_ptr data));
3234 /* If a specific path was passed, search only the directories
3236 is_done = foreach_dirinpath (search_path, 0,
3237 foreachfile_callback, func, data);
3241 /* Otherwise search the default paths. */
3242 is_done = foreach_dirinpath (user_search_path, 0,
3243 foreachfile_callback, func, data);
3246 is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0,
3247 foreachfile_callback, func, data);
3250 #ifdef LTDL_SHLIBPATH_VAR
3253 is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0,
3254 foreachfile_callback, func, data);
3257 #ifdef LTDL_SYSSEARCHPATH
3260 is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0,
3261 foreachfile_callback, func, data);
3273 lt_dlhandle cur, last;
3278 /* check whether the handle is valid */
3279 last = cur = handles;
3280 while (cur && handle != cur)
3288 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3293 handle->info.ref_count--;
3295 /* Note that even with resident modules, we must track the ref_count
3296 correctly incase the user decides to reset the residency flag
3297 later (even though the API makes no provision for that at the
3299 if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle))
3301 lt_user_data data = handle->loader->dlloader_data;
3303 if (handle != handles)
3305 last->next = handle->next;
3309 handles = handle->next;
3312 errors += handle->loader->module_close (data, handle->module);
3313 errors += unload_deplibs(handle);
3315 /* It is up to the callers to free the data itself. */
3316 LT_DLFREE (handle->caller_data);
3318 LT_DLFREE (handle->info.filename);
3319 LT_DLFREE (handle->info.name);
3325 if (LT_DLIS_RESIDENT (handle))
3327 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE));
3332 LT_DLMUTEX_UNLOCK ();
3338 lt_dlsym (handle, symbol)
3343 char lsym[LT_SYMBOL_LENGTH];
3350 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3356 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND));
3360 lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix)
3361 + LT_STRLEN (handle->info.name);
3363 if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH)
3369 sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1);
3372 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW));
3377 data = handle->loader->dlloader_data;
3378 if (handle->info.name)
3380 const char *saved_error;
3382 LT_DLMUTEX_GETERROR (saved_error);
3384 /* this is a libtool module */
3385 if (handle->loader->sym_prefix)
3387 strcpy(sym, handle->loader->sym_prefix);
3388 strcat(sym, handle->info.name);
3392 strcpy(sym, handle->info.name);
3395 strcat(sym, "_LTX_");
3396 strcat(sym, symbol);
3398 /* try "modulename_LTX_symbol" */
3399 address = handle->loader->find_sym (data, handle->module, sym);
3408 LT_DLMUTEX_SETERROR (saved_error);
3411 /* otherwise try "symbol" */
3412 if (handle->loader->sym_prefix)
3414 strcpy(sym, handle->loader->sym_prefix);
3415 strcat(sym, symbol);
3419 strcpy(sym, symbol);
3422 address = handle->loader->find_sym (data, handle->module, sym);
3436 LT_DLMUTEX_GETERROR (error);
3437 LT_DLMUTEX_SETERROR (0);
3439 return error ? error : LT_DLSTRERROR (UNKNOWN);
3443 lt_dlpath_insertdir (ppath, before, dir)
3449 char *canonical = 0;
3451 size_t argz_len = 0;
3454 assert (dir && *dir);
3456 if (canonicalize_path (dir, &canonical) != 0)
3462 assert (canonical && *canonical);
3464 /* If *PPATH is empty, set it to DIR. */
3467 assert (!before); /* BEFORE cannot be set without PPATH. */
3468 assert (dir); /* Without DIR, don't call this function! */
3470 *ppath = lt_estrdup (dir);
3477 assert (ppath && *ppath);
3479 if (argzize_path (*ppath, &argz, &argz_len) != 0)
3485 /* Convert BEFORE into an equivalent offset into ARGZ. This only works
3486 if *PPATH is already canonicalized, and hence does not change length
3487 with respect to ARGZ. We canonicalize each entry as it is added to
3488 the search path, and don't call this function with (uncanonicalized)
3489 user paths, so this is a fair assumption. */
3492 assert (*ppath <= before);
3493 assert (before - *ppath <= strlen (*ppath));
3495 before = before - *ppath + argz;
3498 if (lt_argz_insert (&argz, &argz_len, before, dir) != 0)
3504 argz_stringify (argz, argz_len, LT_PATHSEP_CHAR);
3505 LT_DLMEM_REASSIGN (*ppath, argz);
3508 LT_DLFREE (canonical);
3515 lt_dladdsearchdir (search_dir)
3516 const char *search_dir;
3520 if (search_dir && *search_dir)
3523 if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
3525 LT_DLMUTEX_UNLOCK ();
3532 lt_dlinsertsearchdir (before, search_dir)
3534 const char *search_dir;
3541 if ((before < user_search_path)
3542 || (before >= user_search_path + LT_STRLEN (user_search_path)))
3544 LT_DLMUTEX_UNLOCK ();
3545 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION));
3548 LT_DLMUTEX_UNLOCK ();
3551 if (search_dir && *search_dir)
3554 if (lt_dlpath_insertdir (&user_search_path,
3555 (char *) before, search_dir) != 0)
3559 LT_DLMUTEX_UNLOCK ();
3566 lt_dlsetsearchpath (search_path)
3567 const char *search_path;
3572 LT_DLFREE (user_search_path);
3573 LT_DLMUTEX_UNLOCK ();
3575 if (!search_path || !LT_STRLEN (search_path))
3581 if (canonicalize_path (search_path, &user_search_path) != 0)
3583 LT_DLMUTEX_UNLOCK ();
3589 lt_dlgetsearchpath ()
3591 const char *saved_path;
3594 saved_path = user_search_path;
3595 LT_DLMUTEX_UNLOCK ();
3601 lt_dlmakeresident (handle)
3608 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3613 LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG);
3620 lt_dlisresident (handle)
3625 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3629 return LT_DLIS_RESIDENT (handle);
3635 /* --- MODULE INFORMATION --- */
3638 lt_dlgetinfo (handle)
3643 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE));
3647 return &(handle->info);
3651 lt_dlhandle_next (place)
3654 return place ? place->next : handles;
3658 lt_dlforeach (func, data)
3659 int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data));
3670 lt_dlhandle tmp = cur;
3673 if ((*func) (tmp, data))
3680 LT_DLMUTEX_UNLOCK ();
3686 lt_dlcaller_register ()
3688 static lt_dlcaller_id last_caller_id = 0;
3692 result = ++last_caller_id;
3693 LT_DLMUTEX_UNLOCK ();
3699 lt_dlcaller_set_data (key, handle, data)
3705 lt_ptr stale = (lt_ptr) 0;
3708 /* This needs to be locked so that the caller data can be updated
3709 simultaneously by different threads. */
3712 if (handle->caller_data)
3713 while (handle->caller_data[n_elements].key)
3716 for (i = 0; i < n_elements; ++i)
3718 if (handle->caller_data[i].key == key)
3720 stale = handle->caller_data[i].data;
3725 /* Ensure that there is enough room in this handle's caller_data
3726 array to accept a new element (and an empty end marker). */
3727 if (i == n_elements)
3729 lt_caller_data *temp
3730 = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements);
3738 handle->caller_data = temp;
3740 /* We only need this if we needed to allocate a new caller_data. */
3741 handle->caller_data[i].key = key;
3742 handle->caller_data[1+ i].key = 0;
3745 handle->caller_data[i].data = data;
3748 LT_DLMUTEX_UNLOCK ();
3754 lt_dlcaller_get_data (key, handle)
3758 lt_ptr result = (lt_ptr) 0;
3760 /* This needs to be locked so that the caller data isn't updated by
3761 another thread part way through this function. */
3764 /* Locate the index of the element with a matching KEY. */
3767 for (i = 0; handle->caller_data[i].key; ++i)
3769 if (handle->caller_data[i].key == key)
3771 result = handle->caller_data[i].data;
3777 LT_DLMUTEX_UNLOCK ();
3784 /* --- USER MODULE LOADER API --- */
3788 lt_dlloader_add (place, dlloader, loader_name)
3790 const struct lt_user_dlloader *dlloader;
3791 const char *loader_name;
3794 lt_dlloader *node = 0, *ptr = 0;
3796 if ((dlloader == 0) /* diagnose null parameters */
3797 || (dlloader->module_open == 0)
3798 || (dlloader->module_close == 0)
3799 || (dlloader->find_sym == 0))
3801 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3805 /* Create a new dlloader node with copies of the user callbacks. */
3806 node = LT_EMALLOC (lt_dlloader, 1);
3811 node->loader_name = loader_name;
3812 node->sym_prefix = dlloader->sym_prefix;
3813 node->dlloader_exit = dlloader->dlloader_exit;
3814 node->module_open = dlloader->module_open;
3815 node->module_close = dlloader->module_close;
3816 node->find_sym = dlloader->find_sym;
3817 node->dlloader_data = dlloader->dlloader_data;
3822 /* If there are no loaders, NODE becomes the list! */
3827 /* If PLACE is not set, add NODE to the end of the
3829 for (ptr = loaders; ptr->next; ptr = ptr->next)
3836 else if (loaders == place)
3838 /* If PLACE is the first loader, NODE goes first. */
3844 /* Find the node immediately preceding PLACE. */
3845 for (ptr = loaders; ptr->next != place; ptr = ptr->next)
3850 if (ptr->next != place)
3852 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3857 /* Insert NODE between PTR and PLACE. */
3863 LT_DLMUTEX_UNLOCK ();
3869 lt_dlloader_remove (loader_name)
3870 const char *loader_name;
3872 lt_dlloader *place = lt_dlloader_find (loader_name);
3878 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3884 /* Fail if there are any open modules which use this loader. */
3885 for (handle = handles; handle; handle = handle->next)
3887 if (handle->loader == place)
3889 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER));
3895 if (place == loaders)
3897 /* PLACE is the first loader in the list. */
3898 loaders = loaders->next;
3902 /* Find the loader before the one being removed. */
3904 for (prev = loaders; prev->next; prev = prev->next)
3906 if (!strcmp (prev->next->loader_name, loader_name))
3913 prev->next = prev->next->next;
3916 if (place->dlloader_exit)
3918 errors = place->dlloader_exit (place->dlloader_data);
3924 LT_DLMUTEX_UNLOCK ();
3930 lt_dlloader_next (place)
3936 next = place ? place->next : loaders;
3937 LT_DLMUTEX_UNLOCK ();
3943 lt_dlloader_name (place)
3946 const char *name = 0;
3951 name = place ? place->loader_name : 0;
3952 LT_DLMUTEX_UNLOCK ();
3956 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3963 lt_dlloader_data (place)
3966 lt_user_data *data = 0;
3971 data = place ? &(place->dlloader_data) : 0;
3972 LT_DLMUTEX_UNLOCK ();
3976 LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER));
3983 lt_dlloader_find (loader_name)
3984 const char *loader_name;
3986 lt_dlloader *place = 0;
3989 for (place = loaders; place; place = place->next)
3991 if (strcmp (place->loader_name, loader_name) == 0)
3996 LT_DLMUTEX_UNLOCK ();