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

Last change on this file was 3224, checked in by bird, 18 years ago

Resolve the path before attempting to load anything.

  • 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 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
150void *
151dlsym(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
170const char *
171dlerror(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
193int
194dlclose(void *handle)
195{
196 ULONG rc;
197
198 if ((rc = DosFreeModule((HMODULE)handle)) == 0) return 0;
199
200 retcode = rc;
201 return 2;
202}
Note: See TracBrowser for help on using the repository browser.