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