xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/load_lib.c (revision 67b9b338a7386232ac596b5fd0cd5a9cc8a03c71)
1 /*	$NetBSD: load_lib.c,v 1.3 2022/10/08 16:12:50 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	load_lib 3
6 /* SUMMARY
7 /*	library loading wrappers
8 /* SYNOPSIS
9 /*	#include <load_lib.h>
10 /*
11 /*	void	load_library_symbols(const char *, LIB_FN *, LIB_DP *);
12 /*	const char *libname;
13 /*	LIB_FN	*libfuncs;
14 /*	LIB_DP	*libdata;
15 /* DESCRIPTION
16 /*	load_library_symbols() loads the specified shared object
17 /*	and looks up the function or data pointers for the specified
18 /*	symbols. All errors are fatal.
19 /*
20 /*	Arguments:
21 /* .IP libname
22 /*	shared-library pathname.
23 /* .IP libfuncs
24 /*	Array of LIB_FN structures. The last name member must be null.
25 /* .IP libdata
26 /*	Array of LIB_DP structures. The last name member must be null.
27 /* SEE ALSO
28 /*	msg(3) diagnostics interface
29 /* DIAGNOSTICS
30 /*	Problems are reported via the msg(3) diagnostics routines:
31 /*	library not found, symbols not found, other fatal errors.
32 /* LICENSE
33 /* .ad
34 /* .fi
35 /*	The Secure Mailer license must be distributed with this software.
36 /* AUTHOR(S)
37 /*	LaMont Jones
38 /*	Hewlett-Packard Company
39 /*	3404 Harmony Road
40 /*	Fort Collins, CO 80528, USA
41 /*
42 /*	Wietse Venema
43 /*	IBM T.J. Watson Research
44 /*	P.O. Box 704
45 /*	Yorktown Heights, NY 10598, USA
46 /*--*/
47 
48  /*
49   * System libraries.
50   */
51 #include "sys_defs.h"
52 #include <stdlib.h>
53 #include <stddef.h>
54 #include <string.h>
55 #ifdef USE_DYNAMIC_MAPS
56 #if defined(HAS_DLOPEN)
57 #include <dlfcn.h>
58 #elif defined(HAS_SHL_LOAD)
59 #include <dl.h>
60 #else
61 #error "USE_DYNAMIC_LIBS requires HAS_DLOPEN or HAS_SHL_LOAD"
62 #endif
63 
64  /*
65   * Utility library.
66   */
67 #include <msg.h>
68 #include <load_lib.h>
69 
70 /* load_library_symbols - load shared library and look up symbols */
71 
load_library_symbols(const char * libname,LIB_FN * libfuncs,LIB_DP * libdata)72 void    load_library_symbols(const char *libname, LIB_FN *libfuncs,
73 			             LIB_DP *libdata)
74 {
75     static const char myname[] = "load_library_symbols";
76     LIB_FN *fn;
77     LIB_DP *dp;
78 
79 #if defined(HAS_DLOPEN)
80     void   *handle;
81     char   *emsg;
82 
83     /*
84      * XXX This is basically how FreeBSD dlfunc() silences a compiler warning
85      * about a data/function pointer conversion. The solution below is non-
86      * portable: it assumes that both data and function pointers are the same
87      * in size, and that both have the same representation.
88      */
89     union {
90 	void   *dptr;			/* data pointer */
91 	void    (*fptr) (void);		/* function pointer */
92     }       non_portable_union;
93 
94     if ((handle = dlopen(libname, RTLD_NOW)) == 0) {
95 	emsg = dlerror();
96 	msg_fatal("%s: dlopen failure loading %s: %s", myname, libname,
97 		  emsg ? emsg : "don't know why");
98     }
99     if (libfuncs) {
100 	for (fn = libfuncs; fn->name; fn++) {
101 	    if ((non_portable_union.dptr = dlsym(handle, fn->name)) == 0) {
102 		emsg = dlerror();
103 		msg_fatal("%s: dlsym failure looking up %s in %s: %s", myname,
104 			  fn->name, libname, emsg ? emsg : "don't know why");
105 	    }
106 	    fn->fptr = non_portable_union.fptr;
107 	    if (msg_verbose > 1)
108 		msg_info("loaded %s = %p", fn->name, non_portable_union.dptr);
109 	}
110     }
111     if (libdata) {
112 	for (dp = libdata; dp->name; dp++) {
113 	    if ((dp->dptr = dlsym(handle, dp->name)) == 0) {
114 		emsg = dlerror();
115 		msg_fatal("%s: dlsym failure looking up %s in %s: %s", myname,
116 			  dp->name, libname, emsg ? emsg : "don't know why");
117 	    }
118 	    if (msg_verbose > 1)
119 		msg_info("loaded %s = %p", dp->name, dp->dptr);
120 	}
121     }
122 #elif defined(HAS_SHL_LOAD)
123     shl_t   handle;
124 
125     handle = shl_load(libname, BIND_IMMEDIATE, 0);
126 
127     if (libfuncs) {
128 	for (fn = libfuncs; fn->name; fn++) {
129 	    if (shl_findsym(&handle, fn->name, TYPE_PROCEDURE, &fn->fptr) != 0)
130 		msg_fatal("%s: shl_findsym failure looking up %s in %s: %m",
131 			  myname, fn->name, libname);
132 	    if (msg_verbose > 1)
133 		msg_info("loaded %s = %p", fn->name, (void *) fn->fptr);
134 	}
135     }
136     if (libdata) {
137 	for (dp = libdata; dp->name; dp++) {
138 	    if (shl_findsym(&handle, dp->name, TYPE_DATA, &dp->dptr) != 0)
139 		msg_fatal("%s: shl_findsym failure looking up %s in %s: %m",
140 			  myname, dp->name, libname);
141 	    if (msg_verbose > 1)
142 		msg_info("loaded %s = %p", dp->name, dp->dptr);
143 	}
144     }
145 #endif
146 }
147 
148 #endif
149