summaryrefslogtreecommitdiff
path: root/win32/win32io.c
blob: 333b64a7ecaf9f4bde464387371389874ed7a996 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241

#ifdef __cplusplus
extern "C" {
#endif

#define WIN32_LEAN_AND_MEAN
#define WIN32IO_IS_STDIO
#define EXT
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <assert.h>
#include <errno.h>
#include <process.h>

#include "win32iop.h"

/*
 * The following is just a basic wrapping of the stdio
 *
 *  redirected io subsystem for all XS modules
 */

static int *
dummy_errno(void)
{
    return (&(errno));
}

/* the rest are the remapped stdio routines */
static FILE *
dummy_stderr(void)
{
    return stderr;
}

static FILE *
dummy_stdin(void)
{
    return stdin;
}

static FILE *
dummy_stdout(void)
{
    return stdout;
}

static int
dummy_globalmode(int mode)
{
    int o = _fmode;
    _fmode = mode;

    return o;
}


#if defined(_WIN32) && !defined(WIN95_OSFHANDLE_FIXED) && defined(_M_IX86)

#	ifdef __cplusplus
#define EXT_C_FUNC	extern "C"
#	else
#define EXT_C_FUNC	extern
#	endif

EXT_C_FUNC int __cdecl _alloc_osfhnd(void);
EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value);
EXT_C_FUNC void __cdecl _lock_fhandle(int);
EXT_C_FUNC void __cdecl _unlock_fhandle(int);
EXT_C_FUNC void __cdecl _unlock(int);

#if	(_MSC_VER >= 1000)
typedef struct	{
    long osfhnd;    /* underlying OS file HANDLE */
    char osfile;    /* attributes of file (e.g., open in text mode?) */
    char pipech;    /* one char buffer for handles opened on pipes */
#if defined (_MT) && !defined (DLL_FOR_WIN32S)
    int lockinitflag;
    CRITICAL_SECTION lock;
#endif  /* defined (_MT) && !defined (DLL_FOR_WIN32S) */
}	ioinfo;

EXT_C_FUNC ioinfo * __pioinfo[];

#define IOINFO_L2E			5
#define IOINFO_ARRAY_ELTS	(1 << IOINFO_L2E)
#define _pioinfo(i)	(__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1)))
#define _osfile(i)	(_pioinfo(i)->osfile)

#else	/* (_MSC_VER >= 1000) */
extern char _osfile[];
#endif	/* (_MSC_VER >= 1000) */

#define FOPEN			0x01	/* file handle open */
#define FAPPEND			0x20	/* file handle opened O_APPEND */
#define FDEV			0x40	/* file handle refers to device */
#define FTEXT			0x80	/* file handle is in text mode */

#define _STREAM_LOCKS   26		/* Table of stream locks */
#define _LAST_STREAM_LOCK  (_STREAM_LOCKS+_NSTREAM_-1)	/* Last stream lock */
#define _FH_LOCKS          (_LAST_STREAM_LOCK+1)	/* Table of fh locks */

/***
*int _patch_open_osfhandle(long osfhandle, int flags) - open C Runtime file handle
*
*Purpose:
*       This function allocates a free C Runtime file handle and associates
*       it with the Win32 HANDLE specified by the first parameter. This is a
*		temperary fix for WIN95's brain damage GetFileType() error on socket
*		we just bypass that call for socket
*
*Entry:
*       long osfhandle - Win32 HANDLE to associate with C Runtime file handle.
*       int flags      - flags to associate with C Runtime file handle.
*
*Exit:
*       returns index of entry in fh, if successful
*       return -1, if no free entry is found
*
*Exceptions:
*
*******************************************************************************/

int
my_open_osfhandle(long osfhandle, int flags)
{
    int fh;
    char fileflags;		/* _osfile flags */

    /* copy relevant flags from second parameter */
    fileflags = FDEV;

    if(flags & _O_APPEND)
	fileflags |= FAPPEND;

    if(flags & _O_TEXT)
	fileflags |= FTEXT;

    /* attempt to allocate a C Runtime file handle */
    if((fh = _alloc_osfhnd()) == -1) {
	errno = EMFILE;		/* too many open files */
	_doserrno = 0L;		/* not an OS error */
	return -1;		/* return error to caller */
    }

    /* the file is open. now, set the info in _osfhnd array */
    _set_osfhnd(fh, osfhandle);

    fileflags |= FOPEN;		/* mark as open */

#if (_MSC_VER >= 1000)
    _osfile(fh) = fileflags;	/* set osfile entry */
    _unlock_fhandle(fh);
#else
    _osfile[fh] = fileflags;	/* set osfile entry */
    _unlock(fh+_FH_LOCKS);		/* unlock handle */
#endif

    return fh;			/* return handle */
}
#else

int __cdecl
stolen_open_osfhandle(long osfhandle, int flags)
{
    return _open_osfhandle(osfhandle, flags);
}
#endif	/* _M_IX86 */

long
my_get_osfhandle( int filehandle )
{
    return _get_osfhandle(filehandle);
}

#ifdef PERLDLL
__declspec(dllexport)
#endif
WIN32_IOSUBSYSTEM	win32stdio = {
    12345678L,		/* begin of structure; */
    dummy_errno,	/* (*pfunc_errno)(void); */
    dummy_stdin,	/* (*pfunc_stdin)(void); */
    dummy_stdout,	/* (*pfunc_stdout)(void); */
    dummy_stderr,	/* (*pfunc_stderr)(void); */
    ferror,		/* (*pfunc_ferror)(FILE *fp); */
    feof,		/* (*pfunc_feof)(FILE *fp); */
    strerror,		/* (*strerror)(int e); */
    vfprintf,		/* (*pfunc_vfprintf)(FILE *pf, const char *format, va_list arg); */
    vprintf,		/* (*pfunc_vprintf)(const char *format, va_list arg); */
    fread,		/* (*pfunc_fread)(void *buf, size_t size, size_t count, FILE *pf); */
    fwrite,		/* (*pfunc_fwrite)(void *buf, size_t size, size_t count, FILE *pf); */
    fopen,		/* (*pfunc_fopen)(const char *path, const char *mode); */
    fdopen,		/* (*pfunc_fdopen)(int fh, const char *mode); */
    freopen,		/* (*pfunc_freopen)(const char *path, const char *mode, FILE *pf); */
    fclose,		/* (*pfunc_fclose)(FILE *pf); */
    fputs,		/* (*pfunc_fputs)(const char *s,FILE *pf); */
    fputc,		/* (*pfunc_fputc)(int c,FILE *pf); */
    ungetc,		/* (*pfunc_ungetc)(int c,FILE *pf); */
    getc,		/* (*pfunc_getc)(FILE *pf); */
    fileno,		/* (*pfunc_fileno)(FILE *pf); */
    clearerr,		/* (*pfunc_clearerr)(FILE *pf); */
    fflush,		/* (*pfunc_fflush)(FILE *pf); */
    ftell,		/* (*pfunc_ftell)(FILE *pf); */
    fseek,		/* (*pfunc_fseek)(FILE *pf,long offset,int origin); */
    fgetpos,		/* (*pfunc_fgetpos)(FILE *pf,fpos_t *p); */
    fsetpos,		/* (*pfunc_fsetpos)(FILE *pf,fpos_t *p); */
    rewind,		/* (*pfunc_rewind)(FILE *pf); */
    tmpfile,		/* (*pfunc_tmpfile)(void); */
    abort,		/* (*pfunc_abort)(void); */
    fstat,  		/* (*pfunc_fstat)(int fd,struct stat *bufptr); */
    stat,		/* (*pfunc_stat)(const char *name,struct stat *bufptr); */
    _pipe,		/* (*pfunc_pipe)( int *phandles, unsigned int psize, int textmode ); */
    _popen,		/* (*pfunc_popen)( const char *command, const char *mode ); */
    _pclose,		/* (*pfunc_pclose)( FILE *pf); */
    setmode,		/* (*pfunc_setmode)( int fd, int mode); */
    lseek,		/* (*pfunc_lseek)( int fd, long offset, int origin); */
    tell,		/* (*pfunc_tell)( int fd); */
    dup,		/* (*pfunc_dup)( int fd); */
    dup2,		/* (*pfunc_dup2)(int h1, int h2); */
    open,		/* (*pfunc_open)(const char *path, int oflag,...); */
    close,		/* (*pfunc_close)(int fd); */
    eof,		/* (*pfunc_eof)(int fd); */
    read,		/* (*pfunc_read)(int fd, void *buf, unsigned int cnt); */
    write,		/* (*pfunc_write)(int fd, const void *buf, unsigned int cnt); */
    dummy_globalmode,	/* (*pfunc_globalmode)(int mode) */
    my_open_osfhandle,
    my_get_osfhandle,
    spawnvpe,
    87654321L,		/* end of structure */
};


#ifdef __cplusplus
}
#endif