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