1 | |
---|
2 | #ifdef __cplusplus |
---|
3 | extern "C" { |
---|
4 | #endif |
---|
5 | |
---|
6 | #define WIN32_LEAN_AND_MEAN |
---|
7 | #define WIN32IO_IS_STDIO |
---|
8 | #define EXT |
---|
9 | #include <windows.h> |
---|
10 | #include <stdio.h> |
---|
11 | #include <stdlib.h> |
---|
12 | #include <io.h> |
---|
13 | #include <sys/stat.h> |
---|
14 | #include <sys/socket.h> |
---|
15 | #include <fcntl.h> |
---|
16 | #include <assert.h> |
---|
17 | #include <errno.h> |
---|
18 | #include <process.h> |
---|
19 | #include <direct.h> |
---|
20 | #include "win32iop.h" |
---|
21 | |
---|
22 | /* |
---|
23 | * The following is just a basic wrapping of the stdio |
---|
24 | * |
---|
25 | * redirected io subsystem for all XS modules |
---|
26 | */ |
---|
27 | |
---|
28 | static int * |
---|
29 | dummy_errno(void) |
---|
30 | { |
---|
31 | return (&(errno)); |
---|
32 | } |
---|
33 | |
---|
34 | static char *** |
---|
35 | dummy_environ(void) |
---|
36 | { |
---|
37 | return (&(_environ)); |
---|
38 | } |
---|
39 | |
---|
40 | /* the rest are the remapped stdio routines */ |
---|
41 | static FILE * |
---|
42 | dummy_stderr(void) |
---|
43 | { |
---|
44 | return stderr; |
---|
45 | } |
---|
46 | |
---|
47 | static FILE * |
---|
48 | dummy_stdin(void) |
---|
49 | { |
---|
50 | return stdin; |
---|
51 | } |
---|
52 | |
---|
53 | static FILE * |
---|
54 | dummy_stdout(void) |
---|
55 | { |
---|
56 | return stdout; |
---|
57 | } |
---|
58 | |
---|
59 | static int |
---|
60 | dummy_globalmode(int mode) |
---|
61 | { |
---|
62 | int o = _fmode; |
---|
63 | _fmode = mode; |
---|
64 | |
---|
65 | return o; |
---|
66 | } |
---|
67 | |
---|
68 | #if defined(_DLL) || defined(__BORLANDC__) |
---|
69 | /* It may or may not be fixed (ok on NT), but DLL runtime |
---|
70 | does not export the functions used in the workround |
---|
71 | */ |
---|
72 | #define WIN95_OSFHANDLE_FIXED |
---|
73 | #endif |
---|
74 | |
---|
75 | #if defined(_WIN32) && !defined(WIN95_OSFHANDLE_FIXED) && defined(_M_IX86) |
---|
76 | |
---|
77 | # ifdef __cplusplus |
---|
78 | #define EXT_C_FUNC extern "C" |
---|
79 | # else |
---|
80 | #define EXT_C_FUNC extern |
---|
81 | # endif |
---|
82 | |
---|
83 | EXT_C_FUNC int __cdecl _alloc_osfhnd(void); |
---|
84 | EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value); |
---|
85 | EXT_C_FUNC void __cdecl _lock_fhandle(int); |
---|
86 | EXT_C_FUNC void __cdecl _unlock_fhandle(int); |
---|
87 | EXT_C_FUNC void __cdecl _unlock(int); |
---|
88 | |
---|
89 | #if (_MSC_VER >= 1000) |
---|
90 | typedef struct { |
---|
91 | long osfhnd; /* underlying OS file HANDLE */ |
---|
92 | char osfile; /* attributes of file (e.g., open in text mode?) */ |
---|
93 | char pipech; /* one char buffer for handles opened on pipes */ |
---|
94 | #if defined (_MT) && !defined (DLL_FOR_WIN32S) |
---|
95 | int lockinitflag; |
---|
96 | CRITICAL_SECTION lock; |
---|
97 | #endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */ |
---|
98 | } ioinfo; |
---|
99 | |
---|
100 | EXT_C_FUNC ioinfo * __pioinfo[]; |
---|
101 | |
---|
102 | #define IOINFO_L2E 5 |
---|
103 | #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) |
---|
104 | #define _pioinfo(i) (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1))) |
---|
105 | #define _osfile(i) (_pioinfo(i)->osfile) |
---|
106 | |
---|
107 | #else /* (_MSC_VER >= 1000) */ |
---|
108 | extern char _osfile[]; |
---|
109 | #endif /* (_MSC_VER >= 1000) */ |
---|
110 | |
---|
111 | #define FOPEN 0x01 /* file handle open */ |
---|
112 | #define FAPPEND 0x20 /* file handle opened O_APPEND */ |
---|
113 | #define FDEV 0x40 /* file handle refers to device */ |
---|
114 | #define FTEXT 0x80 /* file handle is in text mode */ |
---|
115 | |
---|
116 | #define _STREAM_LOCKS 26 /* Table of stream locks */ |
---|
117 | #define _LAST_STREAM_LOCK (_STREAM_LOCKS+_NSTREAM_-1) /* Last stream lock */ |
---|
118 | #define _FH_LOCKS (_LAST_STREAM_LOCK+1) /* Table of fh locks */ |
---|
119 | |
---|
120 | /*** |
---|
121 | *int _patch_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle |
---|
122 | * |
---|
123 | *Purpose: |
---|
124 | * This function allocates a free C Runtime file handle and associates |
---|
125 | * it with the Win32 HANDLE specified by the first parameter. This is a |
---|
126 | * temperary fix for WIN95's brain damage GetFileType() error on socket |
---|
127 | * we just bypass that call for socket |
---|
128 | * |
---|
129 | *Entry: |
---|
130 | * long osfhandle - Win32 HANDLE to associate with C Runtime file handle. |
---|
131 | * int flags - flags to associate with C Runtime file handle. |
---|
132 | * |
---|
133 | *Exit: |
---|
134 | * returns index of entry in fh, if successful |
---|
135 | * return -1, if no free entry is found |
---|
136 | * |
---|
137 | *Exceptions: |
---|
138 | * |
---|
139 | *******************************************************************************/ |
---|
140 | |
---|
141 | int |
---|
142 | my_open_osfhandle(long osfhandle, int flags) |
---|
143 | { |
---|
144 | int fh; |
---|
145 | char fileflags; /* _osfile flags */ |
---|
146 | |
---|
147 | /* copy relevant flags from second parameter */ |
---|
148 | fileflags = FDEV; |
---|
149 | |
---|
150 | if(flags & O_APPEND) |
---|
151 | fileflags |= FAPPEND; |
---|
152 | |
---|
153 | if(flags & O_TEXT) |
---|
154 | fileflags |= FTEXT; |
---|
155 | |
---|
156 | /* attempt to allocate a C Runtime file handle */ |
---|
157 | if((fh = _alloc_osfhnd()) == -1) { |
---|
158 | errno = EMFILE; /* too many open files */ |
---|
159 | _doserrno = 0L; /* not an OS error */ |
---|
160 | return -1; /* return error to caller */ |
---|
161 | } |
---|
162 | |
---|
163 | /* the file is open. now, set the info in _osfhnd array */ |
---|
164 | _set_osfhnd(fh, osfhandle); |
---|
165 | |
---|
166 | fileflags |= FOPEN; /* mark as open */ |
---|
167 | |
---|
168 | #if (_MSC_VER >= 1000) |
---|
169 | _osfile(fh) = fileflags; /* set osfile entry */ |
---|
170 | _unlock_fhandle(fh); |
---|
171 | #else |
---|
172 | _osfile[fh] = fileflags; /* set osfile entry */ |
---|
173 | _unlock(fh+_FH_LOCKS); /* unlock handle */ |
---|
174 | #endif |
---|
175 | |
---|
176 | return fh; /* return handle */ |
---|
177 | } |
---|
178 | #else |
---|
179 | |
---|
180 | int __cdecl |
---|
181 | my_open_osfhandle(long osfhandle, int flags) |
---|
182 | { |
---|
183 | return _open_osfhandle(osfhandle, flags); |
---|
184 | } |
---|
185 | #endif /* _M_IX86 */ |
---|
186 | |
---|
187 | long |
---|
188 | my_get_osfhandle( int filehandle ) |
---|
189 | { |
---|
190 | return _get_osfhandle(filehandle); |
---|
191 | } |
---|
192 | |
---|
193 | #ifdef __BORLANDC__ |
---|
194 | #define _chdir chdir |
---|
195 | #endif |
---|
196 | |
---|
197 | /* simulate flock by locking a range on the file */ |
---|
198 | |
---|
199 | |
---|
200 | #define LK_ERR(f,i) ((f) ? (i = 0) : (errno = GetLastError())) |
---|
201 | #define LK_LEN 0xffff0000 |
---|
202 | |
---|
203 | int |
---|
204 | my_flock(int fd, int oper) |
---|
205 | { |
---|
206 | OVERLAPPED o; |
---|
207 | int i = -1; |
---|
208 | HANDLE fh; |
---|
209 | |
---|
210 | fh = (HANDLE)my_get_osfhandle(fd); |
---|
211 | memset(&o, 0, sizeof(o)); |
---|
212 | |
---|
213 | switch(oper) { |
---|
214 | case LOCK_SH: /* shared lock */ |
---|
215 | LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i); |
---|
216 | break; |
---|
217 | case LOCK_EX: /* exclusive lock */ |
---|
218 | LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i); |
---|
219 | break; |
---|
220 | case LOCK_SH|LOCK_NB: /* non-blocking shared lock */ |
---|
221 | LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i); |
---|
222 | break; |
---|
223 | case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */ |
---|
224 | LK_ERR(LockFileEx(fh, |
---|
225 | LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, |
---|
226 | 0, LK_LEN, 0, &o),i); |
---|
227 | break; |
---|
228 | case LOCK_UN: /* unlock lock */ |
---|
229 | LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i); |
---|
230 | break; |
---|
231 | default: /* unknown */ |
---|
232 | errno = EINVAL; |
---|
233 | break; |
---|
234 | } |
---|
235 | return i; |
---|
236 | } |
---|
237 | |
---|
238 | #undef LK_ERR |
---|
239 | #undef LK_LEN |
---|
240 | |
---|
241 | EXT int my_fclose(FILE *pf); |
---|
242 | |
---|
243 | #ifdef PERLDLL |
---|
244 | __declspec(dllexport) |
---|
245 | #endif |
---|
246 | WIN32_IOSUBSYSTEM win32stdio = { |
---|
247 | 12345678L, /* begin of structure; */ |
---|
248 | dummy_errno, /* (*pfunc_errno)(void); */ |
---|
249 | dummy_environ, /* (*pfunc_environ)(void); */ |
---|
250 | dummy_stdin, /* (*pfunc_stdin)(void); */ |
---|
251 | dummy_stdout, /* (*pfunc_stdout)(void); */ |
---|
252 | dummy_stderr, /* (*pfunc_stderr)(void); */ |
---|
253 | ferror, /* (*pfunc_ferror)(FILE *fp); */ |
---|
254 | feof, /* (*pfunc_feof)(FILE *fp); */ |
---|
255 | strerror, /* (*strerror)(int e); */ |
---|
256 | vfprintf, /* (*pfunc_vfprintf)(FILE *pf, const char *format, va_list arg); */ |
---|
257 | vprintf, /* (*pfunc_vprintf)(const char *format, va_list arg); */ |
---|
258 | fread, /* (*pfunc_fread)(void *buf, size_t size, size_t count, FILE *pf); */ |
---|
259 | fwrite, /* (*pfunc_fwrite)(void *buf, size_t size, size_t count, FILE *pf); */ |
---|
260 | fopen, /* (*pfunc_fopen)(const char *path, const char *mode); */ |
---|
261 | fdopen, /* (*pfunc_fdopen)(int fh, const char *mode); */ |
---|
262 | freopen, /* (*pfunc_freopen)(const char *path, const char *mode, FILE *pf); */ |
---|
263 | my_fclose, /* (*pfunc_fclose)(FILE *pf); */ |
---|
264 | fputs, /* (*pfunc_fputs)(const char *s,FILE *pf); */ |
---|
265 | fputc, /* (*pfunc_fputc)(int c,FILE *pf); */ |
---|
266 | ungetc, /* (*pfunc_ungetc)(int c,FILE *pf); */ |
---|
267 | getc, /* (*pfunc_getc)(FILE *pf); */ |
---|
268 | fileno, /* (*pfunc_fileno)(FILE *pf); */ |
---|
269 | clearerr, /* (*pfunc_clearerr)(FILE *pf); */ |
---|
270 | fflush, /* (*pfunc_fflush)(FILE *pf); */ |
---|
271 | ftell, /* (*pfunc_ftell)(FILE *pf); */ |
---|
272 | fseek, /* (*pfunc_fseek)(FILE *pf,long offset,int origin); */ |
---|
273 | fgetpos, /* (*pfunc_fgetpos)(FILE *pf,fpos_t *p); */ |
---|
274 | fsetpos, /* (*pfunc_fsetpos)(FILE *pf,fpos_t *p); */ |
---|
275 | rewind, /* (*pfunc_rewind)(FILE *pf); */ |
---|
276 | tmpfile, /* (*pfunc_tmpfile)(void); */ |
---|
277 | abort, /* (*pfunc_abort)(void); */ |
---|
278 | fstat, /* (*pfunc_fstat)(int fd,struct stat *bufptr); */ |
---|
279 | stat, /* (*pfunc_stat)(const char *name,struct stat *bufptr); */ |
---|
280 | _pipe, /* (*pfunc_pipe)( int *phandles, unsigned int psize, int textmode ); */ |
---|
281 | _popen, /* (*pfunc_popen)( const char *command, const char *mode ); */ |
---|
282 | _pclose, /* (*pfunc_pclose)( FILE *pf); */ |
---|
283 | setmode, /* (*pfunc_setmode)( int fd, int mode); */ |
---|
284 | lseek, /* (*pfunc_lseek)( int fd, long offset, int origin); */ |
---|
285 | tell, /* (*pfunc_tell)( int fd); */ |
---|
286 | dup, /* (*pfunc_dup)( int fd); */ |
---|
287 | dup2, /* (*pfunc_dup2)(int h1, int h2); */ |
---|
288 | open, /* (*pfunc_open)(const char *path, int oflag,...); */ |
---|
289 | close, /* (*pfunc_close)(int fd); */ |
---|
290 | eof, /* (*pfunc_eof)(int fd); */ |
---|
291 | read, /* (*pfunc_read)(int fd, void *buf, unsigned int cnt); */ |
---|
292 | write, /* (*pfunc_write)(int fd, const void *buf, unsigned int cnt); */ |
---|
293 | dummy_globalmode, /* (*pfunc_globalmode)(int mode) */ |
---|
294 | my_open_osfhandle, |
---|
295 | my_get_osfhandle, |
---|
296 | spawnvp, |
---|
297 | mkdir, |
---|
298 | rmdir, |
---|
299 | chdir, |
---|
300 | my_flock, /* (*pfunc_flock)(int fd, int oper) */ |
---|
301 | execvp, |
---|
302 | perror, |
---|
303 | setbuf, |
---|
304 | setvbuf, |
---|
305 | flushall, |
---|
306 | fcloseall, |
---|
307 | fgets, |
---|
308 | gets, |
---|
309 | fgetc, |
---|
310 | putc, |
---|
311 | puts, |
---|
312 | getchar, |
---|
313 | putchar, |
---|
314 | fscanf, |
---|
315 | scanf, |
---|
316 | malloc, |
---|
317 | calloc, |
---|
318 | realloc, |
---|
319 | free, |
---|
320 | 87654321L, /* end of structure */ |
---|
321 | }; |
---|
322 | |
---|
323 | |
---|
324 | #ifdef __cplusplus |
---|
325 | } |
---|
326 | #endif |
---|
327 | |
---|