[inseparable changes from patch to perl 5.004_04]
[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 EXT int         my_fclose(FILE *pf);
242
243 #ifdef PERLDLL
244 __declspec(dllexport)
245 #endif
246 WIN32_IOSUBSYSTEM       win32stdio = {
247     12345678L,          /* begin of structure; */
248     dummy_errno,        /* (*pfunc_errno)(void); */
249     dummy_environ,      /* (*pfunc_environ)(void); */
250     dummy_stdin,        /* (*pfunc_stdin)(void); */
251     dummy_stdout,       /* (*pfunc_stdout)(void); */
252     dummy_stderr,       /* (*pfunc_stderr)(void); */
253     ferror,             /* (*pfunc_ferror)(FILE *fp); */
254     feof,               /* (*pfunc_feof)(FILE *fp); */
255     strerror,           /* (*strerror)(int e); */
256     vfprintf,           /* (*pfunc_vfprintf)(FILE *pf, const char *format, va_list arg); */
257     vprintf,            /* (*pfunc_vprintf)(const char *format, va_list arg); */
258     fread,              /* (*pfunc_fread)(void *buf, size_t size, size_t count, FILE *pf); */
259     fwrite,             /* (*pfunc_fwrite)(void *buf, size_t size, size_t count, FILE *pf); */
260     fopen,              /* (*pfunc_fopen)(const char *path, const char *mode); */
261     fdopen,             /* (*pfunc_fdopen)(int fh, const char *mode); */
262     freopen,            /* (*pfunc_freopen)(const char *path, const char *mode, FILE *pf); */
263     my_fclose,          /* (*pfunc_fclose)(FILE *pf); */
264     fputs,              /* (*pfunc_fputs)(const char *s,FILE *pf); */
265     fputc,              /* (*pfunc_fputc)(int c,FILE *pf); */
266     ungetc,             /* (*pfunc_ungetc)(int c,FILE *pf); */
267     getc,               /* (*pfunc_getc)(FILE *pf); */
268     fileno,             /* (*pfunc_fileno)(FILE *pf); */
269     clearerr,           /* (*pfunc_clearerr)(FILE *pf); */
270     fflush,             /* (*pfunc_fflush)(FILE *pf); */
271     ftell,              /* (*pfunc_ftell)(FILE *pf); */
272     fseek,              /* (*pfunc_fseek)(FILE *pf,long offset,int origin); */
273     fgetpos,            /* (*pfunc_fgetpos)(FILE *pf,fpos_t *p); */
274     fsetpos,            /* (*pfunc_fsetpos)(FILE *pf,fpos_t *p); */
275     rewind,             /* (*pfunc_rewind)(FILE *pf); */
276     tmpfile,            /* (*pfunc_tmpfile)(void); */
277     abort,              /* (*pfunc_abort)(void); */
278     fstat,              /* (*pfunc_fstat)(int fd,struct stat *bufptr); */
279     stat,               /* (*pfunc_stat)(const char *name,struct stat *bufptr); */
280     _pipe,              /* (*pfunc_pipe)( int *phandles, unsigned int psize, int textmode ); */
281     _popen,             /* (*pfunc_popen)( const char *command, const char *mode ); */
282     _pclose,            /* (*pfunc_pclose)( FILE *pf); */
283     setmode,            /* (*pfunc_setmode)( int fd, int mode); */
284     lseek,              /* (*pfunc_lseek)( int fd, long offset, int origin); */
285     tell,               /* (*pfunc_tell)( int fd); */
286     dup,                /* (*pfunc_dup)( int fd); */
287     dup2,               /* (*pfunc_dup2)(int h1, int h2); */
288     open,               /* (*pfunc_open)(const char *path, int oflag,...); */
289     close,              /* (*pfunc_close)(int fd); */
290     eof,                /* (*pfunc_eof)(int fd); */
291     read,               /* (*pfunc_read)(int fd, void *buf, unsigned int cnt); */
292     write,              /* (*pfunc_write)(int fd, const void *buf, unsigned int cnt); */
293     dummy_globalmode,   /* (*pfunc_globalmode)(int mode) */
294     my_open_osfhandle,
295     my_get_osfhandle,
296     spawnvp,
297     mkdir,
298     rmdir,
299     chdir,
300     my_flock,           /* (*pfunc_flock)(int fd, int oper) */
301     execvp,
302     perror,
303     setbuf,
304     setvbuf,
305     flushall,
306     fcloseall,
307     fgets,
308     gets,
309     fgetc,
310     putc,
311     puts,
312     getchar,
313     putchar,
314     fscanf,
315     scanf,
316     malloc,
317     calloc,
318     realloc,
319     free,
320     87654321L,          /* end of structure */
321 };
322
323
324 #ifdef __cplusplus
325 }
326 #endif
327