1 /*
2  * Cross Platform dso/dll load abstraction
3  * Copyright(C) 2008 Michael Jerris
4  *
5  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
6  * copies of the Software, and permit persons to whom the Software is
7  * furnished to do so.
8  *
9  * This work is provided under this license on an "as is" basis, without warranty of any kind,
10  * either expressed or implied, including, without limitation, warranties that the covered code
11  * is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire
12  * risk as to the quality and performance of the covered code is with you. Should any covered
13  * code prove defective in any respect, you (not the initial developer or any other contributor)
14  * assume the cost of any necessary servicing, repair or correction. This disclaimer of warranty
15  * constitutes an essential part of this license. No use of any covered code is authorized hereunder
16  * except under this disclaimer.
17  *
18  */
19 
20 #include <switch.h>
21 #include "switch_dso.h"
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #ifdef WIN32
26 
switch_dso_destroy(switch_dso_lib_t * lib)27 SWITCH_DECLARE(void) switch_dso_destroy(switch_dso_lib_t *lib)
28 {
29 	if (lib && *lib) {
30 		FreeLibrary(*lib);
31 		*lib = NULL;
32 	}
33 }
34 
switch_dso_open(const char * path,int global,char ** err)35 SWITCH_DECLARE(switch_dso_lib_t) switch_dso_open(const char *path, int global, char **err)
36 {
37 	HINSTANCE lib;
38 
39 	lib = LoadLibraryEx(path, NULL, 0);
40 
41 	if (!lib) {
42 		LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
43 	}
44 
45 	if (!lib) {
46 		DWORD error = GetLastError();
47 		*err = switch_mprintf("dll open error [%ul]\n", error);
48 	}
49 
50 	return lib;
51 }
52 
switch_dso_func_sym(switch_dso_lib_t lib,const char * sym,char ** err)53 SWITCH_DECLARE(switch_dso_func_t) switch_dso_func_sym(switch_dso_lib_t lib, const char *sym, char **err)
54 {
55 	FARPROC func = GetProcAddress(lib, sym);
56 	if (!func) {
57 		DWORD error = GetLastError();
58 		*err = switch_mprintf("dll sym error [%ul]\n", error);
59 	}
60 	return (switch_dso_func_t) func;
61 }
62 
switch_dso_data_sym(switch_dso_lib_t lib,const char * sym,char ** err)63 SWITCH_DECLARE(void *) switch_dso_data_sym(switch_dso_lib_t lib, const char *sym, char **err)
64 {
65 	FARPROC addr = GetProcAddress(lib, sym);
66 	if (!addr) {
67 		DWORD error = GetLastError();
68 		*err = switch_mprintf("dll sym error [%ul]\n", error);
69 	}
70 	return (void *) (intptr_t) addr;
71 }
72 
73 
74 #else
75 /*
76 ** {========================================================================
77 ** This is an implementation of loadlib based on the dlfcn interface.
78 ** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,
79 ** NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least
80 ** as an emulation layer on top of native functions.
81 ** =========================================================================
82 */
83 
84 
85 #include <dlfcn.h>
86 
switch_dso_destroy(switch_dso_lib_t * lib)87 void switch_dso_destroy(switch_dso_lib_t *lib)
88 {
89 	if (lib && *lib) {
90 		dlclose(*lib);
91 		*lib = NULL;
92 	}
93 }
94 
switch_dso_open(const char * path,int global,char ** err)95 switch_dso_lib_t switch_dso_open(const char *path, int global, char **err)
96 {
97 	void *lib;
98 
99 	if (global) {
100 		lib = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
101 	} else {
102 		lib = dlopen(path, RTLD_NOW | RTLD_LOCAL);
103 	}
104 
105 	if (lib == NULL) {
106 		const char *dlerr = dlerror();
107 		/* Work around broken uclibc returning NULL on both dlopen() and dlerror() */
108 		if (dlerr) {
109 			*err = strdup(dlerr);
110 		} else {
111 			*err = strdup("Unknown error");
112 		}
113 	}
114 	return lib;
115 }
116 
switch_dso_func_sym(switch_dso_lib_t lib,const char * sym,char ** err)117 switch_dso_func_t switch_dso_func_sym(switch_dso_lib_t lib, const char *sym, char **err)
118 {
119 	void *func = dlsym(lib, sym);
120 	if (!func) {
121 		*err = strdup(dlerror());
122 	}
123 	return (switch_dso_func_t) (intptr_t) func;
124 }
125 
switch_dso_data_sym(switch_dso_lib_t lib,const char * sym,char ** err)126 void *switch_dso_data_sym(switch_dso_lib_t lib, const char *sym, char **err)
127 {
128 	void *addr = dlsym(lib, sym);
129 	if (!addr) {
130 		char *err_str = NULL;
131 		dlerror();
132 
133 		if (!(addr = dlsym(lib, sym))) {
134 			err_str = (char *)dlerror();
135 		}
136 
137 		if (err_str) {
138 			*err = strdup(err_str);
139 		}
140 	}
141 	return addr;
142 }
143 
144 #endif
145 /* }====================================================== */
146 
147 /* For Emacs:
148  * Local Variables:
149  * mode:c
150  * indent-tabs-mode:t
151  * tab-width:4
152  * c-basic-offset:4
153  * End:
154  * For VIM:
155  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet
156  */
157