This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[inseparable changes from patch from perl5.003_23 to perl5.003_24]
[perl5.git] / win32 / win32.c
CommitLineData
0a753a76
PP
1// WIN32.C
2
3// (c) 1995 Microsoft Corporation. All rights reserved.
4// Developed by hip communications inc., http://info.hip.com/info/
5// Portions (c) 1993 Intergraph Corporation. All rights reserved.
6
7// You may distribute under the terms of either the GNU General Public
8// License or the Artistic License, as specified in the README file.
9
10#define WIN32_LEAN_AND_MEAN
11#define WIN32IO_IS_STDIO
12#include <tchar.h>
13#include <windows.h>
14
15//#include "config.h"
16
17#define PERLIO_NOT_STDIO 0
18#if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
19#define PerlIO FILE
20#endif
21
22#include "EXTERN.h"
23#include "perl.h"
24#include <fcntl.h>
25#include <sys/stat.h>
26#include <assert.h>
27#include <string.h>
28#include <stdarg.h>
29
30#define CROAK croak
31#define WARN warn
32
33extern WIN32_IOSUBSYSTEM win32stdio;
34__declspec(thread) PWIN32_IOSUBSYSTEM pIOSubSystem = &win32stdio;
35//__declspec(thread) PWIN32_IOSUBSYSTEM pIOSubSystem = NULL;
36
37BOOL ProbeEnv = FALSE;
38DWORD Win32System;
39char szShellPath[MAX_PATH+1];
40char szPerlLibRoot[MAX_PATH+1];
41HANDLE PerlDllHandle = INVALID_HANDLE_VALUE;
42
43#define IsWin95() (Win32System == VER_PLATFORM_WIN32_WINDOWS)
44#define IsWinNT() (Win32System == VER_PLATFORM_WIN32_NT)
45
46void *SetIOSubSystem(void *p)
47{
48 if (p) {
49 PWIN32_IOSUBSYSTEM pio = (PWIN32_IOSUBSYSTEM)p;
50
51 if (pio->signature_begin == 12345678L && pio->signature_end == 87654321L) {
52 PWIN32_IOSUBSYSTEM pold = pIOSubSystem;
53 pIOSubSystem = pio;
54 return pold;
55 }
56 }
57 else {
58 // re-assign our stuff
59// pIOSubSystem = &win32stdio;
60 pIOSubSystem = NULL;
61 }
62
63 return pIOSubSystem;
64}
65
66char *win32PerlLibPath(void)
67{
68
69 GetModuleFileName((PerlDllHandle == INVALID_HANDLE_VALUE)
70 ? GetModuleHandle(NULL) : PerlDllHandle,
71 szPerlLibRoot,
72 sizeof(szPerlLibRoot));
73
74 *(strrchr(szPerlLibRoot, '\\')) = '\0';
75 strcat(szPerlLibRoot,"\\LIB");
76 return (szPerlLibRoot);
77}
78
79BOOL HasRedirection(char *ptr)
80{
81 int inquote = 0;
82 char quote = '\0';
83
84 //
85 // Scan string looking for redirection (< or >) or pipe
86 // characters (|) that are not in a quoted string
87 //
88 while(*ptr)
89 {
90 switch(*ptr)
91 {
92 case '\'':
93 case '\"':
94 if(inquote)
95 {
96 if(quote == *ptr)
97 {
98 inquote = 0;
99 quote = '\0';
100 }
101 }
102 else
103 {
104 quote = *ptr;
105 inquote++;
106 }
107 break;
108
109 case '>':
110 case '<':
111 case '|':
112 if(!inquote)
113 return TRUE;
114
115 default:
116 break;
117 }
118 ++ptr;
119 }
120 return FALSE;
121}
122
123// since the current process environment is being updated in util.c
124// the library functions will get the correct environment
125PerlIO *my_popen(char *cmd, char *mode)
126{
127#ifdef FIXCMD
128#define fixcmd(x) {\
129 char *pspace = strchr((x),' ');\
130 if (pspace) {\
131 char *p = (x);\
132 while (p < pspace) {\
133 if (*p == '/') *p = '\\';\
134 p++;\
135 }\
136 }\
137 }
138#else
139#define fixcmd(x)
140#endif
141#ifndef PERLDLL
142 fixcmd(cmd);
143 return win32_popen(cmd, mode);
144#else
145/*
146 * There seems to be some problems for the _popen call in a DLL
147 * this trick at the moment seems to work but it is never test
148 * on NT yet
149 *
150 */
151# ifdef __cplusplus
152#define EXT_C_FUNC extern "C"
153# else
154#define EXT_C_FUNC extern
155# endif
156
157EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value);
158EXT_C_FUNC void __cdecl _lock_fhandle(int);
159EXT_C_FUNC void __cdecl _unlock_fhandle(int);
160
161 BOOL fSuccess;
162 PerlIO *pf; // to store the _popen return value
163 int tm = 0; /* flag indicating tDllExport or binary mode */
164 int fhNeeded, fhInherited, fhDup;
165 int ineeded, iinherited;
166 DWORD dwDup;
167 int phdls[2]; /* I/O handles for pipe */
168 HANDLE hPIn,
169 hPOut,
170 hPErr,
171 hSaveStdin,
172 hSaveStdout,
173 hSaveStderr,
174 hPNeeded, hPInherited, hPDuped;
175
176 /* first check for errors in the arguments
177 */
178
179 if ( (cmd == NULL) || (mode == NULL) || ((*mode != 'w') &&
180 (*mode != _T('r'))) )
181 goto error1;
182
183 if ( *(mode + 1) == _T('t') )
184 tm = _O_TEXT;
185 else if ( *(mode + 1) == _T('b') )
186 tm = _O_BINARY;
187 else tm = (*mode == 'w' ? _O_BINARY : _O_TEXT);
188
189
190 fixcmd(cmd);
191 if (&win32stdio != pIOSubSystem) return win32_popen(cmd, mode);
192
193#ifdef EFG
194 if ( _pipe( phdls, 1024, tm ) == -1 )
195#else
196 if ( win32_pipe( phdls, 1024, tm ) == -1 )
197#endif
198 goto error1;
199
200
201 /* save the current situation */
202
203 hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
204 hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
205 hSaveStderr = GetStdHandle(STD_ERROR_HANDLE);
206
207 if (*mode == _T('w')) {
208 ineeded = 1;
209 dwDup = STD_INPUT_HANDLE;
210 iinherited = 0;
211 }
212 else {
213 ineeded = 0;
214 dwDup = STD_OUTPUT_HANDLE;
215 iinherited = 1;
216 }
217
218
219 fhNeeded = phdls[ineeded];
220 fhInherited = phdls[iinherited];
221
222 fSuccess = DuplicateHandle(GetCurrentProcess(),
223 (HANDLE) stolen_get_osfhandle(fhNeeded),
224 GetCurrentProcess(),
225 &hPNeeded,
226 0,
227 FALSE, /* not inherited */
228 DUPLICATE_SAME_ACCESS);
229
230 if (!fSuccess) goto error2;
231
232 fhDup = stolen_open_osfhandle((long) hPNeeded, tm);
233 win32_dup2(fhDup, fhNeeded);
234 win32_close(fhDup);
235
236#ifdef AAA
237 /* Close the Out pipe, child won't need it */
238 hPDuped = (HANDLE) stolen_get_osfhandle(fhNeeded);
239
240 _lock_fhandle(fhNeeded);
241 _set_osfhnd(fhNeeded, (long) hPNeeded); // put in ours duplicated one
242 _unlock_fhandle(fhNeeded);
243
244 CloseHandle(hPDuped); // close the handle first
245#endif
246
247 if (!SetStdHandle(dwDup, (HANDLE) stolen_get_osfhandle(fhInherited))) goto error2;
248
249 //
250 // make sure the child see the same stderr as the calling program
251 //
252 //
253 if (!SetStdHandle(STD_ERROR_HANDLE, (HANDLE) stolen_get_osfhandle(win32_fileno(win32_stderr())))) goto error2;
254
255 pf = win32_popen(cmd, mode); // ask _popen to do the job
256
257 /* restore to where we were */
258 SetStdHandle(STD_INPUT_HANDLE, hSaveStdin);
259 SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout);
260 SetStdHandle(STD_ERROR_HANDLE, hSaveStderr);
261
262 /* we don't need it any more, that's for the child */
263 win32_close(fhInherited);
264
265 if (NULL == pf) {
266 // something wrong
267 win32_close(fhNeeded);
268 goto error1;
269 }
270 else {
271
272 /*
273 * here we steal the file handle in pf and stuff ours in
274 *
275 */
276 win32_dup2(fhNeeded, win32_fileno(pf));
277 win32_close(fhNeeded);
278 }
279
280 return (pf);
281
282error2:
283 win32_close(fhNeeded);
284 win32_close(fhInherited);
285
286error1:
287 return (NULL);
288
289#endif
290}
291
292long my_pclose(PerlIO *fp)
293{
294 return win32_pclose(fp);
295}
296
297static void IdOS(void)
298{
299 OSVERSIONINFO osver;
300
301 memset(&osver, 0, sizeof(OSVERSIONINFO));
302 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
303 GetVersionEx(&osver);
304 Win32System = osver.dwPlatformId;
305 return;
306}
307
308static char *GetShell(void)
309{
310 static char* szWin95ShellEntry = "Win95Shell";
311 static char* szWin95DefaultShell = "Cmd32.exe";
312 static char* szWinNTDefaultShell = "cmd.exe";
313
314 if (!ProbeEnv) {
315 IdOS(), ProbeEnv = TRUE;
316 if (IsWin95()) {
317 strcpy(szShellPath, szWin95DefaultShell);
318 }
319 else {
320 strcpy(szShellPath, szWinNTDefaultShell);
321 }
322 }
323
324 return szShellPath;
325}
326
327int do_aspawn(void* really, void** mark, void** arglast)
328{
329 char **argv;
330 char *strPtr;
331 char *cmd;
332 int status;
333 unsigned int length;
334 int index = 0;
335 SV *sv = (SV*)really;
336 SV** pSv = (SV**)mark;
337
338 New(1110, argv, (arglast - mark) + 3, char*);
339
340 if(sv != Nullsv)
341 {
342 cmd = SvPV(sv, length);
343 }
344 else
345 {
346 cmd = GetShell();
347 argv[index++] = "/c";
348 }
349
350 while(pSv <= (SV**)arglast)
351 {
352 sv = *pSv++;
353 strPtr = SvPV(sv, length);
354 if(strPtr != NULL && *strPtr != '\0')
355 argv[index++] = strPtr;
356 }
357 argv[index++] = 0;
358
359 status = win32_spawnvpe(P_WAIT, cmd, (const char* const*)argv, (const char* const*)environ);
360
361 Safefree(argv);
362
363 // set statusvalue the perl variable $?
364 return (statusvalue = status*256);
365}
366
367int do_spawn(char *cmd)
368{
369 char **a;
370 char *s;
371 char **argv;
372 int status = -1;
373 BOOL needToTry = TRUE;
374 char *shell, *cmd2;
375
376 /* save an extra exec if possible */
377 shell = GetShell();
378
379 /* see if there are shell metacharacters in it */
380 if(!HasRedirection(cmd))
381 {
382 New(1102,argv, strlen(cmd) / 2 + 2, char*);
383
384 New(1103,cmd2, strlen(cmd) + 1, char);
385 strcpy(cmd2, cmd);
386 a = argv;
387 for(s = cmd2; *s;)
388 {
389 while(*s && isspace(*s)) s++;
390 if(*s)
391 *(a++) = s;
392 while(*s && !isspace(*s)) s++;
393 if(*s)
394 *s++ = '\0';
395 }
396 *a = Nullch;
397 if(argv[0])
398 {
399 status = win32_spawnvpe(P_WAIT, argv[0], (const char* const*)argv, (const char* const*)environ);
400 if(status != -1 || errno == 0)
401 needToTry = FALSE;
402 }
403 Safefree(argv);
404 Safefree(cmd2);
405 }
406 if(needToTry)
407 {
408 status = win32_spawnle(P_WAIT, shell, shell, "/c", cmd, (char*)0, environ);
409 }
410
411 // set statusvalue the perl variable $?
412 return (statusvalue = status*256);
413}
414
415
416#define PATHLEN 1024
417
418// The idea here is to read all the directory names into a string table
419// (separated by nulls) and when one of the other dir functions is called
420// return the pointer to the current file name.
421DIR *opendir(char *filename)
422{
423 DIR *p;
424 long len;
425 long idx;
426 char scannamespc[PATHLEN];
427 char *scanname = scannamespc;
428 struct stat sbuf;
429 WIN32_FIND_DATA FindData;
430 HANDLE fh;
431// char root[_MAX_PATH];
432// char volname[_MAX_PATH];
433// DWORD serial, maxname, flags;
434// BOOL downcase;
435// char *dummy;
436
437 // check to see if filename is a directory
438 if(stat(filename, &sbuf) < 0 || sbuf.st_mode & _S_IFDIR == 0)
439 {
440 return NULL;
441 }
442
443 // get the file system characteristics
444// if(GetFullPathName(filename, MAX_PATH, root, &dummy))
445// {
446// if(dummy = strchr(root, '\\'))
447// *++dummy = '\0';
448// if(GetVolumeInformation(root, volname, MAX_PATH, &serial, &maxname, &flags, 0, 0))
449// {
450// downcase = !(flags & FS_CASE_IS_PRESERVED);
451// }
452// }
453// else
454// {
455// downcase = TRUE;
456// }
457
458 // Get us a DIR structure
459 Newz(1501, p, 1, DIR);
460 if(p == NULL)
461 return NULL;
462
463 // Create the search pattern
464 strcpy(scanname, filename);
465
466 if(index("/\\", *(scanname + strlen(scanname) - 1)) == NULL)
467 strcat(scanname, "/*");
468 else
469 strcat(scanname, "*");
470
471 // do the FindFirstFile call
472 fh = FindFirstFile(scanname, &FindData);
473 if(fh == INVALID_HANDLE_VALUE)
474 {
475 return NULL;
476 }
477
478 // now allocate the first part of the string table for the filenames that we find.
479 idx = strlen(FindData.cFileName)+1;
480 New(1502, p->start, idx, char);
481 if(p->start == NULL)
482 {
483 CROAK("opendir: malloc failed!\n");
484 }
485 strcpy(p->start, FindData.cFileName);
486// if(downcase)
487// strlwr(p->start);
488 p->nfiles++;
489
490 // loop finding all the files that match the wildcard
491 // (which should be all of them in this directory!).
492 // the variable idx should point one past the null terminator
493 // of the previous string found.
494 //
495 while(FindNextFile(fh, &FindData))
496 {
497 len = strlen(FindData.cFileName);
498 // bump the string table size by enough for the
499 // new name and it's null terminator
500 Renew(p->start, idx+len+1, char);
501 if(p->start == NULL)
502 {
503 CROAK("opendir: malloc failed!\n");
504 }
505 strcpy(&p->start[idx], FindData.cFileName);
506// if(downcase)
507// strlwr(&p->start[idx]);
508 p->nfiles++;
509 idx += len+1;
510 }
511 FindClose(fh);
512 p->size = idx;
513 p->curr = p->start;
514 return p;
515}
516
517
518// Readdir just returns the current string pointer and bumps the
519// string pointer to the nDllExport entry.
520struct direct *readdir(DIR *dirp)
521{
522 int len;
523 static int dummy = 0;
524
525 if(dirp->curr)
526 { // first set up the structure to return
527 len = strlen(dirp->curr);
528 strcpy(dirp->dirstr.d_name, dirp->curr);
529 dirp->dirstr.d_namlen = len;
530
531 // Fake an inode
532 dirp->dirstr.d_ino = dummy++;
533
534 // Now set up for the nDllExport call to readdir
535 dirp->curr += len + 1;
536 if(dirp->curr >= (dirp->start + dirp->size))
537 {
538 dirp->curr = NULL;
539 }
540
541 return &(dirp->dirstr);
542 }
543 else
544 return NULL;
545}
546
547// Telldir returns the current string pointer position
548long telldir(DIR *dirp)
549{
550 return (long) dirp->curr;
551}
552
553
554// Seekdir moves the string pointer to a previously saved position (Saved by telldir).
555void seekdir(DIR *dirp, long loc)
556{
557 dirp->curr = (char *)loc;
558}
559
560// Rewinddir resets the string pointer to the start
561void rewinddir(DIR *dirp)
562{
563 dirp->curr = dirp->start;
564}
565
566// free the memory allocated by opendir
567int closedir(DIR *dirp)
568{
569 Safefree(dirp->start);
570 Safefree(dirp);
571 return 1;
572}
573
574
575//
576// various stubs
577//
578
579
580// Ownership
581//
582// Just pretend that everyone is a superuser. NT will let us know if
583// we don\'t really have permission to do something.
584//
585
586#define ROOT_UID ((uid_t)0)
587#define ROOT_GID ((gid_t)0)
588
589uid_t getuid(void)
590{
591 return ROOT_UID;
592}
593
594uid_t geteuid(void)
595{
596 return ROOT_UID;
597}
598
599gid_t getgid(void)
600{
601 return ROOT_GID;
602}
603
604gid_t getegid(void)
605{
606 return ROOT_GID;
607}
608
609int setuid(uid_t uid)
610{
611 return (uid == ROOT_UID ? 0 : -1);
612}
613
614int setgid(gid_t gid)
615{
616 return (gid == ROOT_GID ? 0 : -1);
617}
618
619//
620// pretended kill
621//
622int kill(int pid, int sig)
623{
624 HANDLE hProcess= OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
625
626 if (hProcess == NULL) {
627 CROAK("kill process failed!\n");
628 }
629 else {
630 if (!TerminateProcess(hProcess, sig)) CROAK("kill process failed!\n");
631 CloseHandle(hProcess);
632 }
633 return 0;
634}
635
636//
637// File system stuff
638//
639
640int ioctl(int i, unsigned int u, char *data)
641{
642 CROAK("ioctl not implemented!\n");
643 return -1;
644}
645
646unsigned int sleep(unsigned int t)
647{
648 Sleep(t*1000);
649 return 0;
650}
651
652
653#undef rename
654
655int myrename(char *OldFileName, char *newname)
656{
657 if(_access(newname, 0) != -1)
658 { // file exists
659 _unlink(newname);
660 }
661 return rename(OldFileName, newname);
662}
663
664
665int win32_stat(const char *path, struct stat *buffer)
666{
667 char t[MAX_PATH];
668 const char *p = path;
669 int l = strlen(path);
670
671 if (l > 1) {
672 switch(path[l - 1]) {
673 case '\\':
674 case '/':
675 if (path[l - 2] != ':') {
676 strncpy(t, path, l - 1);
677 t[l - 1] = 0;
678 p = t;
679 };
680 }
681 }
682
683 return stat(p, buffer);
684}
685
686#undef times
687int mytimes(struct tms *timebuf)
688{
689 clock_t t = clock();
690 timebuf->tms_utime = t;
691 timebuf->tms_stime = 0;
692 timebuf->tms_cutime = 0;
693 timebuf->tms_cstime = 0;
694
695 return 0;
696}
697
698#undef alarm
699unsigned int myalarm(unsigned int sec)
700{
701 // we warn the usuage of alarm function
702 if (sec != 0)
703 WARN("dummy function alarm called, program might not function as expected\n");
704 return 0;
705}
706
707//
708// redirected io subsystem for all XS modules
709//
710//
711
712DllExport int * win32_errno(void)
713{
714 return (pIOSubSystem->pfnerrno());
715}
716
717// the rest are the remapped stdio routines
718DllExport FILE *win32_stderr(void)
719{
720 return (pIOSubSystem->pfnstderr());
721}
722
723DllExport FILE *win32_stdin(void)
724{
725 return (pIOSubSystem->pfnstdin());
726}
727
728DllExport FILE *win32_stdout()
729{
730 return (pIOSubSystem->pfnstdout());
731}
732
733DllExport int win32_ferror(FILE *fp)
734{
735 return (pIOSubSystem->pfnferror(fp));
736}
737
738
739DllExport int win32_feof(FILE *fp)
740{
741 return (pIOSubSystem->pfnfeof(fp));
742}
743
744//
745// Since the errors returned by the socket error function
746// WSAGetLastError() are not known by the library routine strerror
747// we have to roll our own.
748//
749
750__declspec(thread) char strerror_buffer[512];
751
752DllExport char *win32_strerror(int e)
753{
754 extern int sys_nerr;
755 DWORD source = 0;
756
757 if(e < 0 || e > sys_nerr)
758 {
759 if(e < 0)
760 e = GetLastError();
761
762 if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, &source, e, 0, strerror_buffer, sizeof(strerror_buffer), NULL) == 0)
763 strcpy(strerror_buffer, "Unknown Error");
764
765 return strerror_buffer;
766 }
767
768 return pIOSubSystem->pfnstrerror(e);
769}
770
771DllExport int win32_fprintf(FILE *fp, const char *format, ...)
772{
773 va_list marker;
774 va_start(marker, format); /* Initialize variable arguments. */
775
776 return (pIOSubSystem->pfnvfprintf(fp, format, marker));
777}
778
779DllExport int win32_printf(const char *format, ...)
780{
781 va_list marker;
782 va_start(marker, format); /* Initialize variable arguments. */
783
784 return (pIOSubSystem->pfnvprintf(format, marker));
785}
786
787DllExport int win32_vfprintf(FILE *fp, const char *format, va_list args)
788{
789 return (pIOSubSystem->pfnvfprintf(fp, format, args));
790}
791
792DllExport size_t win32_fread(void *buf, size_t size, size_t count, FILE *fp)
793{
794 return pIOSubSystem->pfnfread(buf, size, count, fp);
795}
796
797DllExport size_t win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
798{
799 return pIOSubSystem->pfnfwrite(buf, size, count, fp);
800}
801
802DllExport FILE *win32_fopen(const char *filename, const char *mode)
803{
804 if (stricmp(filename, "/dev/null")==0) return pIOSubSystem->pfnfopen("NUL", mode);
805 return pIOSubSystem->pfnfopen(filename, mode);
806}
807
808DllExport FILE *win32_fdopen( int handle, const char *mode)
809{
810 return pIOSubSystem->pfnfdopen(handle, mode);
811}
812
813DllExport FILE *win32_freopen( const char *path, const char *mode, FILE *stream)
814{
815 if (stricmp(path, "/dev/null")==0) return pIOSubSystem->pfnfreopen("NUL", mode, stream);
816 return pIOSubSystem->pfnfreopen(path, mode, stream);
817}
818
819DllExport int win32_fclose(FILE *pf)
820{
821 return pIOSubSystem->pfnfclose(pf);
822}
823
824DllExport int win32_fputs(const char *s,FILE *pf)
825{
826 return pIOSubSystem->pfnfputs(s, pf);
827}
828
829DllExport int win32_fputc(int c,FILE *pf)
830{
831 return pIOSubSystem->pfnfputc(c,pf);
832}
833
834DllExport int win32_ungetc(int c,FILE *pf)
835{
836 return pIOSubSystem->pfnungetc(c,pf);
837}
838
839DllExport int win32_getc(FILE *pf)
840{
841 return pIOSubSystem->pfngetc(pf);
842}
843
844DllExport int win32_fileno(FILE *pf)
845{
846 return pIOSubSystem->pfnfileno(pf);
847}
848
849DllExport void win32_clearerr(FILE *pf)
850{
851 pIOSubSystem->pfnclearerr(pf);
852 return;
853}
854
855DllExport int win32_fflush(FILE *pf)
856{
857 return pIOSubSystem->pfnfflush(pf);
858}
859
860DllExport long win32_ftell(FILE *pf)
861{
862 return pIOSubSystem->pfnftell(pf);
863}
864
865DllExport int win32_fseek(FILE *pf,long offset,int origin)
866{
867 return pIOSubSystem->pfnfseek(pf, offset, origin);
868}
869
870DllExport int win32_fgetpos(FILE *pf,fpos_t *p)
871{
872 return pIOSubSystem->pfnfgetpos(pf, p);
873}
874
875DllExport int win32_fsetpos(FILE *pf,const fpos_t *p)
876{
877 return pIOSubSystem->pfnfsetpos(pf, p);
878}
879
880DllExport void win32_rewind(FILE *pf)
881{
882 pIOSubSystem->pfnrewind(pf);
883 return;
884}
885
886DllExport FILE* win32_tmpfile(void)
887{
888 return pIOSubSystem->pfntmpfile();
889}
890
891DllExport void win32_abort(void)
892{
893 pIOSubSystem->pfnabort();
894 return;
895}
896
897DllExport int win32_fstat(int fd,struct stat *bufptr)
898{
899 return pIOSubSystem->pfnfstat(fd,bufptr);
900}
901
902DllExport int win32_pipe(int *pfd, unsigned int size, int mode)
903{
904 return pIOSubSystem->pfnpipe(pfd, size, mode);
905}
906
907DllExport FILE* win32_popen(const char *command, const char *mode)
908{
909 return pIOSubSystem->pfnpopen(command, mode);
910}
911
912DllExport int win32_pclose(FILE *pf)
913{
914 return pIOSubSystem->pfnpclose(pf);
915}
916
917DllExport int win32_setmode(int fd, int mode)
918{
919 return pIOSubSystem->pfnsetmode(fd, mode);
920}
921
922DllExport int win32_open(const char *path, int flag, ...)
923{
924 va_list ap;
925 int pmode;
926
927 va_start(ap, flag);
928 pmode = va_arg(ap, int);
929 va_end(ap);
930
931 if (stricmp(path, "/dev/null")==0) return pIOSubSystem->pfnopen("NUL", flag, pmode);
932 return pIOSubSystem->pfnopen(path,flag,pmode);
933}
934
935DllExport int win32_close(int fd)
936{
937 return pIOSubSystem->pfnclose(fd);
938}
939
940DllExport int win32_dup(int fd)
941{
942 return pIOSubSystem->pfndup(fd);
943}
944
945DllExport int win32_dup2(int fd1,int fd2)
946{
947 return pIOSubSystem->pfndup2(fd1,fd2);
948}
949
950DllExport int win32_read(int fd, char *buf, unsigned int cnt)
951{
952 return pIOSubSystem->pfnread(fd, buf, cnt);
953}
954
955DllExport int win32_write(int fd, const char *buf, unsigned int cnt)
956{
957 return pIOSubSystem->pfnwrite(fd, buf, cnt);
958}
959
960DllExport int win32_spawnvpe(int mode, const char *cmdname, const char *const *argv, const char *const *envp)
961{
962 return pIOSubSystem->pfnspawnvpe(mode, cmdname, argv, envp);
963}
964
965DllExport int win32_spawnle(int mode, const char *cmdname, const char *arglist,...)
966{
967 const char* const* envp;
968 const char* const* argp;
969
970 argp = &arglist;
971 while (*argp++) ;
972
973 return pIOSubSystem->pfnspawnvpe(mode, cmdname, &arglist, argp);
974}
975
976int stolen_open_osfhandle(long handle, int flags)
977{
978 return pIOSubSystem->pfn_open_osfhandle(handle, flags);
979}
980
981long stolen_get_osfhandle(int fd)
982{
983 return pIOSubSystem->pfn_get_osfhandle(fd);
984}