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