/*
- * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2010, 2012-2013 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#include <config.h>
+#ifndef HAVE_DLOPEN
+
#include <sys/types.h>
#include <stdio.h>
void *
sudo_dlopen(const char *path, int mode)
{
- int flags = DYNAMIC_PATH;
+ int flags = DYNAMIC_PATH | BIND_VERBOSE;
if (mode == 0)
mode = RTLD_LAZY; /* default behavior */
shl_t handle = vhandle;
void *value = NULL;
- (void)shl_findsym(&handle, symbol, TYPE_UNDEFINED, &value);
+ /*
+ * Note that the behavior of of RTLD_NEXT and RTLD_SELF
+ * differs from most implementations when called from
+ * a shared library.
+ */
+ if (vhandle == RTLD_NEXT) {
+ /* Iterate over all shared libs looking for symbol. */
+ struct shl_descriptor *desc;
+ int idx = 0;
+ while (shl_get(idx++, &desc) == 0) {
+ if (shl_findsym(&desc->handle, symbol, TYPE_UNDEFINED, &value) == 0)
+ break;
+ }
+ } else {
+ if (vhandle == RTLD_DEFAULT)
+ handle = NULL;
+ else if (vhandle == RTLD_SELF)
+ handle = PROG_HANDLE;
+ (void)shl_findsym(&handle, symbol, TYPE_UNDEFINED, &value);
+ }
return value;
}
{
struct sudo_preload_table *sym;
- for (sym = sudo_preload_table; sym->name != NULL; sym++) {
- if (strcmp(symbol, sym->name) == 0)
- return sym->address;
+ if (symbol != RTLD_NEXT && symbol != RTLD_DEFAULT && symbol != RTLD_SELF) {
+ for (sym = sudo_preload_table; sym->name != NULL; sym++) {
+ if (strcmp(symbol, sym->name) == 0)
+ return sym->address;
+ }
}
return NULL;
}
{
return strerror(errno);
}
-
#endif /* HAVE_SHL_LOAD */
+#endif /* HAVE_DLOPEN */