1 /* ltdl.c -- system independent dlopen wrapper
2 Copyright (C) 1998-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
28 #define _LTDL_COMPILE_
65 # define LTDL_GLOBAL_DATA __declspec(dllexport)
67 # define LTDL_GLOBAL_DATA
70 /* max. filename length */
71 #ifndef LTDL_FILENAME_MAX
72 #define LTDL_FILENAME_MAX 1024
75 #undef LTDL_READTEXT_MODE
76 /* fopen() mode flags for reading a text file */
77 #if defined(_WIN32) && !defined(__CYGWIN__)
78 #define LTDL_READTEXT_MODE "rt"
80 #define LTDL_READTEXT_MODE "r"
83 #undef LTDL_SYMBOL_LENGTH
84 /* This is the maximum symbol size that won't require malloc/free */
85 #define LTDL_SYMBOL_LENGTH 128
87 #undef LTDL_SYMBOL_OVERHEAD
88 /* This accounts for the _LTX_ separator */
89 #define LTDL_SYMBOL_OVERHEAD 5
91 /* NOTE: typedefed in ltdl.h
92 This structure is used for the list of registered loaders. */
93 struct lt_dlloader_t {
94 struct lt_dlloader_t *next;
95 const char *loader_name; /* identifying name for each loader */
96 const char *sym_prefix; /* prefix for symbols */
97 lt_module_open_t *module_open;
98 lt_module_close_t *module_close;
99 lt_find_sym_t *find_sym;
100 lt_dlloader_exit_t *dlloader_exit;
101 lt_dlloader_data_t dlloader_data;
104 typedef struct lt_dlhandle_t {
105 struct lt_dlhandle_t *next;
106 lt_dlloader_t *loader; /* dlopening interface */
108 int depcount; /* number of dependencies */
109 lt_dlhandle *deplibs; /* dependencies */
110 lt_module_t module; /* system module handle */
111 lt_ptr_t system; /* system specific data */
112 lt_ptr_t app_private; /* application private data */
115 static const char objdir[] = LTDL_OBJDIR;
116 #ifdef LTDL_SHLIB_EXT
117 static const char shlib_ext[] = LTDL_SHLIB_EXT;
119 #ifdef LTDL_SYSSEARCHPATH
120 static const char sys_search_path[] = LTDL_SYSSEARCHPATH;
123 /* Extract the diagnostic strings from the error table macro in the same
124 order as the enumberated indices in ltdl.h. */
125 #define LTDL_ERROR(name, diagnostic) (diagnostic),
126 static const char *ltdl_error_strings[] = {
133 # define LT_DLSTRERROR(name) ltdl_error_strings[LTDL_ERROR_##name]
135 # define LT_DLSTRERROR(name) ltdl_error_strings[LTDL_ERROR_/**/name]
138 static const char *last_error = 0;
140 LTDL_GLOBAL_DATA lt_ptr_t (*lt_dlmalloc) LTDL_PARAMS((size_t size)) = (lt_ptr_t(*)LTDL_PARAMS((size_t)))malloc;
141 LTDL_GLOBAL_DATA void (*lt_dlfree) LTDL_PARAMS((lt_ptr_t ptr)) = (void(*)LTDL_PARAMS((lt_ptr_t)))free;
144 #define strdup xstrdup
154 tmp = (char*) lt_dlmalloc(strlen(str)+1);
163 #define strcmp xstrcmp
177 for (;*str1 && *str2; str1++, str2++)
181 return (int)(*str1 - *str2);
190 # define strchr index
194 # define strchr xstrchr
196 static inline const char*
203 for (p = str; *p != (char)ch && *p != '\0'; p++)
206 return (*p == (char)ch) ? p : 0;
217 # define strrchr rindex
221 # define strrchr xstrrchr
223 static inline const char*
230 for (p = str; *p != '\0'; p++)
233 while (*p != (char)ch && p >= str)
236 return (*p == (char)ch) ? p : 0;
243 /* The Cygwin dlopen implementation prints a spurious error message to
244 stderr if its call to LoadLibrary() fails for any reason. We can
245 mitigate this by not using the Cygwin implementation, and falling
246 back to our own LoadLibrary() wrapper. */
249 /* dynamic linking with dlopen/dlsym */
256 # define LTDL_GLOBAL RTLD_GLOBAL
259 # define LTDL_GLOBAL DL_GLOBAL
261 # define LTDL_GLOBAL 0
265 /* We may have to define LTDL_LAZY_OR_NOW in the command line if we
266 find out it does not work in some platform. */
267 #ifndef LTDL_LAZY_OR_NOW
269 # define LTDL_LAZY_OR_NOW RTLD_LAZY
272 # define LTDL_LAZY_OR_NOW DL_LAZY
275 # define LTDL_LAZY_OR_NOW RTLD_NOW
278 # define LTDL_LAZY_OR_NOW DL_NOW
280 # define LTDL_LAZY_OR_NOW 0
289 sys_dl_open (loader_data, filename)
290 lt_dlloader_data_t loader_data;
291 const char *filename;
293 lt_module_t module = dlopen(filename, LTDL_GLOBAL | LTDL_LAZY_OR_NOW);
296 last_error = dlerror();
298 last_error = LT_DLSTRERROR(CANNOT_OPEN);
306 sys_dl_close (loader_data, module)
307 lt_dlloader_data_t loader_data;
310 if (dlclose(module) != 0) {
312 last_error = dlerror();
314 last_error = LT_DLSTRERROR(CANNOT_CLOSE);
323 sys_dl_sym (loader_data, module, symbol)
324 lt_dlloader_data_t loader_data;
328 lt_ptr_t address = dlsym(module, symbol);
332 last_error = dlerror();
334 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
339 static struct lt_user_dlloader sys_dl = {
345 sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 };
350 /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */
356 /* some flags are missing on some systems, so we provide
360 * BIND_IMMEDIATE - Resolve symbol references when the library is loaded.
361 * BIND_DEFERRED - Delay code symbol resolution until actual reference.
364 * BIND_FIRST - Place the library at the head of the symbol search order.
365 * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all unsatisfied
366 * symbols as fatal. This flag allows binding of unsatisfied code
367 * symbols to be deferred until use.
368 * [Perl: For certain libraries, like DCE, deferred binding often
369 * causes run time problems. Adding BIND_NONFATAL to BIND_IMMEDIATE
370 * still allows unresolved references in situations like this.]
371 * BIND_NOSTART - Do not call the initializer for the shared library when the
372 * library is loaded, nor on a future call to shl_unload().
373 * BIND_VERBOSE - Print verbose messages concerning possible unsatisfied symbols.
375 * hp9000s700/hp9000s800:
376 * BIND_RESTRICTED - Restrict symbols visible by the library to those present at
378 * DYNAMIC_PATH - Allow the loader to dynamically search for the library specified
379 * by the path argument.
383 #define DYNAMIC_PATH 0
384 #endif /* DYNAMIC_PATH */
385 #ifndef BIND_RESTRICTED
386 #define BIND_RESTRICTED 0
387 #endif /* BIND_RESTRICTED */
389 #define LTDL_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH)
393 sys_shl_open (loader_data, filename)
394 lt_dlloader_data_t loader_data;
395 const char *filename;
397 lt_module_t module = shl_load(filename, LTDL_BIND_FLAGS, 0L);
399 last_error = LT_DLSTRERROR(CANNOT_OPEN);
406 sys_shl_close (loader_data, module)
407 lt_dlloader_data_t loader_data;
410 if (shl_unload((shl_t) (module)) != 0) {
411 last_error = LT_DLSTRERROR(CANNOT_CLOSE);
419 sys_shl_sym (loader_data, module, symbol)
420 lt_dlloader_data_t loader_data;
426 if (module && shl_findsym((shl_t*) &module,
427 symbol, TYPE_UNDEFINED, &address) == 0)
430 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
434 static struct lt_user_dlloader
435 sys_shl = { 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 };
438 #define LTDL_TYPE_TOP &sys_shl
442 #if defined(_WIN32) && !defined(__CYGWIN__)
444 /* dynamic linking for Win32 */
448 /* Forward declaration; required to implement handle search below. */
449 static lt_dlhandle handles;
453 sys_wll_open (loader_data, filename)
454 lt_dlloader_data_t loader_data;
455 const char *filename;
459 char *searchname = 0;
463 last_error = LT_DLSTRERROR(CANNOT_OPEN);
467 ext = strrchr(filename, '.');
470 /* FILENAME already has an extension. */
471 searchname = strdup(filename);
473 /* Append a `.' to stop Windows from adding an
474 implicit `.dll' extension. */
475 searchname = (char*)lt_dlmalloc(2+ strlen(filename));
477 last_error = LT_DLSTRERROR(NO_MEMORY);
480 strcpy(searchname, filename);
481 strcat(searchname, ".");
484 module = LoadLibrary(searchname);
485 lt_dlfree(searchname);
487 /* libltdl expects this function to fail if it is unable
488 to physically load the library. Sadly, LoadLibrary
489 will search the loaded libraries for a match and return
490 one of them if the path search load fails.
492 We check whether LoadLibrary is returning a handle to
493 an already loaded module, and simulate failure if we
501 if (cur->module == module)
506 if (cur || !module) {
507 last_error = LT_DLSTRERROR(CANNOT_OPEN);
516 sys_wll_close (loader_data, module)
517 lt_dlloader_data_t loader_data;
520 if (FreeLibrary(module) == 0) {
521 last_error = LT_DLSTRERROR(CANNOT_CLOSE);
529 sys_wll_sym (loader_data, module, symbol)
530 lt_dlloader_data_t loader_data;
534 lt_ptr_t address = GetProcAddress(module, symbol);
537 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
541 static struct lt_user_dlloader
542 sys_wll = { 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 };
548 /* dynamic linking for BeOS */
550 #include <kernel/image.h>
554 sys_bedl_open (loader_data, filename)
555 lt_dlloader_data_t loader_data;
556 const char *filename;
561 image = load_add_on(filename);
565 if (get_next_image_info(0, &cookie, &info) == B_OK)
566 image = load_add_on(info.name);
569 last_error = LT_DLSTRERROR(CANNOT_OPEN);
573 return (lt_module_t) image;
578 sys_bedl_close (loader_data, module)
579 lt_dlloader_data_t loader_data;
582 if (unload_add_on((image_id)module) != B_OK) {
583 last_error = LT_DLSTRERROR(CANNOT_CLOSE);
591 sys_bedl_sym (loader_data, module, symbol)
592 lt_dlloader_data_t loader_data;
596 lt_ptr_t address = 0;
597 image_id image = (image_id)module;
599 if (get_image_symbol(image, symbol, B_SYMBOL_TYPE_ANY,
601 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
607 static struct lt_user_dlloader
608 sys_bedl = { 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 };
614 /* dynamic linking with dld */
622 sys_dld_open (loader_data, filename)
623 lt_dlloader_data_t loader_data;
624 const char *filename;
626 lt_module_t module = strdup(filename);
628 last_error = LT_DLSTRERROR(NO_MEMORY);
631 if (dld_link(filename) != 0) {
632 last_error = LT_DLSTRERROR(CANNOT_OPEN);
641 sys_dld_close (loader_data, module)
642 lt_dlloader_data_t loader_data;
645 if (dld_unlink_by_file((char*)(module), 1) != 0) {
646 last_error = LT_DLSTRERROR(CANNOT_CLOSE);
655 sys_dld_sym (loader_data, module, symbol)
656 lt_dlloader_data_t loader_data;
660 lt_ptr_t address = dld_get_func(symbol);
663 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
667 static struct lt_user_dlloader
668 sys_dld = { 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 };
672 /* emulate dynamic linking using preloaded_symbols */
674 typedef struct lt_dlsymlists_t {
675 struct lt_dlsymlists_t *next;
676 const lt_dlsymlist *syms;
679 static const lt_dlsymlist *default_preloaded_symbols = 0;
680 static lt_dlsymlists_t *preloaded_symbols = 0;
684 presym_init (loader_data)
685 lt_dlloader_data_t loader_data;
687 preloaded_symbols = 0;
688 if (default_preloaded_symbols)
689 return lt_dlpreload(default_preloaded_symbols);
694 presym_free_symlists LTDL_PARAMS((void))
696 lt_dlsymlists_t *lists = preloaded_symbols;
699 lt_dlsymlists_t *tmp = lists;
704 preloaded_symbols = 0;
710 presym_exit (loader_data)
711 lt_dlloader_data_t loader_data;
713 presym_free_symlists();
718 presym_add_symlist (preloaded)
719 const lt_dlsymlist *preloaded;
721 lt_dlsymlists_t *tmp;
722 lt_dlsymlists_t *lists = preloaded_symbols;
725 if (lists->syms == preloaded)
730 tmp = (lt_dlsymlists_t*) lt_dlmalloc(sizeof(lt_dlsymlists_t));
732 last_error = LT_DLSTRERROR(NO_MEMORY);
735 tmp->syms = preloaded;
736 tmp->next = preloaded_symbols;
737 preloaded_symbols = tmp;
743 presym_open (loader_data, filename)
744 lt_dlloader_data_t loader_data;
745 const char *filename;
747 lt_dlsymlists_t *lists = preloaded_symbols;
750 last_error = LT_DLSTRERROR(NO_SYMBOLS);
754 filename = "@PROGRAM@";
756 const lt_dlsymlist *syms = lists->syms;
759 if (!syms->address &&
760 strcmp(syms->name, filename) == 0) {
761 return (lt_module_t) syms;
767 last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
773 presym_close (loader_data, module)
774 lt_dlloader_data_t loader_data;
777 /* Just to silence gcc -Wall */
784 presym_sym (loader_data, module, symbol)
785 lt_dlloader_data_t loader_data;
789 lt_dlsymlist *syms = (lt_dlsymlist*)(module);
792 while (syms->address) {
793 if (strcmp(syms->name, symbol) == 0)
794 return syms->address;
797 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
801 static struct lt_user_dlloader
802 presym = { 0, presym_open, presym_close, presym_sym, presym_exit, 0 };
805 static char *user_search_path = 0;
806 static lt_dlloader_t *loaders = 0;
807 static lt_dlhandle handles = 0;
808 static int initialized = 0;
811 lt_dlinit LTDL_PARAMS((void))
813 /* initialize libltdl */
816 if (initialized) { /* Initialize only at first call. */
821 user_search_path = 0; /* empty search path */
824 errors += lt_add_dlloader (lt_next_dlloader(0), &sys_dl, "dlopen");
827 errors += lt_add_dlloader (lt_next_dlloader(0), &sys_shl, "dlopen");
829 #if defined(_WIN32) && !defined(__CYGWIN__)
830 errors += lt_add_dlloader (lt_next_dlloader(0), &sys_wll, "dlopen");
833 errors += lt_add_dlloader (lt_next_dlloader(0), &sys_bedl, "dlopen");
836 errors += lt_add_dlloader (lt_next_dlloader(0), &sys_dld, "dld");
838 errors += lt_add_dlloader (lt_next_dlloader(0), &presym, "dlpreload");
839 if (presym_init(presym.dlloader_data)) {
840 last_error = LT_DLSTRERROR(INIT_LOADER);
845 last_error = LT_DLSTRERROR(DLOPEN_NOT_SUPPORTED);
854 lt_dlpreload (preloaded)
855 const lt_dlsymlist *preloaded;
858 return presym_add_symlist(preloaded);
859 presym_free_symlists();
860 if (default_preloaded_symbols)
861 return lt_dlpreload(default_preloaded_symbols);
866 lt_dlpreload_default (preloaded)
867 const lt_dlsymlist *preloaded;
869 default_preloaded_symbols = preloaded;
874 lt_dlexit LTDL_PARAMS((void))
876 /* shut down libltdl */
877 lt_dlloader_t *loader = loaders;
881 last_error = LT_DLSTRERROR(SHUTDOWN);
884 if (initialized != 1) { /* shut down only at last call. */
888 /* close all modules */
890 for (level = 1; handles; level++) {
891 lt_dlhandle cur = handles;
893 lt_dlhandle tmp = cur;
895 if (tmp->info.ref_count <= level)
900 /* close all loaders */
902 lt_dlloader_t *next = loader->next;
903 lt_dlloader_data_t data = loader->dlloader_data;
904 if (loader->dlloader_exit && loader->dlloader_exit(data))
915 tryall_dlopen (handle, filename)
917 const char *filename;
919 lt_dlhandle cur = handles;
920 lt_dlloader_t *loader = loaders;
921 const char *saved_error = last_error;
923 /* check whether the module was already opened */
925 /* try to dlopen the program itself? */
926 if (!cur->info.filename && !filename)
928 if (cur->info.filename && filename &&
929 strcmp(cur->info.filename, filename) == 0)
935 cur->info.ref_count++;
942 cur->info.filename = strdup(filename);
943 if (!cur->info.filename) {
944 last_error = LT_DLSTRERROR(NO_MEMORY);
948 cur->info.filename = 0;
950 lt_dlloader_data_t data = loader->dlloader_data;
951 cur->module = loader->module_open(data, filename);
952 if (cur->module != 0)
954 loader = loader->next;
957 if (cur->info.filename)
958 lt_dlfree(cur->info.filename);
961 cur->loader = loader;
962 last_error = saved_error;
967 find_module (handle, dir, libdir, dlname, old_name, installed)
972 const char *old_name;
977 /* try to open the old library first; if it was dlpreopened,
978 we want the preopened version of it, even if a dlopenable
979 module is available */
980 if (old_name && tryall_dlopen(handle, old_name) == 0)
982 /* try to open the dynamic library */
984 /* try to open the installed module */
985 if (installed && libdir) {
987 lt_dlmalloc(strlen(libdir)+1+strlen(dlname)+1);
989 last_error = LT_DLSTRERROR(NO_MEMORY);
992 sprintf (filename, "%s/%s", libdir, dlname);
993 error = tryall_dlopen(handle, filename) != 0;
998 /* try to open the not-installed module */
1001 lt_dlmalloc((dir ? strlen(dir) : 0)
1002 + strlen(objdir) + strlen(dlname) + 1);
1004 last_error = LT_DLSTRERROR(NO_MEMORY);
1008 strcpy(filename, dir);
1011 strcat(filename, objdir);
1012 strcat(filename, dlname);
1014 error = tryall_dlopen(handle, filename) != 0;
1015 lt_dlfree(filename);
1019 /* maybe it was moved to another directory */
1022 lt_dlmalloc((dir ? strlen(dir) : 0)
1023 + strlen(dlname) + 1);
1025 strcpy(filename, dir);
1028 strcat(filename, dlname);
1029 error = tryall_dlopen(handle, filename) != 0;
1030 lt_dlfree(filename);
1039 canonicalize_path (path)
1042 char *canonical = 0;
1044 if (path && *path) {
1045 char *ptr = strdup (path);
1047 #ifdef LTDL_DIRSEP_CHAR
1048 /* Avoid this overhead where '/' is the only separator. */
1049 while (ptr = strchr (ptr, LTDL_DIRSEP_CHAR))
1058 find_file (basename, search_path, pdir, handle)
1059 const char *basename;
1060 const char *search_path;
1062 lt_dlhandle *handle;
1064 /* when handle != NULL search a library, otherwise a file */
1065 /* return NULL on failure, otherwise the file/handle */
1067 lt_ptr_t result = 0;
1069 int filenamesize = 0;
1070 int lenbase = strlen(basename);
1071 char *canonical = 0, *next = 0;
1073 if (!search_path || !*search_path) {
1074 last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
1077 canonical = canonicalize_path (search_path);
1079 last_error = LT_DLSTRERROR(NO_MEMORY);
1087 next = strchr(cur, LTDL_PATHSEP_CHAR);
1089 next = cur + strlen(cur);
1090 lendir = next - cur;
1091 if (*next == LTDL_PATHSEP_CHAR)
1097 if (lendir + 1 + lenbase >= filenamesize) {
1099 lt_dlfree(filename);
1100 filenamesize = lendir + 1 + lenbase + 1;
1101 filename = (char*) lt_dlmalloc(filenamesize);
1103 last_error = LT_DLSTRERROR(NO_MEMORY);
1107 strncpy(filename, cur, lendir);
1108 if (filename[lendir-1] != '/')
1109 filename[lendir++] = '/';
1110 strcpy(filename+lendir, basename);
1112 if (tryall_dlopen(handle, filename) == 0) {
1113 result = (lt_ptr_t) handle;
1117 FILE *file = fopen(filename, LTDL_READTEXT_MODE);
1121 filename[lendir] = '\0';
1122 *pdir = strdup(filename);
1124 /* We could have even avoided the
1125 strdup, but there would be some
1130 result = (lt_ptr_t) file;
1135 last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
1138 lt_dlfree(filename);
1140 lt_dlfree(canonical);
1145 load_deplibs(handle, deplibs)
1149 char *p, *save_search_path;
1151 int ret = 1, depcount = 0;
1153 lt_dlhandle *handles = 0;
1155 handle->depcount = 0;
1158 save_search_path = strdup(user_search_path);
1159 if (user_search_path && !save_search_path) {
1160 last_error = LT_DLSTRERROR(NO_MEMORY);
1164 /* extract search paths and count deplibs */
1168 while (*end && !isspace(*end)) end++;
1169 if (strncmp(p, "-L", 2) == 0 ||
1170 strncmp(p, "-R", 2) == 0) {
1172 *end = 0; /* set a temporary string terminator */
1173 if (lt_dladdsearchdir(p+2))
1186 names = lt_dlmalloc(depcount * sizeof(char*));
1189 handles = lt_dlmalloc(depcount * sizeof(lt_dlhandle*));
1193 /* now only extract the actual deplibs */
1198 while (*end && !isspace(*end)) end++;
1199 if (strncmp(p, "-L", 2) != 0 &&
1200 strncmp(p, "-R", 2) != 0) {
1203 *end = 0; /* set a temporary string terminator */
1204 if (strncmp(p, "-l", 2) == 0) {
1205 name = lt_dlmalloc(3+ /* "lib" */
1206 strlen(p+2)+strlen(shlib_ext)+1);
1208 sprintf(name, "lib%s%s", p+2, shlib_ext);
1212 names[depcount++] = name;
1221 /* load the deplibs (in reverse order) */
1222 for (i = 0; i < depcount; i++) {
1223 lt_dlhandle handle = lt_dlopen(names[depcount-1-i]);
1226 for (j = 0; j < i; j++)
1227 lt_dlclose(handles[j]);
1228 last_error = LT_DLSTRERROR(DEPLIB_NOT_FOUND);
1231 handles[i] = handle;
1233 handle->depcount = depcount;
1234 handle->deplibs = handles;
1238 for (i = 0; i < depcount; i++)
1239 lt_dlfree(names[i]);
1245 /* restore the old search path */
1246 if (user_search_path)
1247 lt_dlfree(user_search_path);
1248 user_search_path = save_search_path;
1253 unload_deplibs(handle)
1259 if (!handle->depcount)
1261 for (i = 0; i < handle->depcount; i++)
1262 errors += lt_dlclose(handle->deplibs[i]);
1271 /* remove the leading and trailing "'" from str
1272 and store the result in dest */
1274 const char *end = strrchr(str, '\'');
1275 int len = strlen(str);
1279 if (len > 3 && str[0] == '\'') {
1280 tmp = (char*) lt_dlmalloc(end - str);
1282 last_error = LT_DLSTRERROR(NO_MEMORY);
1285 strncpy(tmp, &str[1], (end - str) - 1);
1294 free_vars( dlname, oldname, libdir, deplibs)
1312 lt_dlopen (filename)
1313 const char *filename;
1315 lt_dlhandle handle = 0, newhandle;
1317 const char *saved_error = last_error;
1318 char *canonical = 0, *basename = 0, *dir = 0, *name = 0;
1321 handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
1323 last_error = LT_DLSTRERROR(NO_MEMORY);
1326 handle->info.ref_count = 0;
1327 handle->depcount = 0;
1328 handle->deplibs = 0;
1330 if (tryall_dlopen(&newhandle, 0) != 0) {
1334 goto register_handle;
1336 canonical = canonicalize_path (filename);
1338 last_error = LT_DLSTRERROR(NO_MEMORY);
1343 basename = strrchr(canonical, '/');
1346 dir = (char*) lt_dlmalloc(basename - canonical + 1);
1348 last_error = LT_DLSTRERROR(NO_MEMORY);
1352 strncpy(dir, canonical, basename - canonical);
1353 dir[basename - canonical] = '\0';
1355 basename = canonical;
1356 /* check whether we open a libtool module (.la extension) */
1357 ext = strrchr(basename, '.');
1358 if (ext && strcmp(ext, ".la") == 0) {
1359 /* this seems to be a libtool module */
1362 char *dlname = 0, *old_name = 0;
1363 char *libdir = 0, *deplibs = 0;
1366 /* if we can't find the installed flag, it is probably an
1367 installed libtool archive, produced with an old version
1371 /* extract the module name from the file name */
1372 name = (char*) lt_dlmalloc(ext - basename + 1);
1374 last_error = LT_DLSTRERROR(NO_MEMORY);
1378 /* canonicalize the module name */
1379 for (i = 0; i < ext - basename; i++)
1380 if (isalnum((int)(basename[i])))
1381 name[i] = basename[i];
1384 name[ext - basename] = '\0';
1385 /* now try to open the .la file */
1386 file = fopen(filename, LTDL_READTEXT_MODE);
1388 last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
1389 if (!file && !dir) {
1390 /* try other directories */
1391 file = (FILE*) find_file(basename,
1395 file = (FILE*) find_file(basename,
1396 getenv("LTDL_LIBRARY_PATH"),
1398 #ifdef LTDL_SHLIBPATH_VAR
1400 file = (FILE*) find_file(basename,
1401 getenv(LTDL_SHLIBPATH_VAR),
1404 #ifdef LTDL_SYSSEARCHPATH
1406 file = (FILE*) find_file(basename,
1415 line = (char*) lt_dlmalloc(LTDL_FILENAME_MAX);
1418 last_error = LT_DLSTRERROR(NO_MEMORY);
1422 /* read the .la file */
1423 while (!feof(file)) {
1424 if (!fgets(line, LTDL_FILENAME_MAX, file))
1426 if (line[0] == '\n' || line[0] == '#')
1429 # define STR_DLNAME "dlname="
1430 if (strncmp(line, STR_DLNAME,
1431 sizeof(STR_DLNAME) - 1) == 0)
1432 error = trim(&dlname,
1433 &line[sizeof(STR_DLNAME) - 1]);
1435 # undef STR_OLD_LIBRARY
1436 # define STR_OLD_LIBRARY "old_library="
1437 if (strncmp(line, STR_OLD_LIBRARY,
1438 sizeof(STR_OLD_LIBRARY) - 1) == 0)
1439 error = trim(&old_name,
1440 &line[sizeof(STR_OLD_LIBRARY) - 1]);
1443 # define STR_LIBDIR "libdir="
1444 if (strncmp(line, STR_LIBDIR,
1445 sizeof(STR_LIBDIR) - 1) == 0)
1446 error = trim(&libdir,
1447 &line[sizeof(STR_LIBDIR) - 1]);
1449 # undef STR_DL_DEPLIBS
1450 # define STR_DL_DEPLIBS "dl_dependency_libs="
1451 if (strncmp(line, STR_DL_DEPLIBS,
1452 sizeof(STR_DL_DEPLIBS) - 1) == 0)
1453 error = trim(&deplibs,
1454 &line[sizeof(STR_DL_DEPLIBS) - 1]);
1456 if (strcmp(line, "installed=yes\n") == 0)
1459 if (strcmp(line, "installed=no\n") == 0)
1466 /* allocate the handle */
1467 handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
1468 if (!handle || error) {
1472 last_error = LT_DLSTRERROR(NO_MEMORY);
1473 free_vars(dlname, old_name, libdir, deplibs);
1474 /* handle is already set to 0 */
1477 handle->info.ref_count = 0;
1478 if (load_deplibs(handle, deplibs) == 0) {
1480 /* find_module may replace newhandle */
1481 if (find_module(&newhandle, dir, libdir,
1482 dlname, old_name, installed)) {
1483 unload_deplibs(handle);
1488 free_vars(dlname, old_name, libdir, deplibs);
1494 if (handle != newhandle)
1495 unload_deplibs(handle);
1497 /* not a libtool module */
1498 handle = (lt_dlhandle) lt_dlmalloc(sizeof(lt_dlhandle_t));
1500 last_error = LT_DLSTRERROR(NO_MEMORY);
1501 /* handle is already set to 0 */
1504 handle->info.ref_count = 0;
1505 /* non-libtool modules don't have dependencies */
1506 handle->depcount = 0;
1507 handle->deplibs = 0;
1509 if (tryall_dlopen(&newhandle, filename)
1511 || (!find_file(basename, user_search_path,
1513 && !find_file(basename,
1514 getenv("LTDL_LIBRARY_PATH"),
1516 #ifdef LTDL_SHLIBPATH_VAR
1517 && !find_file(basename,
1518 getenv(LTDL_SHLIBPATH_VAR),
1521 #ifdef LTDL_SYSSEARCHPATH
1522 && !find_file(basename, sys_search_path,
1532 if (newhandle != handle) {
1536 if (!handle->info.ref_count) {
1537 handle->info.ref_count = 1;
1538 handle->info.name = name;
1539 handle->next = handles;
1541 name = 0; /* don't free this during `cleanup' */
1543 last_error = saved_error;
1550 lt_dlfree(canonical);
1555 lt_dlopenext (filename)
1556 const char *filename;
1561 const char *saved_error = last_error;
1564 return lt_dlopen(filename);
1565 len = strlen(filename);
1567 last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
1570 /* try the normal file name */
1571 handle = lt_dlopen(filename);
1574 /* try "filename.la" */
1575 tmp = (char*) lt_dlmalloc(len+4);
1577 last_error = LT_DLSTRERROR(NO_MEMORY);
1580 strcpy(tmp, filename);
1582 handle = lt_dlopen(tmp);
1584 last_error = saved_error;
1588 #ifdef LTDL_SHLIB_EXT
1589 /* try "filename.EXT" */
1590 if (strlen(shlib_ext) > 3) {
1592 tmp = (char*) lt_dlmalloc(len + strlen(shlib_ext) + 1);
1594 last_error = LT_DLSTRERROR(NO_MEMORY);
1597 strcpy(tmp, filename);
1600 strcat(tmp, shlib_ext);
1601 handle = lt_dlopen(tmp);
1603 last_error = saved_error;
1608 last_error = LT_DLSTRERROR(FILE_NOT_FOUND);
1617 lt_dlhandle cur, last;
1619 /* check whether the handle is valid */
1620 last = cur = handles;
1621 while (cur && handle != cur) {
1626 last_error = LT_DLSTRERROR(INVALID_HANDLE);
1629 handle->info.ref_count--;
1630 if (!handle->info.ref_count) {
1632 lt_dlloader_data_t data = handle->loader->dlloader_data;
1634 if (handle != handles)
1635 last->next = handle->next;
1637 handles = handle->next;
1638 error = handle->loader->module_close(data, handle->module);
1639 error += unload_deplibs(handle);
1640 if (handle->info.filename)
1641 lt_dlfree(handle->info.filename);
1642 if (handle->info.name)
1643 lt_dlfree(handle->info.name);
1651 lt_dlsym (handle, symbol)
1656 char lsym[LTDL_SYMBOL_LENGTH];
1659 lt_dlloader_data_t data;
1662 last_error = LT_DLSTRERROR(INVALID_HANDLE);
1666 last_error = LT_DLSTRERROR(SYMBOL_NOT_FOUND);
1669 lensym = strlen(symbol);
1670 if (handle->loader->sym_prefix)
1671 lensym += strlen(handle->loader->sym_prefix);
1672 if (handle->info.name)
1673 lensym += strlen(handle->info.name);
1674 if (lensym + LTDL_SYMBOL_OVERHEAD < LTDL_SYMBOL_LENGTH)
1677 sym = (char*) lt_dlmalloc(lensym + LTDL_SYMBOL_OVERHEAD + 1);
1679 last_error = LT_DLSTRERROR(BUFFER_OVERFLOW);
1682 data = handle->loader->dlloader_data;
1683 if (handle->info.name) {
1684 const char *saved_error = last_error;
1686 /* this is a libtool module */
1687 if (handle->loader->sym_prefix) {
1688 strcpy(sym, handle->loader->sym_prefix);
1689 strcat(sym, handle->info.name);
1691 strcpy(sym, handle->info.name);
1692 strcat(sym, "_LTX_");
1693 strcat(sym, symbol);
1694 /* try "modulename_LTX_symbol" */
1695 address = handle->loader->find_sym(data, handle->module, sym);
1701 last_error = saved_error;
1703 /* otherwise try "symbol" */
1704 if (handle->loader->sym_prefix) {
1705 strcpy(sym, handle->loader->sym_prefix);
1706 strcat(sym, symbol);
1708 strcpy(sym, symbol);
1709 address = handle->loader->find_sym(data, handle->module, sym);
1716 lt_dlerror LTDL_PARAMS((void))
1718 const char *error = last_error;
1725 lt_dladdsearchdir (search_dir)
1726 const char *search_dir;
1728 if (!search_dir || !strlen(search_dir))
1730 if (!user_search_path) {
1731 user_search_path = strdup(search_dir);
1732 if (!user_search_path) {
1733 last_error = LT_DLSTRERROR(NO_MEMORY);
1737 char *new_search_path = (char*)
1738 lt_dlmalloc(strlen(user_search_path) +
1739 strlen(search_dir) + 2); /* ':' + '\0' == 2 */
1740 if (!new_search_path) {
1741 last_error = LT_DLSTRERROR(NO_MEMORY);
1744 sprintf (new_search_path, "%s%c%s", user_search_path,
1745 LTDL_PATHSEP_CHAR, search_dir);
1746 lt_dlfree(user_search_path);
1747 user_search_path = new_search_path;
1753 lt_dlsetsearchpath (search_path)
1754 const char *search_path;
1756 if (user_search_path)
1757 lt_dlfree(user_search_path);
1758 user_search_path = 0; /* reset the search path */
1759 if (!search_path || !strlen(search_path))
1761 user_search_path = strdup(search_path);
1762 if (!user_search_path)
1768 lt_dlgetsearchpath LTDL_PARAMS((void))
1770 return user_search_path;
1774 lt_dlgetinfo (handle)
1778 last_error = LT_DLSTRERROR(INVALID_HANDLE);
1781 return &(handle->info);
1785 lt_dlforeach (func, data)
1786 int (*func) LTDL_PARAMS((lt_dlhandle handle, lt_ptr_t data));
1789 lt_dlhandle cur = handles;
1791 lt_dlhandle tmp = cur;
1793 if (func(tmp, data))
1801 lt_add_dlloader (place, dlloader, loader_name)
1802 lt_dlloader_t *place;
1803 const struct lt_user_dlloader *dlloader;
1804 const char *loader_name;
1806 lt_dlloader_t *node = 0, *ptr = 0;
1808 if ((dlloader == 0) /* diagnose null parameters */
1809 || (dlloader->module_open == 0)
1810 || (dlloader->module_close == 0)
1811 || (dlloader->find_sym == 0)) {
1812 last_error = LT_DLSTRERROR(INVALID_LOADER);
1816 /* Create a new dlloader node with copies of the user callbacks. */
1817 node = (lt_dlloader_t *) lt_dlmalloc (sizeof (lt_dlloader_t));
1819 last_error = LT_DLSTRERROR(NO_MEMORY);
1823 node->loader_name = loader_name;
1824 node->sym_prefix = dlloader->sym_prefix;
1825 node->dlloader_exit = dlloader->dlloader_exit;
1826 node->module_open = dlloader->module_open;
1827 node->module_close = dlloader->module_close;
1828 node->find_sym = dlloader->find_sym;
1829 node->dlloader_data = dlloader->dlloader_data;
1832 /* If there are no loaders, NODE becomes the list! */
1835 /* If PLACE is not set, add NODE to the end of the
1837 for (ptr = loaders; ptr->next; ptr = ptr->next)
1840 } else if (loaders == place) {
1841 /* If PLACE is the first loader, NODE goes first. */
1845 /* Find the node immediately preceding PLACE. */
1846 for (ptr = loaders; ptr->next != place; ptr = ptr->next)
1849 if (ptr->next != place) {
1850 last_error = LT_DLSTRERROR(INVALID_LOADER);
1854 /* Insert NODE between PTR and PLACE. */
1863 lt_remove_dlloader (loader_name)
1864 const char *loader_name;
1866 lt_dlloader_t *place = lt_find_dlloader (loader_name);
1871 last_error = LT_DLSTRERROR(INVALID_LOADER);
1875 /* Fail if there are any open modules which use this loader. */
1876 for (handle = handles; handle; handle = handle->next)
1877 if (handle->loader == place) {
1878 last_error = LT_DLSTRERROR(REMOVE_LOADER);
1882 if (place == loaders)
1883 /* PLACE is the first loader in the list. */
1884 loaders = loaders->next;
1886 /* Find the loader before the one being removed. */
1887 lt_dlloader_t *prev;
1888 for (prev = loaders; prev->next; prev = prev->next)
1889 if (!strcmp (prev->next->loader_name, loader_name))
1893 prev->next = prev->next->next;
1895 if (place->dlloader_exit)
1896 result = place->dlloader_exit (place->dlloader_data);
1903 lt_next_dlloader (place)
1904 lt_dlloader_t *place;
1906 return place ? place->next : loaders;
1910 lt_dlloader_name (place)
1911 lt_dlloader_t *place;
1914 last_error = LT_DLSTRERROR(INVALID_LOADER);
1915 return place ? place->loader_name : 0;
1918 lt_dlloader_data_t *
1919 lt_dlloader_data (place)
1920 lt_dlloader_t *place;
1923 last_error = LT_DLSTRERROR(INVALID_LOADER);
1924 return place ? &(place->dlloader_data) : 0;
1928 lt_find_dlloader (loader_name)
1929 const char *loader_name;
1931 lt_dlloader_t *place = 0;
1933 for (place = loaders; place; place = place->next)
1934 if (strcmp (place->loader_name, loader_name) == 0)
1941 static const char **user_error_strings = 0;
1942 static int errorcode = LTDL_ERROR_MAX;
1945 lt_dladderror (diagnostic)
1946 const char *diagnostic;
1948 int index = errorcode - LTDL_ERROR_MAX;
1949 const char **temp = 0;
1951 /* realloc is not entirely portable, so simulate it using
1952 lt_dlmalloc and lt_dlfree. */
1953 temp = (const char **) lt_dlmalloc ((1+index) * sizeof(const char*));
1955 last_error = LT_DLSTRERROR(NO_MEMORY);
1959 /* Build the new vector in the memory addressed by temp. */
1960 temp[index] = diagnostic;
1961 while (--index >= 0)
1962 temp[index] = user_error_strings[index];
1964 lt_dlfree (user_error_strings);
1965 user_error_strings = temp;
1970 lt_dlseterror (index)
1973 if (index >= errorcode || index < 0) {
1974 last_error = LT_DLSTRERROR(INVALID_ERRORCODE);
1978 if (index < LTDL_ERROR_MAX)
1979 last_error = ltdl_error_strings[errorcode];
1981 last_error = user_error_strings[errorcode - LTDL_ERROR_MAX];