xref: /openbsd/gnu/usr.bin/perl/os2/dl_os2.c (revision 264ca280)
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 }
196