#define LTDL_SYMBOL_LENGTH 128
#undef LTDL_SYMBOL_OVERHEAD
-/* This accounts for the _LTX_ separator and the string terminator */
-#define LTDL_SYMBOL_OVERHEAD 6
+/* This accounts for the _LTX_ separator */
+#define LTDL_SYMBOL_OVERHEAD 5
+static const char *objdir = LTDL_OBJDIR "/";
+static const char *shlib_ext = LTDL_SHLIB_EXT;
static const char *unknown_error = "unknown error";
static const char *dlopen_not_supported_error = "dlopen support not available";
static const char *buffer_overflow_error = "internal buffer overflow";
static const char *shutdown_error = "library already shutdown";
+#ifndef HAVE_PRELOADED_SYMBOLS
+/* If libtool won't define it, we'd better do */
+const lt_dlsymlist lt_preloaded_symbols[1] = { { 0, 0 } };
+#endif
+
static const char *last_error = 0;
typedef struct lt_dltype_t {
return 0;
}
-static int /* not all compilers support void */
+static int
presym_free_symlists ()
{
lt_dlsymlists_t *lists = preloaded_symbols;
#undef LTDL_TYPE_TOP
#define LTDL_TYPE_TOP &presym
-static char *usr_search_path;
-static int usr_search_path_size = 0;
+static char *user_search_path = 0;
static lt_dlhandle handles = 0;
static int initialized = 0;
return 0;
}
handles = 0;
- if (usr_search_path)
- free(usr_search_path);
- usr_search_path = 0; /* empty search path */
+ user_search_path = 0; /* empty search path */
while (*type) {
if ((*type)->mod_init())
return 0;
}
-#ifndef HAVE_PRELOADED_SYMBOLS
-/* If libtool won't define it, we'd better do */
-const lt_dlsymlist lt_preloaded_symbols[1] = { { 0, 0 } };
-#endif
-
int
lt_dlexit ()
{
return errors;
}
+static int
+trim (dest, s)
+ char *dest;
+ const char *s;
+{
+ char *i = strrchr(s, '\'');
+ int len = strlen(s);
+
+ if (len > 3 && s[0] == '\'') {
+ strncpy(dest, &s[1], (i - s) - 1);
+ dest[len-3] = '\0';
+ } else
+ *dest = '\0';
+ return 0;
+}
+
static int
tryall_dlopen (handle, filename)
lt_dlhandle *handle;
return 0;
}
- (*handle)->filename = strdup(filename);
- if (!(*handle)->filename)
+ cur = *handle;
+ cur->filename = strdup(filename);
+ if (!cur->filename)
return 1;
while (type) {
- if (type->lib_open(*handle, filename) == 0)
+ if (type->lib_open(cur, filename) == 0)
break;
type = type->next;
}
if (!type) {
- free((*handle)->filename);
+ free(cur->filename);
return 1;
}
- (*handle)->type = type;
+ cur->type = type;
last_error = saved_error;
return 0;
}
static int
-find_module (handle, dir, dlname, old_name)
+find_module (handle, dir, libdir, dlname, old_name, installed)
lt_dlhandle *handle;
const char *dir;
+ const char *libdir;
const char *dlname;
const char *old_name;
+ int installed;
{
- /* search for old library first; if it was dlpreopened, we
- want the preopened version of it, even if a dlopenable
- module is available */
- if (old_name && tryall_dlopen(handle, old_name) == 0)
+ char filename[LTDL_FILENAME_MAX];
+
+ /* try to open the old library first; if it was dlpreopened,
+ we want the preopened version of it, even if a dlopenable
+ module is available */
+ if (*old_name && tryall_dlopen(handle, old_name) == 0)
return 0;
-
- /* search a module */
- if (dlname) {
- char *filename = malloc(strlen(dir)+1+strlen(dlname)+1);
-
- if (!filename) {
- last_error = memory_error;
- return 1;
+ /* try to open the dynamic library */
+ if (*dlname) {
+ /* try to open the installed module */
+ if (installed &&
+ strlen(libdir)+1+strlen(dlname) < LTDL_FILENAME_MAX) {
+ strcpy(filename, libdir);
+ strcat(filename, "/");
+ strcat(filename, dlname);
+ if (tryall_dlopen(handle, filename) == 0)
+ return 0;
}
- strcpy(filename, dir);
- strcat(filename, "/");
- strcat(filename, dlname);
- if (tryall_dlopen(handle, filename) == 0) {
- free(filename);
- return 0;
+ /* try to open the not-installed module */
+ if (!installed &&
+ strlen(dir)+strlen(objdir)+strlen(dlname)
+ < LTDL_FILENAME_MAX) {
+ strcpy(filename, dir);
+ strcat(filename, objdir);
+ strcat(filename, dlname);
+ if (tryall_dlopen(handle, filename) == 0)
+ return 0;
}
- free(filename);
- }
- last_error = file_not_found_error;
- return 1;
-}
-
-#undef LTDL_CHECK_SIZE
-#define LTDL_CHECK_SIZE(buf_, size_, need_, ret) do { \
- char **pbuf = &buf_; int *psize = &size_, need = need_; \
- if (need > *psize) { \
- if (*pbuf) \
- free(*pbuf); \
- *pbuf = malloc(need); \
- if (!*pbuf) { \
- last_error = memory_error; \
- return ret; \
- } \
- } \
-} while(0)
-
-static int
-find_library (handle, basename, search_path)
- lt_dlhandle *handle;
- const char *basename;
- const char *search_path;
-{
- char *filename = 0;
- int size = 0;
- const char *cur, *next;
- int baselen;
-
- if (!search_path || !strlen(search_path)) {
- last_error = file_not_found_error;
- return 1;
- }
- cur = search_path;
- baselen = strlen(basename);
- while (cur) {
- int lendir;
- next = strchr(cur, ':');
- if (next)
- lendir = next-cur;
- else
- lendir = strlen(cur);
- if (lendir == 0)
- continue;
- LTDL_CHECK_SIZE(filename, size, \
- lendir + 1 + baselen + 1, 1);
- strncpy(filename, cur, lendir);
- if (next)
- cur = next+1;
- else
- cur = 0;
- filename[lendir] = '/';
- strncpy(filename+lendir+1, basename, baselen+1);
- if (tryall_dlopen(handle, filename) == 0) {
- free(filename);
- return 0;
+ /* hmm, maybe it was moved to another directory */
+ if (strlen(dir)+strlen(dlname) < LTDL_FILENAME_MAX) {
+ strcpy(filename, dir);
+ strcat(filename, dlname);
+ if (tryall_dlopen(handle, filename) == 0)
+ return 0;
}
}
- free(filename);
last_error = file_not_found_error;
return 1;
}
-static FILE *
-find_file (basename, search_path, pdir)
+static lt_ptr_t
+find_file (basename, search_path, pdir, handle)
const char *basename;
const char *search_path;
- const char **pdir;
+ char *pdir;
+ lt_dlhandle *handle;
{
- char *filename = 0;
- int size = 0;
+ /* when handle != NULL search a library, otherwise a file */
+ /* return NULL on failure, otherwise the file/handle */
+
+ char filename[LTDL_FILENAME_MAX];
const char *cur, *next;
FILE *file;
- int baselen;
- int overhead;
-
+ int lendir;
+
if (!search_path || !strlen(search_path)) {
last_error = file_not_found_error;
return 0;
}
cur = search_path;
- baselen = strlen(basename);
- overhead = strlen(LTDL_OBJDIR)+1;
- if (baselen > overhead)
- overhead = baselen;
while (cur) {
- int lendir;
next = strchr(cur, ':');
- if (next)
- lendir = next-cur;
- else
- lendir = strlen(cur);
- if (lendir == 0)
- continue;
- LTDL_CHECK_SIZE(filename, size, \
- lendir + 1 + overhead + 1, 0);
- strncpy(filename, cur, lendir);
- if (next)
+ if (next) {
+ if (next - cur + 1 >= LTDL_FILENAME_MAX) {
+ last_error = buffer_overflow_error;
+ return 0;
+ }
+ strncpy(filename, cur, next - cur);
+ filename[next - cur] = '\0';
cur = next+1;
- else
+ } else {
+ if (strlen(cur)+1 >= LTDL_FILENAME_MAX) {
+ last_error = buffer_overflow_error;
+ return 0;
+ }
+ strcpy(filename, cur);
cur = 0;
- filename[lendir] = '/';
- strncpy(filename+lendir+1, basename, baselen+1);
- file = fopen(filename, LTDL_READTEXT_MODE);
- if (file) {
- filename[lendir+1] = '\0';
- *pdir = filename;
- return file;
+ }
+ if (!*filename)
+ continue;
+ strcat(filename, "/");
+ lendir = strlen(filename);
+ if (lendir+strlen(basename) < LTDL_FILENAME_MAX) {
+ strcat(filename, basename);
+ if (handle) {
+ if (tryall_dlopen(handle, filename) == 0)
+ return (lt_ptr_t) handle;
+ } else {
+ file = fopen(filename, LTDL_READTEXT_MODE);
+ if (file) {
+ filename[lendir+1] = '\0';
+ strcpy(pdir, filename);
+ return (lt_ptr_t) file;
+ }
+ }
}
}
- free(filename);
last_error = file_not_found_error;
return 0;
}
return 0;
}
-#undef LTDL_TRIM
-#define LTDL_TRIM(dest_, s_) do { \
- char **dest = &(dest_); \
- char *s = (s_); \
- int len = strlen(s); \
- \
- if (*dest) \
- free(*dest); \
- *dest = 0; \
- \
- if (len > 3 && s[0] == '\'' \
- && s[len-1] == '\n' && s[len-2] == '\'') { \
- *dest = malloc(len-2); \
- if (!*dest) \
- goto trim_raise_memory_error; \
- strncpy(*dest, &s[1], len - 3); \
- (*dest)[len-3] = '\0'; \
- } \
-} while(0)
-
lt_dlhandle
lt_dlopen (filename)
const char *filename;
{
- lt_dlhandle handle = 0;
- char *dir = 0, *name = 0;
+ lt_dlhandle handle;
+ char dir[LTDL_FILENAME_MAX];
const char *basename, *ext;
const char *saved_error = last_error;
+ char *name = 0;
+ if (!filename) {
+ last_error = file_not_found_error;
+ return 0;
+ }
basename = strrchr(filename, '/');
- if (basename) {
+ if (basename)
basename++;
- dir = malloc(basename - filename + strlen(LTDL_OBJDIR) + 1);
- if (!dir) {
- last_error = memory_error;
- return 0;
- }
- strncpy(dir, filename, basename-filename);
- dir[basename-filename] = '\0';
- } else
+ else
basename = filename;
-
+ if (basename - filename >= LTDL_FILENAME_MAX) {
+ last_error = buffer_overflow_error;
+ return 0;
+ }
+ strncpy(dir, filename, basename - filename);
+ dir[basename - filename] = '\0';
/* check whether we open a libtool module (.la extension) */
ext = strrchr(basename, '.');
if (ext && strcmp(ext, ".la") == 0) {
- char *dlname = 0, *old_name = 0;
- char *libdir = 0, *deplibs = 0;
+ char dlname[LTDL_FILENAME_MAX], old_name[LTDL_FILENAME_MAX];
+ char libdir[LTDL_FILENAME_MAX], deplibs[LTDL_FILENAME_MAX];
char tmp[LTDL_FILENAME_MAX];
FILE *file;
int i;
+
/* if we can't find the installed flag, it is probably an
installed libtool archive, produced with an old version
of libtool */
int installed=1;
+ dlname[0] = old_name[0] = libdir[0] = deplibs[0] = '\0';
+
/* extract the module name from the file name */
if (strlen(basename) >= sizeof(tmp)) {
last_error = buffer_overflow_error;
return 0;
}
- strcpy(tmp, basename);
- tmp[ext - basename] = '\0';
/* canonicalize the module name */
for (i = 0; i < ext - basename; i++)
- if (!isalnum(tmp[i]))
+ if (isalnum(basename[i]))
+ tmp[i] = basename[i];
+ else
tmp[i] = '_';
+ tmp[ext - basename] = '\0';
name = strdup(tmp);
if (!name) {
last_error = memory_error;
return 0;
}
+
file = fopen(filename, LTDL_READTEXT_MODE);
- if (!file && !dir) {
+ if (!file)
+ last_error = file_not_found_error;
+ if (!file && !*dir) {
/* try other directories */
- file = find_file(basename, usr_search_path, &dir);
+ file = (FILE*) find_file(basename,
+ user_search_path,
+ dir, 0);
if (!file)
- file = find_file(basename,
+ file = (FILE*) find_file(basename,
getenv("LTDL_LIBRARY_PATH"),
- &dir);
+ dir, 0);
#ifdef LTDL_SHLIBPATH_VAR
if (!file)
- file = find_file(basename,
+ file = (FILE*) find_file(basename,
getenv(LTDL_SHLIBPATH_VAR),
- &dir);
+ dir, 0);
#endif
}
if (!file) {
- goto clean_up_dir;
+ free(name);
+ return 0;
}
while (!feof(file)) {
if (!fgets(tmp, sizeof(tmp), file))
break;
if (tmp[0] == '\n' || tmp[0] == '#')
- ;
- else
+ continue;
if (strncmp(tmp, "dlname=", 7) == 0)
- LTDL_TRIM(dlname, &tmp[7]);
+ trim(dlname, &tmp[7]);
else
if (strncmp(tmp, "old_library=", 12) == 0)
- LTDL_TRIM(old_name, &tmp[12]);
+ trim(old_name, &tmp[12]);
else
if (strncmp(tmp, "libdir=", 7) == 0)
- LTDL_TRIM(libdir, &tmp[7]);
+ trim(libdir, &tmp[7]);
else
if (strncmp(tmp, "dl_dependency_libs=", 20) == 0)
- LTDL_TRIM(deplibs, &tmp[20]);
+ trim(deplibs, &tmp[20]);
else
if (strcmp(tmp, "installed=yes\n") == 0)
installed = 1;
else
if (strcmp(tmp, "installed=no\n") == 0)
installed = 0;
- else
- if (0) {
- trim_raise_memory_error:
- fclose(file);
- goto handle_raise_memory_error;
- }
}
fclose(file);
handle = (lt_dlhandle) malloc(sizeof(lt_dlhandle_t));
if (!handle) {
- handle_raise_memory_error:
last_error = memory_error;
- goto clean_up_vars;
+ free(name);
+ return 0;
}
handle->usage = 0;
- if (deplibs && load_deplibs(handle, deplibs)) {
- clean_up_handle:
+ if (load_deplibs(handle, deplibs)) {
free(handle);
- handle = 0;
- goto clean_up_vars;
+ free(name);
+ return 0;
}
- if (installed) {
- if (find_module(&handle, libdir, dlname, old_name)) {
- clean_up_deplibs:
- unload_deplibs(handle);
- goto clean_up_handle;
- }
- } else {
- /* We dir is non-NULL, it has enough space for
- LTDL_OBJDIR: it was reserved in the
- beginning of the function or within
- find_file */
- if (dir)
- strcat(dir, LTDL_OBJDIR);
- if (find_module(&handle,
- dir ? dir : LTDL_OBJDIR,
- dlname, old_name))
- goto clean_up_deplibs;
+ if (find_module(&handle, dir, libdir,
+ dlname, old_name, installed)) {
+ unload_deplibs(handle);
+ free(handle);
+ free(name);
+ return 0;
}
- clean_up_vars:
- if (dlname)
- free(dlname);
- if (old_name)
- free(old_name);
- if (libdir)
- free(libdir);
- if (deplibs)
- free(deplibs);
- if (!handle)
- goto clean_up_dir;
} else {
- /* try to append libtool library extension */
- char *newfilename = malloc(strlen(filename)+4);
- if (!newfilename) {
- last_error = memory_error;
- goto clean_up_dir;
- }
- strcpy(newfilename, filename);
- strcat(newfilename, ".la");
- handle = lt_dlopen(newfilename);
- free(newfilename);
- if (handle)
- goto restore_error;
-
/* not a libtool module */
handle = (lt_dlhandle) malloc(sizeof(lt_dlhandle_t));
if (!handle) {
last_error = memory_error;
- goto clean_up_dir;
+ return 0;
}
handle->usage = 0;
- if (tryall_dlopen(&handle, filename)
- && (dir
- || (find_library(&handle, basename, usr_search_path)
- && find_library(&handle, basename,
- getenv("LTDL_LIBRARY_PATH"))
+ if (tryall_dlopen(&handle, filename) && (*dir
+ || (find_file(basename, user_search_path, 0, &handle)
+ && find_file(basename, getenv("LTDL_LIBRARY_PATH"),
+ 0, &handle)
#ifdef LTDL_SHLIBPATH_VAR
- && find_library(&handle, basename,
- getenv(LTDL_SHLIBPATH_VAR))
-#endif
- ))) {
-#ifdef LTDL_SHLIB_EXT
- newfilename = malloc(strlen(filename) +
- strlen(LTDL_SHLIB_EXT) + 1);
- if (!newfilename) {
- last_error = memory_error;
- goto clean_up_hand;
- }
- strcpy(newfilename, filename);
- strcat(newfilename, LTDL_SHLIB_EXT);
- basename = newfilename + (basename - filename);
- if (tryall_dlopen(&handle, newfilename)
- && (dir
- || (find_library(&handle, basename, usr_search_path)
- && find_library(&handle, basename,
- getenv("LTDL_LIBRARY_PATH"))
-#ifdef LTDL_SHLIBPATH_VAR
- && find_library(&handle, basename,
- getenv(LTDL_SHLIBPATH_VAR))
-#endif
- ))) {
-#endif
- clean_up_hand:
- free(handle);
- handle = 0;
- goto clean_up_dir;
-#ifdef LTDL_SHLIB_EXT
- }
+ && find_file(basename, getenv(LTDL_SHLIBPATH_VAR),
+ 0, &handle)
#endif
+ ))) {
+ free(handle);
+ return 0;
}
}
if (!handle->usage) {
handle->usage = 1;
+ handle->name = name;
handle->next = handles;
handles = handle;
- handle->name = name;
- name = 0;
}
- restore_error:
last_error = saved_error;
- clean_up_dir:
- if (dir)
- free(dir);
- if (name)
- free(name);
return handle;
}
+lt_dlhandle
+lt_dlopenext (filename)
+ const char *filename;
+{
+ lt_dlhandle handle;
+ char tmp[LTDL_FILENAME_MAX];
+ int len;
+ const char *saved_error = last_error;
+
+ if (!filename) {
+ last_error = file_not_found_error;
+ return 0;
+ }
+ len = strlen(filename);
+ if (!len) {
+ last_error = file_not_found_error;
+ return 0;
+ }
+ /* try the normal file name */
+ handle = lt_dlopen(filename);
+ if (handle)
+ return handle;
+ /* try "filename.la" */
+ if (len+3 >= sizeof(tmp)) {
+ last_error = buffer_overflow_error;
+ return 0;
+ }
+ strcpy(tmp, filename);
+ strcat(tmp, ".la");
+ handle = lt_dlopen(tmp);
+ if (handle) {
+ last_error = saved_error;
+ return handle;
+ }
+#ifdef LTDL_SHLIB_EXT
+ /* try "filename.EXT" */
+ tmp[len-1] = '\0';
+ if (len+strlen(shlib_ext) >= sizeof(tmp)) {
+ last_error = buffer_overflow_error;
+ return 0;
+ }
+ strcat(tmp, shlib_ext);
+ handle = lt_dlopen(tmp);
+ if (handle) {
+ last_error = saved_error;
+ return handle;
+ }
+#endif
+ return 0;
+}
+
int
lt_dlclose (handle)
lt_dlhandle handle;
if (lensym + LTDL_SYMBOL_OVERHEAD < LTDL_SYMBOL_LENGTH)
sym = lsym;
else
- sym = malloc(lensym + LTDL_SYMBOL_OVERHEAD);
+ sym = malloc(lensym + LTDL_SYMBOL_OVERHEAD + 1);
if (!sym) {
last_error = buffer_overflow_error;
return 0;
lt_dladdsearchdir (search_dir)
const char *search_dir;
{
- if (!search_dir) {
- if (usr_search_path)
- free(usr_search_path);
- usr_search_path = 0; /* reset the search path */
+ if (!search_dir || !strlen(search_dir))
return 0;
- }
- if (!strlen(search_dir))
- return 0;
- if (!usr_search_path) {
- usr_search_path_size = strlen(search_dir)+1;
- usr_search_path = malloc(usr_search_path_size);
- if (!usr_search_path) {
+ if (!user_search_path) {
+ user_search_path = strdup(search_dir);
+ if (!user_search_path) {
last_error = memory_error;
return 1;
}
- strcpy(usr_search_path, search_dir);
} else {
- int new_size = usr_search_path_size + strlen(search_dir) + 1;
- char *new_search_path = realloc(usr_search_path, new_size);
+ char *new_search_path = (char*)
+ malloc(strlen(user_search_path) +
+ strlen(search_dir) + 1);
if (!new_search_path) {
last_error = memory_error;
return 1;
}
- usr_search_path = new_search_path;
- usr_search_path_size = new_size;
- strcat(usr_search_path, ":");
- strcat(usr_search_path, search_dir);
+ strcat(new_search_path, ":");
+ strcat(new_search_path, search_dir);
+ free(user_search_path);
+ user_search_path = new_search_path;
}
return 0;
}
lt_dlsetsearchpath (search_path)
const char *search_path;
{
- if (usr_search_path)
- free(usr_search_path);
- usr_search_path = 0; /* reset the search path */
- if (!search_path || !strlen(search_path)) {
+ if (user_search_path)
+ free(user_search_path);
+ user_search_path = 0; /* reset the search path */
+ if (!search_path || !strlen(search_path))
return 0;
- }
- usr_search_path = strdup(search_path);
- if (usr_search_path)
- usr_search_path_size = strlen(usr_search_path)+1;
- else
+ user_search_path = strdup(search_path);
+ if (!user_search_path)
return 1;
return 0;
}
const char *
-lt_dlgetsearchpath __P((void))
+lt_dlgetsearchpath ()
{
- return usr_search_path;
+ return user_search_path;
}