More detailed IO::Socket documentation
[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;
37__declspec(thread) PWIN32_IOSUBSYSTEM pIOSubSystem = &win32stdio;
68dc0745 38/*__declspec(thread) PWIN32_IOSUBSYSTEM pIOSubSystem = NULL;*/
0a753a76 39
40BOOL ProbeEnv = FALSE;
8b10511d 41DWORD Win32System = (DWORD)-1;
0a753a76 42char szShellPath[MAX_PATH+1];
43char szPerlLibRoot[MAX_PATH+1];
44HANDLE PerlDllHandle = INVALID_HANDLE_VALUE;
45
3fe9a6f1 46int
47IsWin95(void) {
8b10511d 48 return (IdOS() == VER_PLATFORM_WIN32_WINDOWS);
3fe9a6f1 49}
50
51int
52IsWinNT(void) {
8b10511d 53 return (IdOS() == VER_PLATFORM_WIN32_NT);
3fe9a6f1 54}
0a753a76 55
68dc0745 56void *
57SetIOSubSystem(void *p)
0a753a76 58{
137443ea 59 PWIN32_IOSUBSYSTEM old = pIOSubSystem;
68dc0745 60 if (p) {
61 PWIN32_IOSUBSYSTEM pio = (PWIN32_IOSUBSYSTEM)p;
68dc0745 62 if (pio->signature_begin == 12345678L
63 && pio->signature_end == 87654321L) {
68dc0745 64 pIOSubSystem = pio;
68dc0745 65 }
66 }
67 else {
137443ea 68 pIOSubSystem = &win32stdio;
68dc0745 69 }
137443ea 70 return old;
68dc0745 71}
72
73char *
74win32PerlLibPath(void)
75{
76 char *end;
77 GetModuleFileName((PerlDllHandle == INVALID_HANDLE_VALUE)
78 ? GetModuleHandle(NULL)
79 : PerlDllHandle,
80 szPerlLibRoot,
81 sizeof(szPerlLibRoot));
82
83 *(end = strrchr(szPerlLibRoot, '\\')) = '\0';
84 if (stricmp(end-4,"\\bin") == 0)
85 end -= 4;
86 strcpy(end,"\\lib");
87 return (szPerlLibRoot);
88}
0a753a76 89
68dc0745 90BOOL
91HasRedirection(char *ptr)
92{
93 int inquote = 0;
94 char quote = '\0';
95
96 /*
97 * Scan string looking for redirection (< or >) or pipe
98 * characters (|) that are not in a quoted string
99 */
100 while(*ptr) {
101 switch(*ptr) {
102 case '\'':
103 case '\"':
104 if(inquote) {
105 if(quote == *ptr) {
106 inquote = 0;
107 quote = '\0';
0a753a76 108 }
68dc0745 109 }
110 else {
111 quote = *ptr;
112 inquote++;
113 }
114 break;
115 case '>':
116 case '<':
117 case '|':
118 if(!inquote)
119 return TRUE;
120 default:
121 break;
0a753a76 122 }
68dc0745 123 ++ptr;
124 }
125 return FALSE;
0a753a76 126}
127
68dc0745 128/* since the current process environment is being updated in util.c
129 * the library functions will get the correct environment
130 */
131PerlIO *
132my_popen(char *cmd, char *mode)
0a753a76 133{
134#ifdef FIXCMD
68dc0745 135#define fixcmd(x) { \
136 char *pspace = strchr((x),' '); \
137 if (pspace) { \
138 char *p = (x); \
139 while (p < pspace) { \
140 if (*p == '/') \
141 *p = '\\'; \
142 p++; \
143 } \
144 } \
145 }
0a753a76 146#else
147#define fixcmd(x)
148#endif
68dc0745 149
150#if 1
151/* was #ifndef PERLDLL, but the #else stuff doesn't work on NT
152 * GSAR 97/03/13
153 */
154 fixcmd(cmd);
0a753a76 155 return win32_popen(cmd, mode);
156#else
157/*
158 * There seems to be some problems for the _popen call in a DLL
159 * this trick at the moment seems to work but it is never test
160 * on NT yet
161 *
162 */
163# ifdef __cplusplus
164#define EXT_C_FUNC extern "C"
165# else
166#define EXT_C_FUNC extern
167# endif
168
68dc0745 169 EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value);
170 EXT_C_FUNC void __cdecl _lock_fhandle(int);
171 EXT_C_FUNC void __cdecl _unlock_fhandle(int);
172
173 BOOL fSuccess;
174 PerlIO *pf; /* to store the _popen return value */
175 int tm = 0; /* flag indicating tDllExport or binary mode */
176 int fhNeeded, fhInherited, fhDup;
177 int ineeded, iinherited;
178 DWORD dwDup;
179 int phdls[2]; /* I/O handles for pipe */
180 HANDLE hPIn, hPOut, hPErr,
181 hSaveStdin, hSaveStdout, hSaveStderr,
182 hPNeeded, hPInherited, hPDuped;
0a753a76 183
68dc0745 184 /* first check for errors in the arguments */
185 if ( (cmd == NULL) || (mode == NULL)
186 || ((*mode != 'w') && (*mode != _T('r'))) )
187 goto error1;
0a753a76 188
189 if ( *(mode + 1) == _T('t') )
68dc0745 190 tm = _O_TEXT;
0a753a76 191 else if ( *(mode + 1) == _T('b') )
68dc0745 192 tm = _O_BINARY;
193 else
194 tm = (*mode == 'w' ? _O_BINARY : _O_TEXT);
0a753a76 195
196
68dc0745 197 fixcmd(cmd);
198 if (&win32stdio != pIOSubSystem)
199 return win32_popen(cmd, mode);
0a753a76 200
201#ifdef EFG
202 if ( _pipe( phdls, 1024, tm ) == -1 )
203#else
204 if ( win32_pipe( phdls, 1024, tm ) == -1 )
205#endif
68dc0745 206 goto error1;
207
208 /* save the current situation */
209 hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
210 hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
211 hSaveStderr = GetStdHandle(STD_ERROR_HANDLE);
212
213 if (*mode == _T('w')) {
214 ineeded = 1;
215 dwDup = STD_INPUT_HANDLE;
216 iinherited = 0;
217 }
218 else {
219 ineeded = 0;
220 dwDup = STD_OUTPUT_HANDLE;
221 iinherited = 1;
222 }
223
224 fhNeeded = phdls[ineeded];
225 fhInherited = phdls[iinherited];
226
227 fSuccess = DuplicateHandle(GetCurrentProcess(),
228 (HANDLE) stolen_get_osfhandle(fhNeeded),
229 GetCurrentProcess(),
230 &hPNeeded,
231 0,
232 FALSE, /* not inherited */
233 DUPLICATE_SAME_ACCESS);
234
235 if (!fSuccess)
236 goto error2;
237
238 fhDup = stolen_open_osfhandle((long) hPNeeded, tm);
239 win32_dup2(fhDup, fhNeeded);
240 win32_close(fhDup);
0a753a76 241
242#ifdef AAA
68dc0745 243 /* Close the Out pipe, child won't need it */
244 hPDuped = (HANDLE) stolen_get_osfhandle(fhNeeded);
0a753a76 245
68dc0745 246 _lock_fhandle(fhNeeded);
247 _set_osfhnd(fhNeeded, (long)hPNeeded); /* put in ours duplicated one */
248 _unlock_fhandle(fhNeeded);
0a753a76 249
68dc0745 250 CloseHandle(hPDuped); /* close the handle first */
0a753a76 251#endif
252
68dc0745 253 if (!SetStdHandle(dwDup, (HANDLE) stolen_get_osfhandle(fhInherited)))
254 goto error2;
0a753a76 255
68dc0745 256 /*
257 * make sure the child see the same stderr as the calling program
258 */
259 if (!SetStdHandle(STD_ERROR_HANDLE,
260 (HANDLE)stolen_get_osfhandle(win32_fileno(win32_stderr()))))
261 goto error2;
0a753a76 262
68dc0745 263 pf = win32_popen(cmd, mode); /* ask _popen to do the job */
0a753a76 264
68dc0745 265 /* restore to where we were */
0a753a76 266 SetStdHandle(STD_INPUT_HANDLE, hSaveStdin);
267 SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout);
268 SetStdHandle(STD_ERROR_HANDLE, hSaveStderr);
269
68dc0745 270 /* we don't need it any more, that's for the child */
271 win32_close(fhInherited);
0a753a76 272
68dc0745 273 if (NULL == pf) {
274 /* something wrong */
275 win32_close(fhNeeded);
276 goto error1;
277 }
278 else {
279 /*
280 * here we steal the file handle in pf and stuff ours in
281 */
282 win32_dup2(fhNeeded, win32_fileno(pf));
283 win32_close(fhNeeded);
284 }
285 return (pf);
0a753a76 286
287error2:
68dc0745 288 win32_close(fhNeeded);
289 win32_close(fhInherited);
0a753a76 290
291error1:
68dc0745 292 return (NULL);
0a753a76 293
294#endif
295}
296
68dc0745 297long
298my_pclose(PerlIO *fp)
0a753a76 299{
300 return win32_pclose(fp);
301}
302
8b10511d 303static DWORD
68dc0745 304IdOS(void)
0a753a76 305{
8b10511d 306 static OSVERSIONINFO osver;
0a753a76 307
8b10511d 308 if (osver.dwPlatformId != Win32System) {
309 memset(&osver, 0, sizeof(OSVERSIONINFO));
310 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
311 GetVersionEx(&osver);
312 Win32System = osver.dwPlatformId;
313 }
314 return (Win32System);
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) {
8b10511d 325 ProbeEnv = TRUE;
68dc0745 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
fc36a67e 348 New(1310, 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)) {
fc36a67e 395 New(1301,argv, strlen(cmd) / 2 + 2, char*);
396 New(1302,cmd2, strlen(cmd) + 1, char);
68dc0745 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 */
fc36a67e 480 Newz(1303, p, 1, DIR);
68dc0745 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;
fc36a67e 502 New(1304, p->start, idx, char);
68dc0745 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
dcb2879a 759DllExport char ***
760win32_environ(void)
761{
762 return (pIOSubSystem->pfnenviron());
763}
764
68dc0745 765/* the rest are the remapped stdio routines */
766DllExport FILE *
767win32_stderr(void)
0a753a76 768{
68dc0745 769 return (pIOSubSystem->pfnstderr());
0a753a76 770}
771
68dc0745 772DllExport FILE *
773win32_stdin(void)
0a753a76 774{
68dc0745 775 return (pIOSubSystem->pfnstdin());
0a753a76 776}
777
68dc0745 778DllExport FILE *
779win32_stdout()
0a753a76 780{
68dc0745 781 return (pIOSubSystem->pfnstdout());
0a753a76 782}
783
68dc0745 784DllExport int
785win32_ferror(FILE *fp)
0a753a76 786{
68dc0745 787 return (pIOSubSystem->pfnferror(fp));
0a753a76 788}
789
790
68dc0745 791DllExport int
792win32_feof(FILE *fp)
0a753a76 793{
68dc0745 794 return (pIOSubSystem->pfnfeof(fp));
0a753a76 795}
796
68dc0745 797/*
798 * Since the errors returned by the socket error function
799 * WSAGetLastError() are not known by the library routine strerror
800 * we have to roll our own.
801 */
0a753a76 802
803__declspec(thread) char strerror_buffer[512];
804
68dc0745 805DllExport char *
806win32_strerror(int e)
0a753a76 807{
68dc0745 808 extern int sys_nerr;
809 DWORD source = 0;
0a753a76 810
68dc0745 811 if(e < 0 || e > sys_nerr) {
812 if(e < 0)
813 e = GetLastError();
0a753a76 814
68dc0745 815 if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, &source, e, 0,
816 strerror_buffer, sizeof(strerror_buffer), NULL) == 0)
817 strcpy(strerror_buffer, "Unknown Error");
0a753a76 818
68dc0745 819 return strerror_buffer;
820 }
821 return pIOSubSystem->pfnstrerror(e);
0a753a76 822}
823
68dc0745 824DllExport int
825win32_fprintf(FILE *fp, const char *format, ...)
0a753a76 826{
68dc0745 827 va_list marker;
828 va_start(marker, format); /* Initialize variable arguments. */
0a753a76 829
68dc0745 830 return (pIOSubSystem->pfnvfprintf(fp, format, marker));
0a753a76 831}
832
68dc0745 833DllExport int
834win32_printf(const char *format, ...)
0a753a76 835{
68dc0745 836 va_list marker;
837 va_start(marker, format); /* Initialize variable arguments. */
0a753a76 838
68dc0745 839 return (pIOSubSystem->pfnvprintf(format, marker));
0a753a76 840}
841
68dc0745 842DllExport int
843win32_vfprintf(FILE *fp, const char *format, va_list args)
0a753a76 844{
68dc0745 845 return (pIOSubSystem->pfnvfprintf(fp, format, args));
0a753a76 846}
847
96e4d5b1 848DllExport int
849win32_vprintf(const char *format, va_list args)
850{
851 return (pIOSubSystem->pfnvprintf(format, args));
852}
853
68dc0745 854DllExport size_t
855win32_fread(void *buf, size_t size, size_t count, FILE *fp)
0a753a76 856{
68dc0745 857 return pIOSubSystem->pfnfread(buf, size, count, fp);
0a753a76 858}
859
68dc0745 860DllExport size_t
861win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
0a753a76 862{
68dc0745 863 return pIOSubSystem->pfnfwrite(buf, size, count, fp);
0a753a76 864}
865
68dc0745 866DllExport FILE *
867win32_fopen(const char *filename, const char *mode)
0a753a76 868{
68dc0745 869 if (stricmp(filename, "/dev/null")==0)
870 return pIOSubSystem->pfnfopen("NUL", mode);
871 return pIOSubSystem->pfnfopen(filename, mode);
0a753a76 872}
873
68dc0745 874DllExport FILE *
875win32_fdopen( int handle, const char *mode)
0a753a76 876{
68dc0745 877 return pIOSubSystem->pfnfdopen(handle, mode);
0a753a76 878}
879
68dc0745 880DllExport FILE *
881win32_freopen( const char *path, const char *mode, FILE *stream)
0a753a76 882{
68dc0745 883 if (stricmp(path, "/dev/null")==0)
884 return pIOSubSystem->pfnfreopen("NUL", mode, stream);
885 return pIOSubSystem->pfnfreopen(path, mode, stream);
0a753a76 886}
887
68dc0745 888DllExport int
889win32_fclose(FILE *pf)
0a753a76 890{
68dc0745 891 return pIOSubSystem->pfnfclose(pf);
0a753a76 892}
893
68dc0745 894DllExport int
895win32_fputs(const char *s,FILE *pf)
0a753a76 896{
68dc0745 897 return pIOSubSystem->pfnfputs(s, pf);
0a753a76 898}
899
68dc0745 900DllExport int
901win32_fputc(int c,FILE *pf)
0a753a76 902{
68dc0745 903 return pIOSubSystem->pfnfputc(c,pf);
0a753a76 904}
905
68dc0745 906DllExport int
907win32_ungetc(int c,FILE *pf)
0a753a76 908{
68dc0745 909 return pIOSubSystem->pfnungetc(c,pf);
0a753a76 910}
911
68dc0745 912DllExport int
913win32_getc(FILE *pf)
0a753a76 914{
68dc0745 915 return pIOSubSystem->pfngetc(pf);
0a753a76 916}
917
68dc0745 918DllExport int
919win32_fileno(FILE *pf)
0a753a76 920{
68dc0745 921 return pIOSubSystem->pfnfileno(pf);
0a753a76 922}
923
68dc0745 924DllExport void
925win32_clearerr(FILE *pf)
0a753a76 926{
68dc0745 927 pIOSubSystem->pfnclearerr(pf);
928 return;
0a753a76 929}
930
68dc0745 931DllExport int
932win32_fflush(FILE *pf)
0a753a76 933{
68dc0745 934 return pIOSubSystem->pfnfflush(pf);
0a753a76 935}
936
68dc0745 937DllExport long
938win32_ftell(FILE *pf)
0a753a76 939{
68dc0745 940 return pIOSubSystem->pfnftell(pf);
0a753a76 941}
942
68dc0745 943DllExport int
944win32_fseek(FILE *pf,long offset,int origin)
0a753a76 945{
68dc0745 946 return pIOSubSystem->pfnfseek(pf, offset, origin);
0a753a76 947}
948
68dc0745 949DllExport int
950win32_fgetpos(FILE *pf,fpos_t *p)
0a753a76 951{
68dc0745 952 return pIOSubSystem->pfnfgetpos(pf, p);
0a753a76 953}
954
68dc0745 955DllExport int
956win32_fsetpos(FILE *pf,const fpos_t *p)
0a753a76 957{
68dc0745 958 return pIOSubSystem->pfnfsetpos(pf, p);
0a753a76 959}
960
68dc0745 961DllExport void
962win32_rewind(FILE *pf)
0a753a76 963{
68dc0745 964 pIOSubSystem->pfnrewind(pf);
965 return;
0a753a76 966}
967
68dc0745 968DllExport FILE*
969win32_tmpfile(void)
0a753a76 970{
68dc0745 971 return pIOSubSystem->pfntmpfile();
0a753a76 972}
973
68dc0745 974DllExport void
975win32_abort(void)
0a753a76 976{
68dc0745 977 pIOSubSystem->pfnabort();
978 return;
0a753a76 979}
980
68dc0745 981DllExport int
982win32_fstat(int fd,struct stat *bufptr)
0a753a76 983{
68dc0745 984 return pIOSubSystem->pfnfstat(fd,bufptr);
0a753a76 985}
986
68dc0745 987DllExport int
988win32_pipe(int *pfd, unsigned int size, int mode)
0a753a76 989{
68dc0745 990 return pIOSubSystem->pfnpipe(pfd, size, mode);
0a753a76 991}
992
68dc0745 993DllExport FILE*
994win32_popen(const char *command, const char *mode)
0a753a76 995{
68dc0745 996 return pIOSubSystem->pfnpopen(command, mode);
0a753a76 997}
998
68dc0745 999DllExport int
1000win32_pclose(FILE *pf)
0a753a76 1001{
68dc0745 1002 return pIOSubSystem->pfnpclose(pf);
0a753a76 1003}
1004
68dc0745 1005DllExport int
1006win32_setmode(int fd, int mode)
0a753a76 1007{
68dc0745 1008 return pIOSubSystem->pfnsetmode(fd, mode);
0a753a76 1009}
1010
96e4d5b1 1011DllExport long
1012win32_lseek(int fd, long offset, int origin)
1013{
1014 return pIOSubSystem->pfnlseek(fd, offset, origin);
1015}
1016
1017DllExport long
1018win32_tell(int fd)
1019{
1020 return pIOSubSystem->pfntell(fd);
1021}
1022
68dc0745 1023DllExport int
1024win32_open(const char *path, int flag, ...)
0a753a76 1025{
68dc0745 1026 va_list ap;
1027 int pmode;
0a753a76 1028
1029 va_start(ap, flag);
1030 pmode = va_arg(ap, int);
1031 va_end(ap);
1032
68dc0745 1033 if (stricmp(path, "/dev/null")==0)
1034 return pIOSubSystem->pfnopen("NUL", flag, pmode);
1035 return pIOSubSystem->pfnopen(path,flag,pmode);
0a753a76 1036}
1037
68dc0745 1038DllExport int
1039win32_close(int fd)
0a753a76 1040{
68dc0745 1041 return pIOSubSystem->pfnclose(fd);
0a753a76 1042}
1043
68dc0745 1044DllExport int
96e4d5b1 1045win32_eof(int fd)
1046{
1047 return pIOSubSystem->pfneof(fd);
1048}
1049
1050DllExport int
68dc0745 1051win32_dup(int fd)
0a753a76 1052{
68dc0745 1053 return pIOSubSystem->pfndup(fd);
0a753a76 1054}
1055
68dc0745 1056DllExport int
1057win32_dup2(int fd1,int fd2)
0a753a76 1058{
68dc0745 1059 return pIOSubSystem->pfndup2(fd1,fd2);
0a753a76 1060}
1061
68dc0745 1062DllExport int
1063win32_read(int fd, char *buf, unsigned int cnt)
0a753a76 1064{
68dc0745 1065 return pIOSubSystem->pfnread(fd, buf, cnt);
0a753a76 1066}
1067
68dc0745 1068DllExport int
1069win32_write(int fd, const char *buf, unsigned int cnt)
0a753a76 1070{
68dc0745 1071 return pIOSubSystem->pfnwrite(fd, buf, cnt);
0a753a76 1072}
1073
68dc0745 1074DllExport int
5aabfad6 1075win32_mkdir(const char *dir, int mode)
1076{
1077 return pIOSubSystem->pfnmkdir(dir); /* just ignore mode */
1078}
96e4d5b1 1079
5aabfad6 1080DllExport int
1081win32_rmdir(const char *dir)
1082{
1083 return pIOSubSystem->pfnrmdir(dir);
1084}
96e4d5b1 1085
5aabfad6 1086DllExport int
1087win32_chdir(const char *dir)
1088{
1089 return pIOSubSystem->pfnchdir(dir);
1090}
96e4d5b1 1091
5aabfad6 1092DllExport int
68dc0745 1093win32_spawnvpe(int mode, const char *cmdname,
1094 const char *const *argv, const char *const *envp)
0a753a76 1095{
68dc0745 1096 return pIOSubSystem->pfnspawnvpe(mode, cmdname, argv, envp);
0a753a76 1097}
1098
68dc0745 1099DllExport int
1100win32_spawnle(int mode, const char *cmdname, const char *arglist,...)
0a753a76 1101{
68dc0745 1102 const char* const* envp;
1103 const char* const* argp;
0a753a76 1104
68dc0745 1105 argp = &arglist;
1106 while (*argp++) ;
3fe9a6f1 1107 envp = (const char* const*)*argp;
0a753a76 1108
3fe9a6f1 1109 return pIOSubSystem->pfnspawnvpe(mode, cmdname, &arglist, envp);
0a753a76 1110}
1111
68dc0745 1112int
1113stolen_open_osfhandle(long handle, int flags)
0a753a76 1114{
68dc0745 1115 return pIOSubSystem->pfn_open_osfhandle(handle, flags);
0a753a76 1116}
1117
68dc0745 1118long
1119stolen_get_osfhandle(int fd)
0a753a76 1120{
68dc0745 1121 return pIOSubSystem->pfn_get_osfhandle(fd);
0a753a76 1122}
7bac28a0 1123
1124
1125/*
1126 * Extras.
1127 */
1128
1129/* simulate flock by locking a range on the file */
1130
1131#define LK_ERR(f,i) ((f) ? (i = 0) : (errno = GetLastError()))
1132#define LK_LEN 0xffff0000
1133
1134DllExport int
1135win32_flock(int fd, int oper)
1136{
1137 OVERLAPPED o;
1138 int i = -1;
1139 HANDLE fh;
1140
1141 if (!IsWinNT()) {
1142 croak("flock() unimplemented on this platform");
1143 return -1;
1144 }
1145
1146 fh = (HANDLE)stolen_get_osfhandle(fd);
1147 memset(&o, 0, sizeof(o));
1148
1149 switch(oper) {
1150 case LOCK_SH: /* shared lock */
1151 LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i);
1152 break;
1153 case LOCK_EX: /* exclusive lock */
1154 LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i);
1155 break;
1156 case LOCK_SH|LOCK_NB: /* non-blocking shared lock */
1157 LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i);
1158 break;
1159 case LOCK_EX|LOCK_NB: /* non-blocking exclusive lock */
1160 LK_ERR(LockFileEx(fh,
1161 LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
1162 0, LK_LEN, 0, &o),i);
1163 break;
1164 case LOCK_UN: /* unlock lock */
1165 LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i);
1166 break;
1167 default: /* unknown */
1168 errno = EINVAL;
1169 break;
1170 }
1171 return i;
1172}
1173
1174#undef LK_ERR
1175#undef LK_LEN
1176