Finish thread state machine: fixes global destruction of threads,
[p5sagit/p5-mst-13.2.git] / win32 / win32io.c
CommitLineData
68dc0745 1
2#ifdef __cplusplus
3extern "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>
5aabfad6 19#include <direct.h>
68dc0745 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
28static int *
29dummy_errno(void)
30{
31 return (&(errno));
32}
33
dcb2879a 34static char ***
35dummy_environ(void)
36{
37 return (&(_environ));
38}
39
68dc0745 40/* the rest are the remapped stdio routines */
41static FILE *
42dummy_stderr(void)
43{
44 return stderr;
45}
46
47static FILE *
48dummy_stdin(void)
49{
50 return stdin;
51}
52
53static FILE *
54dummy_stdout(void)
55{
56 return stdout;
57}
58
59static int
60dummy_globalmode(int mode)
61{
62 int o = _fmode;
63 _fmode = mode;
64
65 return o;
66}
67
3e3baf6d 68#if defined(_DLL) || defined(__BORLANDC__)
137443ea 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
68dc0745 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
83EXT_C_FUNC int __cdecl _alloc_osfhnd(void);
84EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value);
85EXT_C_FUNC void __cdecl _lock_fhandle(int);
86EXT_C_FUNC void __cdecl _unlock_fhandle(int);
87EXT_C_FUNC void __cdecl _unlock(int);
88
89#if (_MSC_VER >= 1000)
90typedef 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
100EXT_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) */
108extern 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
141int
142my_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
3e3baf6d 150 if(flags & O_APPEND)
68dc0745 151 fileflags |= FAPPEND;
152
3e3baf6d 153 if(flags & O_TEXT)
68dc0745 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
180int __cdecl
137443ea 181my_open_osfhandle(long osfhandle, int flags)
68dc0745 182{
183 return _open_osfhandle(osfhandle, flags);
184}
185#endif /* _M_IX86 */
186
187long
188my_get_osfhandle( int filehandle )
189{
190 return _get_osfhandle(filehandle);
191}
192
3e3baf6d 193#ifdef __BORLANDC__
194#define _chdir chdir
195#endif
c90c0ff4 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
203int
204my_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
54310121 242#ifdef PERLDLL
243__declspec(dllexport)
244#endif
68dc0745 245WIN32_IOSUBSYSTEM win32stdio = {
246 12345678L, /* begin of structure; */
247 dummy_errno, /* (*pfunc_errno)(void); */
dcb2879a 248 dummy_environ, /* (*pfunc_environ)(void); */
68dc0745 249 dummy_stdin, /* (*pfunc_stdin)(void); */
250 dummy_stdout, /* (*pfunc_stdout)(void); */
251 dummy_stderr, /* (*pfunc_stderr)(void); */
252 ferror, /* (*pfunc_ferror)(FILE *fp); */
253 feof, /* (*pfunc_feof)(FILE *fp); */
254 strerror, /* (*strerror)(int e); */
255 vfprintf, /* (*pfunc_vfprintf)(FILE *pf, const char *format, va_list arg); */
256 vprintf, /* (*pfunc_vprintf)(const char *format, va_list arg); */
257 fread, /* (*pfunc_fread)(void *buf, size_t size, size_t count, FILE *pf); */
258 fwrite, /* (*pfunc_fwrite)(void *buf, size_t size, size_t count, FILE *pf); */
259 fopen, /* (*pfunc_fopen)(const char *path, const char *mode); */
260 fdopen, /* (*pfunc_fdopen)(int fh, const char *mode); */
261 freopen, /* (*pfunc_freopen)(const char *path, const char *mode, FILE *pf); */
262 fclose, /* (*pfunc_fclose)(FILE *pf); */
263 fputs, /* (*pfunc_fputs)(const char *s,FILE *pf); */
264 fputc, /* (*pfunc_fputc)(int c,FILE *pf); */
265 ungetc, /* (*pfunc_ungetc)(int c,FILE *pf); */
266 getc, /* (*pfunc_getc)(FILE *pf); */
267 fileno, /* (*pfunc_fileno)(FILE *pf); */
268 clearerr, /* (*pfunc_clearerr)(FILE *pf); */
269 fflush, /* (*pfunc_fflush)(FILE *pf); */
270 ftell, /* (*pfunc_ftell)(FILE *pf); */
271 fseek, /* (*pfunc_fseek)(FILE *pf,long offset,int origin); */
272 fgetpos, /* (*pfunc_fgetpos)(FILE *pf,fpos_t *p); */
273 fsetpos, /* (*pfunc_fsetpos)(FILE *pf,fpos_t *p); */
274 rewind, /* (*pfunc_rewind)(FILE *pf); */
275 tmpfile, /* (*pfunc_tmpfile)(void); */
276 abort, /* (*pfunc_abort)(void); */
277 fstat, /* (*pfunc_fstat)(int fd,struct stat *bufptr); */
278 stat, /* (*pfunc_stat)(const char *name,struct stat *bufptr); */
279 _pipe, /* (*pfunc_pipe)( int *phandles, unsigned int psize, int textmode ); */
280 _popen, /* (*pfunc_popen)( const char *command, const char *mode ); */
281 _pclose, /* (*pfunc_pclose)( FILE *pf); */
282 setmode, /* (*pfunc_setmode)( int fd, int mode); */
283 lseek, /* (*pfunc_lseek)( int fd, long offset, int origin); */
284 tell, /* (*pfunc_tell)( int fd); */
285 dup, /* (*pfunc_dup)( int fd); */
286 dup2, /* (*pfunc_dup2)(int h1, int h2); */
287 open, /* (*pfunc_open)(const char *path, int oflag,...); */
288 close, /* (*pfunc_close)(int fd); */
289 eof, /* (*pfunc_eof)(int fd); */
290 read, /* (*pfunc_read)(int fd, void *buf, unsigned int cnt); */
291 write, /* (*pfunc_write)(int fd, const void *buf, unsigned int cnt); */
292 dummy_globalmode, /* (*pfunc_globalmode)(int mode) */
293 my_open_osfhandle,
294 my_get_osfhandle,
3e3baf6d 295 spawnvp,
84902520 296 mkdir,
297 rmdir,
298 chdir,
c90c0ff4 299 my_flock, /* (*pfunc_flock)(int fd, int oper) */
6890e559 300 execvp,
84902520 301 perror,
302 setbuf,
303 setvbuf,
304 flushall,
305 fcloseall,
306 fgets,
307 gets,
308 fgetc,
309 putc,
310 puts,
311 getchar,
312 putchar,
313 fscanf,
314 scanf,
315 malloc,
316 calloc,
317 realloc,
318 free,
68dc0745 319 87654321L, /* end of structure */
320};
321
322
323#ifdef __cplusplus
324}
325#endif
326