1 | #include "dlfcn.h"
|
---|
2 | #include "string.h"
|
---|
3 | #include "stdio.h"
|
---|
4 |
|
---|
5 | #define INCL_EXAPIS
|
---|
6 | #define INCL_EXAPIS_MAPPINGS
|
---|
7 | #define INCL_BASE
|
---|
8 | #include <os2.h>
|
---|
9 | #include <float.h>
|
---|
10 | #include <stdlib.h>
|
---|
11 |
|
---|
12 | static ULONG retcode;
|
---|
13 | static char fail[300];
|
---|
14 |
|
---|
15 | static ULONG dllHandle;
|
---|
16 | static int handle_found;
|
---|
17 | static int handle_loaded;
|
---|
18 | #ifdef PERL_CORE
|
---|
19 |
|
---|
20 | #include "EXTERN.h"
|
---|
21 | #include "perl.h"
|
---|
22 |
|
---|
23 | #else
|
---|
24 |
|
---|
25 | char *os2error(int rc);
|
---|
26 |
|
---|
27 | #endif
|
---|
28 |
|
---|
29 | #ifdef DLOPEN_INITTERM
|
---|
30 | unsigned long _DLL_InitTerm(unsigned long modHandle, unsigned long flag)
|
---|
31 | {
|
---|
32 | switch (flag) {
|
---|
33 | case 0: /* INIT */
|
---|
34 | /* Save handle */
|
---|
35 | dllHandle = modHandle;
|
---|
36 | handle_found = 1;
|
---|
37 | return TRUE;
|
---|
38 |
|
---|
39 | case 1: /* TERM */
|
---|
40 | handle_found = 0;
|
---|
41 | dllHandle = (unsigned long)NULLHANDLE;
|
---|
42 | return TRUE;
|
---|
43 | }
|
---|
44 |
|
---|
45 | return FALSE;
|
---|
46 | }
|
---|
47 |
|
---|
48 | #endif
|
---|
49 |
|
---|
50 | HMODULE
|
---|
51 | find_myself(void)
|
---|
52 | {
|
---|
53 |
|
---|
54 | static APIRET APIENTRY (*pDosQueryModFromEIP) (HMODULE * hmod, ULONG * obj, ULONG BufLen, PCHAR Buf,
|
---|
55 | ULONG * Offset, ULONG Address);
|
---|
56 | HMODULE doscalls_h, mod;
|
---|
57 | static int failed;
|
---|
58 | ULONG obj, offset, rc;
|
---|
59 | char buf[260];
|
---|
60 |
|
---|
61 | if (failed)
|
---|
62 | return 0;
|
---|
63 | failed = 1;
|
---|
64 | doscalls_h = (HMODULE)dlopen("DOSCALLS",0);
|
---|
65 | if (!doscalls_h)
|
---|
66 | return 0;
|
---|
67 | /* {&doscalls_handle, NULL, 360}, */ /* DosQueryModFromEIP */
|
---|
68 | rc = DosQueryProcAddr(doscalls_h, 360, 0, (PFN*)&pDosQueryModFromEIP);
|
---|
69 | if (rc)
|
---|
70 | return 0;
|
---|
71 | rc = pDosQueryModFromEIP(&mod, &obj, sizeof(buf), buf, &offset, (ULONG)dlopen);
|
---|
72 | if (rc)
|
---|
73 | return 0;
|
---|
74 | failed = 0;
|
---|
75 | handle_found = 1;
|
---|
76 | dllHandle = mod;
|
---|
77 | return mod;
|
---|
78 | }
|
---|
79 |
|
---|
80 | void *
|
---|
81 | dlopen(const char *path, int mode)
|
---|
82 | {
|
---|
83 | HMODULE handle;
|
---|
84 | char tmp[260];
|
---|
85 | const char *beg, *dot;
|
---|
86 | ULONG rc;
|
---|
87 | unsigned fpflag = _control87(0,0);
|
---|
88 |
|
---|
89 | fail[0] = 0;
|
---|
90 | if (!path) { /* Our own handle. */
|
---|
91 | if (handle_found || find_myself()) {
|
---|
92 | char dllname[260];
|
---|
93 |
|
---|
94 | if (handle_loaded)
|
---|
95 | return (void*)dllHandle;
|
---|
96 | rc = DosQueryModuleName(dllHandle, sizeof(dllname), dllname);
|
---|
97 | if (rc) {
|
---|
98 | strcpy(fail, "can't find my DLL name by the handle");
|
---|
99 | retcode = rc;
|
---|
100 | return 0;
|
---|
101 | }
|
---|
102 | rc = DosLoadModule(fail, sizeof fail, dllname, &handle);
|
---|
103 | if (rc) {
|
---|
104 | strcpy(fail, "can't load my own DLL");
|
---|
105 | retcode = rc;
|
---|
106 | return 0;
|
---|
107 | }
|
---|
108 | handle_loaded = 1;
|
---|
109 | goto ret;
|
---|
110 | }
|
---|
111 | retcode = ERROR_MOD_NOT_FOUND;
|
---|
112 | strcpy(fail, "can't load from myself: compiled without -DDLOPEN_INITTERM");
|
---|
113 | return 0;
|
---|
114 | }
|
---|
115 | beg = tmp;
|
---|
116 | if (!_realrealpath(path, tmp, sizeof(tmp)))
|
---|
117 | beg = path;
|
---|
118 | if ((rc = DosLoadModule(fail, sizeof fail, (char *)beg, &handle)) == 0)
|
---|
119 | goto ret;
|
---|
120 |
|
---|
121 | retcode = rc;
|
---|
122 |
|
---|
123 | if (strlen(path) >= sizeof(tmp))
|
---|
124 | return NULL;
|
---|
125 |
|
---|
126 | /* Not found. Check for non-FAT name and try truncated name. */
|
---|
127 | /* Don't know if this helps though... */
|
---|
128 | for (beg = dot = path + strlen(path);
|
---|
129 | beg > path && !strchr(":/\\", *(beg-1));
|
---|
130 | beg--)
|
---|
131 | if (*beg == '.')
|
---|
132 | dot = beg;
|
---|
133 | if (dot - beg > 8) {
|
---|
134 | int n = beg+8-path;
|
---|
135 |
|
---|
136 | memmove(tmp, path, n);
|
---|
137 | memmove(tmp+n, dot, strlen(dot)+1);
|
---|
138 | if (DosLoadModule(fail, sizeof fail, tmp, &handle) == 0)
|
---|
139 | goto ret;
|
---|
140 | }
|
---|
141 | handle = 0;
|
---|
142 |
|
---|
143 | ret:
|
---|
144 | _control87(fpflag, MCW_EM); /* Some modules reset FP flags on load */
|
---|
145 | return (void *)handle;
|
---|
146 | }
|
---|
147 |
|
---|
148 | #define ERROR_WRONG_PROCTYPE 0xffffffff
|
---|
149 |
|
---|
150 | void *
|
---|
151 | dlsym(void *handle, const char *symbol)
|
---|
152 | {
|
---|
153 | ULONG rc, type;
|
---|
154 | PFN addr;
|
---|
155 |
|
---|
156 | fail[0] = 0;
|
---|
157 |
|
---|
158 | rc = DosQueryProcAddr((HMODULE)handle, 0, symbol, &addr);
|
---|
159 | if (rc == 0) {
|
---|
160 | rc = DosQueryProcType((HMODULE)handle, 0, symbol, &type);
|
---|
161 | if (rc == 0 && type == PT_32BIT)
|
---|
162 | return (void *)addr;
|
---|
163 | rc = ERROR_WRONG_PROCTYPE;
|
---|
164 | }
|
---|
165 |
|
---|
166 | retcode = rc;
|
---|
167 | return NULL;
|
---|
168 | }
|
---|
169 |
|
---|
170 | const char *
|
---|
171 | dlerror(void)
|
---|
172 | {
|
---|
173 | static char buf[700];
|
---|
174 | ULONG len;
|
---|
175 | char *err;
|
---|
176 |
|
---|
177 | if (retcode == 0)
|
---|
178 | return NULL;
|
---|
179 | if (retcode == ERROR_WRONG_PROCTYPE)
|
---|
180 | err = "Wrong procedure type";
|
---|
181 | else
|
---|
182 | err = os2error(retcode);
|
---|
183 | len = strlen(err);
|
---|
184 | if (len > sizeof(buf) - 1)
|
---|
185 | len = sizeof(buf) - 1;
|
---|
186 | strncpy(buf, err, len+1);
|
---|
187 | if (fail[0] && len + strlen(fail) < sizeof(buf) - 100)
|
---|
188 | sprintf(buf + len, ", possible problematic module: '%s'", fail);
|
---|
189 | retcode = 0;
|
---|
190 | return buf;
|
---|
191 | }
|
---|
192 |
|
---|
193 | int
|
---|
194 | dlclose(void *handle)
|
---|
195 | {
|
---|
196 | ULONG rc;
|
---|
197 |
|
---|
198 | if ((rc = DosFreeModule((HMODULE)handle)) == 0) return 0;
|
---|
199 |
|
---|
200 | retcode = rc;
|
---|
201 | return 2;
|
---|
202 | }
|
---|