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