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