summaryrefslogtreecommitdiffstats
path: root/src/util/load_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/load_lib.c')
-rw-r--r--src/util/load_lib.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/src/util/load_lib.c b/src/util/load_lib.c
new file mode 100644
index 0000000..44e540d
--- /dev/null
+++ b/src/util/load_lib.c
@@ -0,0 +1,146 @@
+/*++
+/* NAME
+/* load_lib 3
+/* SUMMARY
+/* library loading wrappers
+/* SYNOPSIS
+/* #include <load_lib.h>
+/*
+/* void load_library_symbols(const char *, LIB_FN *, LIB_DP *);
+/* const char *libname;
+/* LIB_FN *libfuncs;
+/* LIB_DP *libdata;
+/* DESCRIPTION
+/* load_library_symbols() loads the specified shared object
+/* and looks up the function or data pointers for the specified
+/* symbols. All errors are fatal.
+/*
+/* Arguments:
+/* .IP libname
+/* shared-library pathname.
+/* .IP libfuncs
+/* Array of LIB_FN structures. The last name member must be null.
+/* .IP libdata
+/* Array of LIB_DP structures. The last name member must be null.
+/* SEE ALSO
+/* msg(3) diagnostics interface
+/* DIAGNOSTICS
+/* Problems are reported via the msg(3) diagnostics routines:
+/* library not found, symbols not found, other fatal errors.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* LaMont Jones
+/* Hewlett-Packard Company
+/* 3404 Harmony Road
+/* Fort Collins, CO 80528, USA
+/*
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+ /*
+ * System libraries.
+ */
+#include "sys_defs.h"
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#ifdef USE_DYNAMIC_MAPS
+#if defined(HAS_DLOPEN)
+#include <dlfcn.h>
+#elif defined(HAS_SHL_LOAD)
+#include <dl.h>
+#else
+#error "USE_DYNAMIC_LIBS requires HAS_DLOPEN or HAS_SHL_LOAD"
+#endif
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <load_lib.h>
+
+/* load_library_symbols - load shared library and look up symbols */
+
+void load_library_symbols(const char *libname, LIB_FN *libfuncs,
+ LIB_DP *libdata)
+{
+ static const char myname[] = "load_library_symbols";
+ LIB_FN *fn;
+ LIB_DP *dp;
+
+#if defined(HAS_DLOPEN)
+ void *handle;
+ char *emsg;
+
+ /*
+ * XXX This is basically how FreeBSD dlfunc() silences a compiler warning
+ * about a data/function pointer conversion. The solution below is non-
+ * portable: it assumes that both data and function pointers are the same
+ * in size, and that both have the same representation.
+ */
+ union {
+ void *dptr; /* data pointer */
+ void (*fptr) (void); /* function pointer */
+ } non_portable_union;
+
+ if ((handle = dlopen(libname, RTLD_NOW)) == 0) {
+ emsg = dlerror();
+ msg_fatal("%s: dlopen failure loading %s: %s", myname, libname,
+ emsg ? emsg : "don't know why");
+ }
+ if (libfuncs) {
+ for (fn = libfuncs; fn->name; fn++) {
+ if ((non_portable_union.dptr = dlsym(handle, fn->name)) == 0) {
+ emsg = dlerror();
+ msg_fatal("%s: dlsym failure looking up %s in %s: %s", myname,
+ fn->name, libname, emsg ? emsg : "don't know why");
+ }
+ fn->fptr = non_portable_union.fptr;
+ if (msg_verbose > 1)
+ msg_info("loaded %s = %p", fn->name, non_portable_union.dptr);
+ }
+ }
+ if (libdata) {
+ for (dp = libdata; dp->name; dp++) {
+ if ((dp->dptr = dlsym(handle, dp->name)) == 0) {
+ emsg = dlerror();
+ msg_fatal("%s: dlsym failure looking up %s in %s: %s", myname,
+ dp->name, libname, emsg ? emsg : "don't know why");
+ }
+ if (msg_verbose > 1)
+ msg_info("loaded %s = %p", dp->name, dp->dptr);
+ }
+ }
+#elif defined(HAS_SHL_LOAD)
+ shl_t handle;
+
+ handle = shl_load(libname, BIND_IMMEDIATE, 0);
+
+ if (libfuncs) {
+ for (fn = libfuncs; fn->name; fn++) {
+ if (shl_findsym(&handle, fn->name, TYPE_PROCEDURE, &fn->fptr) != 0)
+ msg_fatal("%s: shl_findsym failure looking up %s in %s: %m",
+ myname, fn->name, libname);
+ if (msg_verbose > 1)
+ msg_info("loaded %s = %p", fn->name, (void *) fn->fptr);
+ }
+ }
+ if (libdata) {
+ for (dp = libdata; dp->name; dp++) {
+ if (shl_findsym(&handle, dp->name, TYPE_DATA, &dp->dptr) != 0)
+ msg_fatal("%s: shl_findsym failure looking up %s in %s: %m",
+ myname, dp->name, libname);
+ if (msg_verbose > 1)
+ msg_info("loaded %s = %p", dp->name, dp->dptr);
+ }
+ }
+#endif
+}
+
+#endif