Initial (untested) merge of all non-ansi changes on ansiperl branch
[p5sagit/p5-mst-13.2.git] / win32 / win32io.c
1
2
3 #define WIN32_LEAN_AND_MEAN
4 #include <stdio.h>
5 extern int my_fclose(FILE *pf);
6 #include "EXTERN.h"
7 #define WIN32IO_IS_STDIO
8 #include <windows.h>
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>
17 #include <direct.h>
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
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
42 static char ***
43 dummy_environ(void)
44 {
45     return (&(_environ));
46 }
47
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
76 #if defined(_DLL) || defined(__BORLANDC__)
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
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
158     if(flags & O_APPEND)
159         fileflags |= FAPPEND;
160
161     if(flags & O_TEXT)
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
189 my_open_osfhandle(long osfhandle, int flags)
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
201 #ifdef __BORLANDC__
202 #define _chdir chdir
203 #endif
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
250 #ifdef PERLDLL
251 __declspec(dllexport)
252 #endif
253 WIN32_IOSUBSYSTEM       win32stdio = {
254     12345678L,          /* begin of structure; */
255     dummy_errno,        /* (*pfunc_errno)(void); */
256     dummy_environ,      /* (*pfunc_environ)(void); */
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); */
270     my_fclose,          /* (*pfunc_fclose)(FILE *pf); */
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,
303     spawnvp,
304     mkdir,
305     rmdir,
306     chdir,
307     my_flock,           /* (*pfunc_flock)(int fd, int oper) */
308     execvp,
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,
327     87654321L,          /* end of structure */
328 };
329
330
331
332
333