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