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