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