#include "ltdl.h"
-static const char *last_error = "unknown error";
+static const char *unknown_error = "unknown error";
+static const char *not_supported_error = "dlopen support not available";
+static const char *file_not_found_error = "file not found";
+static const char *no_symbols_error = "no symbols defined";
+static const char *symbol_error = "symbol not found";
+static const char *memory_error = "not enough memory";
+static const char *invalid_handle_error = "invalid handle";
+static const char *buffer_overflow_error = "internal buffer overflow";
+static const char *shutdown_error = "libraries already shutdown";
+
+static const char *last_error;
typedef struct lt_dltype_t {
struct lt_dltype_t *next;
# include <dlfcn.h>
#endif
-#ifdef RTLD_LAZY
-# define DLOPEN_MODE RTLD_LAZY
+#if ! HAVE_DLERROR /* not all platforms have dlerror() */
+#define dlerror() unknown_error
+#endif
+
+#if RTDL_GLOBAL
+# define LTDL_GLOBAL RTDL_GLOBAL
+#else
+# if DL_GLOBAL
+# define LTDL_GLOBAL DL_GLOBAL
+# else
+# define LTDL_GLOBAL 0
+# endif
+#endif
+
+#if RTDL_NOW
+# define LTDL_NOW RTDL_NOW
#else
-# ifdef DL_LAZY
-# define DLOPEN_MODE DL_LAZY
+# if DL_NOW
+# define LTDL_NOW DL_NOW
# else
-# define DLOPEN_MODE 1
+# define LTDL_NOW 0
# endif
#endif
lt_dlhandle handle;
const char *filename;
{
- handle->handle = dlopen(filename, DLOPEN_MODE);
- return !(handle->handle);
+ handle->handle = dlopen(filename, LTDL_GLOBAL | LTDL_NOW);
+ if (!handle->handle) {
+ last_error = dlerror();
+ return 1;
+ }
+ return 0;
}
static int
dl_close (handle)
lt_dlhandle handle;
{
- return dlclose(handle->handle);
+ if (dlclose(handle->handle) != 0) {
+ last_error = dlerror();
+ return 1;
+ }
+ return 0;
}
static lt_ptr_t
lt_dlhandle handle;
const char *symbol;
{
- return dlsym(handle->handle, symbol);
+ lt_ptr_t address = dlsym(handle->handle, symbol);
+
+ if (!address)
+ last_error = dlerror();
+ return address;
}
static
#include <dl.h>
#endif
-/* the following lines are (c) Tim Janik */
-
/* some flags are missing on some systems, so we provide
* harmless defaults.
*
* DYNAMIC_PATH - Allow the loader to dynamically search for the library specified
* by the path argument.
*/
+
#ifndef DYNAMIC_PATH
#define DYNAMIC_PATH 0
#endif /* DYNAMIC_PATH */
{
handle->handle = shl_load (filename, OPT_BIND_FLAGS, 0L);
/* the hp-docs say we should better abort() if errno==ENOSYM ;( */
- return !(handle->handle);
+ if (!handle->handle) {
+ last_error = unknown_error;
+ return 1;
+ }
+ return 0;
}
static int
shl_close (handle)
lt_dlhandle handle;
{
- shl_unload((shl_t) (handle->handle));
+ if (shl_unload((shl_t) (handle->handle)) != 0) {
+ last_error = unknown_error;
+ return 1;
+ }
return 0;
}
lt_dlhandle handle;
const char *symbol;
{
- lt_ptr_t *sym;
+ lt_ptr_t address;
- if (shl_findsym ((shl_t) (handle->handle), symbol,
- TYPE_UNDEFINED, &sym) || !(handle->handle) || !sym)
+ if (shl_findsym ((shl_t) (handle->handle), symbol, TYPE_UNDEFINED,
+ &address) != 0 || !(handle->handle) || !address) {
+ last_error = unknown_error;
return 0;
- return sym;
+ }
+ return address;
}
static
lt_dlhandle handle;
const char *filename;
{
- if (dld_link(filename))
+ if (dld_link(filename) != 0) {
+ last_error = unknown_error;
return 1;
+ }
handle->handle = strdup(filename);
return 0;
}
dld_close (handle)
lt_dlhandle handle;
{
- dld_unlink_by_file((char*)(handle->handle), 1);
+ if (dld_unlink_by_file((char*)(handle->handle), 1) != 0) {
+ last_error = unknown_error;
+ return 1;
+ }
free(handle->filename);
return 0;
}
lt_dlhandle handle;
const char *symbol;
{
- return dld_get_func(symbol);
+ lt_ptr_t address = dld_get_func(symbol);
+
+ if (!address)
+ last_error = unknown_error;
+ return address;
}
static
const char *filename;
{
handle->handle = LoadLibrary(filename);
- return !(handle->handle);
+ if (!handle->handle) {
+ last_error = unknown_error;
+ return 1;
+ }
+ return 0;
}
static int
wll_close (handle)
lt_dlhandle handle;
{
- FreeLibrary(handle->handle);
+ if (FreeLibrary(handle->handle) != 0) {
+ last_error = unknown_error;
+ return 1;
+ }
return 0;
}
lt_dlhandle handle;
const char *symbol;
{
- return GetProcAddress(handle->handle, symbol);
+ lt_ptr_t address = GetProcAddress(handle->handle, symbol);
+
+ if (!address)
+ last_error = unknown_error;
+ return address;
}
static
struct lt_dlsymlist
{
- char *name;
- lt_ptr_t address;
+ char *name;
+ lt_ptr_t address;
};
static struct lt_dlsymlist *preloaded_symbols;
{
struct lt_dlsymlist *s = preloaded_symbols;
- if (!s)
+ if (!filename) {
+ last_error = file_not_found_error;
return 1;
-
+ }
+ if (!s) {
+ last_error = no_symbols_error;
+ return 1;
+ }
while (s->name) {
if (!s->address && !strcmp(s->name, filename))
break;
s++;
}
- if (!s->name)
+ if (!s->name) {
+ last_error = file_not_found_error;
return 1;
+ }
handle->handle = s;
return 0;
}
{
struct lt_dlsymlist *s = (struct lt_dlsymlist*)(handle->handle);
- if (!s)
- return 0;
-
#if NEED_USCORE
/* lt_dlsym will have prepended a `_', but we don't need it */
- ++symbol;
+ symbol++;
#endif
s++;
while (s->address) {
return s->address;
s++;
}
+ last_error = symbol_error;
return 0;
}
typecount++;
}
}
- if (typecount == 0)
+ if (typecount == 0) {
+ last_error = not_supported_error;
return 1;
+ }
+ last_error = 0;
initialized = 1;
return 0;
}
lt_dltype type = types;
int errors;
- if (!initialized)
- return 1; /* already deinitialized */
+ if (!initialized) {
+ last_error = shutdown_error;
+ return 1;
+ }
if (initialized != 1) { /* shut down only at last call. */
initialized--;
return 0;
{
lt_dlhandle cur;
lt_dltype type = types;
+ const char *saved_error = last_error;
/* check whether the module was already opened */
cur = handles;
break;
type = type->next;
}
+ if (!type)
+ return 1;
(*handle)->type = type;
(*handle)->filename = strdup(filename);
- return !(type);
+ last_error = saved_error;
+ return 0;
}
#undef MAX_FILENAME
{
lt_dlhandle handle;
FILE *file;
- char dir[MAX_FILENAME];
- char tmp[MAX_FILENAME];
+ char dir[MAX_FILENAME], tmp[MAX_FILENAME];
const char *basename, *ext, *search_path;
+ const char *saved_error = last_error;
basename = strrchr(filename, '/');
if (basename)
basename++;
else
basename = filename;
- if (basename - filename >= MAX_FILENAME)
+ if (basename - filename >= MAX_FILENAME) {
+ last_error = buffer_overflow_error;
return 0;
+ }
strncpy(dir, filename, basename - filename);
dir[basename - filename] = '\0';
search_path = getenv("LTDL_LIBRARY_PATH"); /* get the search path */
while (!file && p) {
next = strchr(p, ':');
if (next) {
- if (next - p + 1 >= MAX_FILENAME)
+ if (next - p + 1 >= MAX_FILENAME) {
+ last_error = buffer_overflow_error;
return 0;
+ }
strncpy(dir, p, next - p);
dir[next - p] = '\0';
p = next+1;
} else {
- if (strlen(p)+1 >= MAX_FILENAME)
+ if (strlen(p)+1 >= MAX_FILENAME) {
+ last_error = buffer_overflow_error;
return 0;
+ }
strcpy(dir, p);
p = 0;
}
}
}
}
- if (!file)
+ if (!file) {
+ last_error = file_not_found_error;
return 0;
+ }
while (!feof(file)) {
if (!fgets(tmp, MAX_FILENAME, file))
break;
/* FIXME: preload required libraries */
handle = (lt_dlhandle) malloc(sizeof(lt_dlhandle_t));
- if (!handle)
+ if (!handle) {
+ last_error = memory_error;
return 0;
+ }
if (find_module(&handle, dir, libdir, dlname, old_name)) {
free(handle);
+ last_error = file_not_found_error;
return 0;
}
/* extract the module name from the file name */
- if (strlen(basename) >= MAX_FILENAME)
+ if (strlen(basename) >= MAX_FILENAME) {
+ last_error = buffer_overflow_error;
return 0;
+ }
strcpy(tmp, basename);
tmp[ext - basename] = '\0';
/* canonicalize the module name */
} else {
/* not a libtool module */
handle = (lt_dlhandle) malloc(sizeof(lt_dlhandle_t));
- if (!handle)
+ if (!handle) {
+ last_error = memory_error;
return 0;
-
- if (tryall_dlopen(*handle, filename)) {
+ }
+ if (tryall_dlopen(&handle, filename)) {
int error = 1;
if (!*dir && search_path) {
while (error && p) {
next = strchr(p, ':');
if (next) {
- if (next - p + 1 >= MAX_FILENAME)
+ if (next - p + 1 >= MAX_FILENAME) {
+ last_error = buffer_overflow_error;
return 0;
+ }
strncpy(dir, p, next - p);
dir[next - p] = '\0';
p = next+1;
} else {
- if (strlen(p)+1 >= MAX_FILENAME)
+ if (strlen(p)+1 >= MAX_FILENAME) {
+ last_error = buffer_overflow_error;
return 0;
+ }
strcpy(dir, p);
p = 0;
}
if (strlen(dir)+strlen(basename) < MAX_FILENAME) {
strcpy(tmp, dir);
strcat(tmp, basename);
- error = tryall_dlopen(*handle, tmp);
+ error = tryall_dlopen(&handle, tmp);
}
}
}
if (error) {
free(handle);
+ last_error = file_not_found_error;
return 0;
}
}
handle->usage = 1;
handle->next = handles;
handles = handle;
+ last_error = saved_error;
return handle;
}
last = cur;
cur = cur->next;
}
- if (!cur)
- return 1; /* invalid handle */
+ if (!cur) {
+ last_error = invalid_handle_error;
+ return 1;
+ }
handle->usage--;
if (!handle->usage) {
int error;
char sym[MAX_SYMBOL_LENGTH];
lt_ptr_t address;
+ if (strlen(symbol) >= MAX_SYMBOL_LENGTH) {
+ last_error = buffer_overflow_error;
+ return 0;
+ }
#ifdef NEED_USCORE
if (handle->name && strlen(handle->name) < MAX_SYMBOL_LENGTH-6) {
/* this is a libtool module */
#ifdef NEED_USCORE
/* prefix symbol with leading underscore */
strcpy(sym, "_");
- if (strlen(symbol) >= MAX_SYMBOL_LENGTH)
- return 0;
strcat(sym, symbol);
return handle->type->find_sym(handle, sym);
#else
const char *
lt_dlerror ()
{
- return last_error;
+ const char *error = last_error;
+
+ last_error = 0;
+ return error;
}