Commit | Line | Data |
0a753a76 |
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 | |
20 | #include "win32iop.h" |
21 | |
22 | // |
23 | // The following is just a basic wrapping of the stdio |
24 | // |
25 | // |
26 | // redirected io subsystem for all XS modules |
27 | // |
28 | // |
29 | |
30 | static int * dummy_errno() |
31 | { |
32 | return (&(errno)); |
33 | } |
34 | |
35 | static FILE *dummy_stderr() |
36 | { |
37 | return stderr; |
38 | } |
39 | |
40 | static FILE *dummy_stdin() |
41 | { |
42 | return stdin; |
43 | } |
44 | |
45 | static FILE *dummy_stdout() |
46 | { |
47 | return stdout; |
48 | } |
49 | |
50 | static int dummy_globalmode(int mode) |
51 | { |
52 | int o = _fmode; |
53 | _fmode = mode; |
54 | |
55 | return o; |
56 | } |
57 | |
58 | |
59 | #if defined(_WIN32) && !defined(WIN95_OSFHANDLE_FIXED) && defined(_M_IX86) |
60 | |
61 | # ifdef __cplusplus |
62 | #define EXT_C_FUNC extern "C" |
63 | # else |
64 | #define EXT_C_FUNC extern |
65 | # endif |
66 | |
67 | EXT_C_FUNC int __cdecl _alloc_osfhnd(void); |
68 | EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value); |
69 | EXT_C_FUNC void __cdecl _lock_fhandle(int); |
70 | EXT_C_FUNC void __cdecl _unlock_fhandle(int); |
71 | EXT_C_FUNC void __cdecl _unlock(int); |
72 | |
73 | #if (_MSC_VER >= 1000) |
74 | typedef struct |
75 | { |
76 | long osfhnd; /* underlying OS file HANDLE */ |
77 | char osfile; /* attributes of file (e.g., open in text mode?) */ |
78 | char pipech; /* one char buffer for handles opened on pipes */ |
79 | #if defined (_MT) && !defined (DLL_FOR_WIN32S) |
80 | int lockinitflag; |
81 | CRITICAL_SECTION lock; |
82 | #endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */ |
83 | } ioinfo; |
84 | |
85 | EXT_C_FUNC ioinfo * __pioinfo[]; |
86 | |
87 | #define IOINFO_L2E 5 |
88 | #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) |
89 | #define _pioinfo(i) (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1))) |
90 | #define _osfile(i) (_pioinfo(i)->osfile) |
91 | #else |
92 | extern "C" extern char _osfile[]; |
93 | #endif // (_MSC_VER >= 1000) |
94 | |
95 | #define FOPEN 0x01 // file handle open |
96 | #define FAPPEND 0x20 // file handle opened O_APPEND |
97 | #define FDEV 0x40 // file handle refers to device |
98 | #define FTEXT 0x80 // file handle is in text mode |
99 | |
100 | #define _STREAM_LOCKS 26 // Table of stream locks |
101 | #define _LAST_STREAM_LOCK (_STREAM_LOCKS+_NSTREAM_-1) // Last stream lock |
102 | #define _FH_LOCKS (_LAST_STREAM_LOCK+1) // Table of fh locks |
103 | |
104 | /*** |
105 | *int _patch_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle |
106 | * |
107 | *Purpose: |
108 | * This function allocates a free C Runtime file handle and associates |
109 | * it with the Win32 HANDLE specified by the first parameter. This is a |
110 | * temperary fix for WIN95's brain damage GetFileType() error on socket |
111 | * we just bypass that call for socket |
112 | * |
113 | *Entry: |
114 | * long osfhandle - Win32 HANDLE to associate with C Runtime file handle. |
115 | * int flags - flags to associate with C Runtime file handle. |
116 | * |
117 | *Exit: |
118 | * returns index of entry in fh, if successful |
119 | * return -1, if no free entry is found |
120 | * |
121 | *Exceptions: |
122 | * |
123 | *******************************************************************************/ |
124 | |
125 | int my_open_osfhandle(long osfhandle, int flags) |
126 | { |
127 | int fh; |
128 | char fileflags; // _osfile flags |
129 | |
130 | // copy relevant flags from second parameter |
131 | fileflags = FDEV; |
132 | |
133 | if(flags & _O_APPEND) |
134 | fileflags |= FAPPEND; |
135 | |
136 | if(flags & _O_TEXT) |
137 | fileflags |= FTEXT; |
138 | |
139 | // attempt to allocate a C Runtime file handle |
140 | if((fh = _alloc_osfhnd()) == -1) |
141 | { |
142 | errno = EMFILE; // too many open files |
143 | _doserrno = 0L; // not an OS error |
144 | return -1; // return error to caller |
145 | } |
146 | |
147 | // the file is open. now, set the info in _osfhnd array |
148 | _set_osfhnd(fh, osfhandle); |
149 | |
150 | fileflags |= FOPEN; // mark as open |
151 | |
152 | #if (_MSC_VER >= 1000) |
153 | _osfile(fh) = fileflags; // set osfile entry |
154 | _unlock_fhandle(fh); |
155 | #else |
156 | _osfile[fh] = fileflags; // set osfile entry |
157 | _unlock(fh+_FH_LOCKS); // unlock handle |
158 | #endif |
159 | |
160 | |
161 | return fh; // return handle |
162 | } |
163 | #else |
164 | int __cdecl stolen_open_osfhandle(long osfhandle, int flags) |
165 | { |
166 | return _open_osfhandle(osfhandle, flags); |
167 | } |
168 | #endif // _M_IX86 |
169 | |
170 | long my_get_osfhandle( int filehandle ) |
171 | { |
172 | return _get_osfhandle(filehandle); |
173 | } |
174 | |
175 | WIN32_IOSUBSYSTEM win32stdio = { |
176 | 12345678L, // begin of structure; |
177 | dummy_errno, // (*pfunc_errno)(void); |
178 | dummy_stdin, // (*pfunc_stdin)(void); |
179 | dummy_stdout, // (*pfunc_stdout)(void); |
180 | dummy_stderr, // (*pfunc_stderr)(void); |
181 | ferror, // (*pfunc_ferror)(FILE *fp); |
182 | feof, // (*pfunc_feof)(FILE *fp); |
183 | strerror, // (*strerror)(int e); |
184 | vfprintf, // (*pfunc_vfprintf)(FILE *pf, const char *format, va_list arg); |
185 | vprintf, // (*pfunc_vprintf)(const char *format, va_list arg); |
186 | fread, // (*pfunc_fread)(void *buf, size_t size, size_t count, FILE *pf); |
187 | fwrite, // (*pfunc_fwrite)(void *buf, size_t size, size_t count, FILE *pf); |
188 | fopen, // (*pfunc_fopen)(const char *path, const char *mode); |
189 | fdopen, // (*pfunc_fdopen)(int fh, const char *mode); |
190 | freopen, // (*pfunc_freopen)(const char *path, const char *mode, FILE *pf); |
191 | fclose, // (*pfunc_fclose)(FILE *pf); |
192 | fputs, // (*pfunc_fputs)(const char *s,FILE *pf); |
193 | fputc, // (*pfunc_fputc)(int c,FILE *pf); |
194 | ungetc, // (*pfunc_ungetc)(int c,FILE *pf); |
195 | getc, // (*pfunc_getc)(FILE *pf); |
196 | fileno, // (*pfunc_fileno)(FILE *pf); |
197 | clearerr, // (*pfunc_clearerr)(FILE *pf); |
198 | fflush, // (*pfunc_fflush)(FILE *pf); |
199 | ftell, // (*pfunc_ftell)(FILE *pf); |
200 | fseek, // (*pfunc_fseek)(FILE *pf,long offset,int origin); |
201 | fgetpos, // (*pfunc_fgetpos)(FILE *pf,fpos_t *p); |
202 | fsetpos, // (*pfunc_fsetpos)(FILE *pf,fpos_t *p); |
203 | rewind, // (*pfunc_rewind)(FILE *pf); |
204 | tmpfile, // (*pfunc_tmpfile)(void); |
205 | abort, // (*pfunc_abort)(void); |
206 | fstat, // (*pfunc_fstat)(int fd,struct stat *bufptr); |
207 | stat, // (*pfunc_stat)(const char *name,struct stat *bufptr); |
208 | _pipe, // (*pfunc_pipe)( int *phandles, unsigned int psize, int textmode ); |
209 | _popen, // (*pfunc_popen)( const char *command, const char *mode ); |
210 | _pclose, // (*pfunc_pclose)( FILE *pf); |
211 | setmode, // (*pfunc_setmode)( int fd, int mode); |
212 | lseek, // (*pfunc_lseek)( int fd, long offset, int origin); |
213 | tell, // (*pfunc_tell)( int fd); |
214 | dup, // (*pfunc_dup)( int fd); |
215 | dup2, // (*pfunc_dup2)(int h1, int h2); |
216 | open, // (*pfunc_open)(const char *path, int oflag,...); |
217 | close, // (*pfunc_close)(int fd); |
218 | eof, // (*pfunc_eof)(int fd); |
219 | read, // (*pfunc_read)(int fd, void *buf, unsigned int cnt); |
220 | write, // (*pfunc_write)(int fd, const void *buf, unsigned int cnt); |
221 | dummy_globalmode,// (*pfunc_globalmode)(int mode) |
222 | my_open_osfhandle, |
223 | my_get_osfhandle, |
224 | spawnvpe, |
225 | 87654321L, // end of structure |
226 | }; |
227 | |
228 | |
229 | #ifdef __cplusplus |
230 | } |
231 | #endif |