Finish thread state machine: fixes global destruction of threads,
[p5sagit/p5-mst-13.2.git] / win32 / win32io.c
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
242 #ifdef PERLDLL
243 __declspec(dllexport)
244 #endif
245 WIN32_IOSUBSYSTEM       win32stdio = {
246     12345678L,          /* begin of structure; */
247     dummy_errno,        /* (*pfunc_errno)(void); */
248     dummy_environ,      /* (*pfunc_environ)(void); */
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,
295     spawnvp,
296     mkdir,
297     rmdir,
298     chdir,
299     my_flock,           /* (*pfunc_flock)(int fd, int oper) */
300     execvp,
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,
319     87654321L,          /* end of structure */
320 };
321
322
323 #ifdef __cplusplus
324 }
325 #endif
326