source: trunk/essentials/dev-lang/perl/os2/dl_os2.c@ 3210

Last change on this file since 3210 was 3206, checked in by bird, 19 years ago

Fixed the fork crash.

  • Property svn:eol-style set to native
File size: 4.0 KB
Line 
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
12static ULONG retcode;
13static char fail[300];
14
15static ULONG dllHandle;
16static int handle_found;
17static int handle_loaded;
18#ifdef PERL_CORE
19
20#include "EXTERN.h"
21#include "perl.h"
22
23#else
24
25char *os2error(int rc);
26
27#endif
28
29#ifdef DLOPEN_INITTERM
30unsigned 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
50HMODULE
51find_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
80void *
81dlopen(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 if ((rc = DosLoadModule(fail, sizeof fail, (char*)path, &handle)) == 0)
116 goto ret;
117
118 retcode = rc;
119
120 if (strlen(path) >= sizeof(tmp))
121 return NULL;
122
123 /* Not found. Check for non-FAT name and try truncated name. */
124 /* Don't know if this helps though... */
125 for (beg = dot = path + strlen(path);
126 beg > path && !strchr(":/\\", *(beg-1));
127 beg--)
128 if (*beg == '.')
129 dot = beg;
130 if (dot - beg > 8) {
131 int n = beg+8-path;
132
133 memmove(tmp, path, n);
134 memmove(tmp+n, dot, strlen(dot)+1);
135 if (DosLoadModule(fail, sizeof fail, tmp, &handle) == 0)
136 goto ret;
137 }
138 handle = 0;
139
140 ret:
141 _control87(fpflag, MCW_EM); /* Some modules reset FP flags on load */
142 return (void *)handle;
143}
144
145#define ERROR_WRONG_PROCTYPE 0xffffffff
146
147void *
148dlsym(void *handle, const char *symbol)
149{
150 ULONG rc, type;
151 PFN addr;
152
153 fail[0] = 0;
154
155 rc = DosQueryProcAddr((HMODULE)handle, 0, symbol, &addr);
156 if (rc == 0) {
157 rc = DosQueryProcType((HMODULE)handle, 0, symbol, &type);
158 if (rc == 0 && type == PT_32BIT)
159 return (void *)addr;
160 rc = ERROR_WRONG_PROCTYPE;
161 }
162
163 retcode = rc;
164 return NULL;
165}
166
167char *
168dlerror(void)
169{
170 static char buf[700];
171 ULONG len;
172 char *err;
173
174 if (retcode == 0)
175 return NULL;
176 if (retcode == ERROR_WRONG_PROCTYPE)
177 err = "Wrong procedure type";
178 else
179 err = os2error(retcode);
180 len = strlen(err);
181 if (len > sizeof(buf) - 1)
182 len = sizeof(buf) - 1;
183 strncpy(buf, err, len+1);
184 if (fail[0] && len + strlen(fail) < sizeof(buf) - 100)
185 sprintf(buf + len, ", possible problematic module: '%s'", fail);
186 retcode = 0;
187 return buf;
188}
189
190int
191dlclose(void *handle)
192{
193 ULONG rc;
194
195 if ((rc = DosFreeModule((HMODULE)handle)) == 0) return 0;
196
197 retcode = rc;
198 return 2;
199}
Note: See TracBrowser for help on using the repository browser.