/*++ /* NAME /* load_lib 3 /* SUMMARY /* library loading wrappers /* SYNOPSIS /* #include /* /* 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 #include #include #ifdef USE_DYNAMIC_MAPS #if defined(HAS_DLOPEN) #include #elif defined(HAS_SHL_LOAD) #include #else #error "USE_DYNAMIC_LIBS requires HAS_DLOPEN or HAS_SHL_LOAD" #endif /* * Utility library. */ #include #include /* 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