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.
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.
10 #define WIN32_LEAN_AND_MEAN
11 #define WIN32IO_IS_STDIO
17 #define PERLIO_NOT_STDIO 0
18 #if !defined(PERLIO_IS_STDIO) && !defined(USE_SFIO)
33 extern WIN32_IOSUBSYSTEM win32stdio;
34 __declspec(thread) PWIN32_IOSUBSYSTEM pIOSubSystem = &win32stdio;
35 //__declspec(thread) PWIN32_IOSUBSYSTEM pIOSubSystem = NULL;
37 BOOL ProbeEnv = FALSE;
39 char szShellPath[MAX_PATH+1];
40 char szPerlLibRoot[MAX_PATH+1];
41 HANDLE PerlDllHandle = INVALID_HANDLE_VALUE;
43 #define IsWin95() (Win32System == VER_PLATFORM_WIN32_WINDOWS)
44 #define IsWinNT() (Win32System == VER_PLATFORM_WIN32_NT)
46 void *SetIOSubSystem(void *p)
49 PWIN32_IOSUBSYSTEM pio = (PWIN32_IOSUBSYSTEM)p;
51 if (pio->signature_begin == 12345678L && pio->signature_end == 87654321L) {
52 PWIN32_IOSUBSYSTEM pold = pIOSubSystem;
58 // re-assign our stuff
59 // pIOSubSystem = &win32stdio;
66 char *win32PerlLibPath(void)
69 GetModuleFileName((PerlDllHandle == INVALID_HANDLE_VALUE)
70 ? GetModuleHandle(NULL) : PerlDllHandle,
72 sizeof(szPerlLibRoot));
74 *(strrchr(szPerlLibRoot, '\\')) = '\0';
75 strcat(szPerlLibRoot,"\\LIB");
76 return (szPerlLibRoot);
79 BOOL HasRedirection(char *ptr)
85 // Scan string looking for redirection (< or >) or pipe
86 // characters (|) that are not in a quoted string
123 // since the current process environment is being updated in util.c
124 // the library functions will get the correct environment
125 PerlIO *my_popen(char *cmd, char *mode)
129 char *pspace = strchr((x),' ');\
132 while (p < pspace) {\
133 if (*p == '/') *p = '\\';\
143 return win32_popen(cmd, mode);
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
152 #define EXT_C_FUNC extern "C"
154 #define EXT_C_FUNC extern
157 EXT_C_FUNC int __cdecl _set_osfhnd(int fh, long value);
158 EXT_C_FUNC void __cdecl _lock_fhandle(int);
159 EXT_C_FUNC void __cdecl _unlock_fhandle(int);
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;
167 int phdls[2]; /* I/O handles for pipe */
174 hPNeeded, hPInherited, hPDuped;
176 /* first check for errors in the arguments
179 if ( (cmd == NULL) || (mode == NULL) || ((*mode != 'w') &&
180 (*mode != _T('r'))) )
183 if ( *(mode + 1) == _T('t') )
185 else if ( *(mode + 1) == _T('b') )
187 else tm = (*mode == 'w' ? _O_BINARY : _O_TEXT);
191 if (&win32stdio != pIOSubSystem) return win32_popen(cmd, mode);
194 if ( _pipe( phdls, 1024, tm ) == -1 )
196 if ( win32_pipe( phdls, 1024, tm ) == -1 )
201 /* save the current situation */
203 hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);
204 hSaveStdout = GetStdHandle(STD_OUTPUT_HANDLE);
205 hSaveStderr = GetStdHandle(STD_ERROR_HANDLE);
207 if (*mode == _T('w')) {
209 dwDup = STD_INPUT_HANDLE;
214 dwDup = STD_OUTPUT_HANDLE;
219 fhNeeded = phdls[ineeded];
220 fhInherited = phdls[iinherited];
222 fSuccess = DuplicateHandle(GetCurrentProcess(),
223 (HANDLE) stolen_get_osfhandle(fhNeeded),
227 FALSE, /* not inherited */
228 DUPLICATE_SAME_ACCESS);
230 if (!fSuccess) goto error2;
232 fhDup = stolen_open_osfhandle((long) hPNeeded, tm);
233 win32_dup2(fhDup, fhNeeded);
237 /* Close the Out pipe, child won't need it */
238 hPDuped = (HANDLE) stolen_get_osfhandle(fhNeeded);
240 _lock_fhandle(fhNeeded);
241 _set_osfhnd(fhNeeded, (long) hPNeeded); // put in ours duplicated one
242 _unlock_fhandle(fhNeeded);
244 CloseHandle(hPDuped); // close the handle first
247 if (!SetStdHandle(dwDup, (HANDLE) stolen_get_osfhandle(fhInherited))) goto error2;
250 // make sure the child see the same stderr as the calling program
253 if (!SetStdHandle(STD_ERROR_HANDLE, (HANDLE) stolen_get_osfhandle(win32_fileno(win32_stderr())))) goto error2;
255 pf = win32_popen(cmd, mode); // ask _popen to do the job
257 /* restore to where we were */
258 SetStdHandle(STD_INPUT_HANDLE, hSaveStdin);
259 SetStdHandle(STD_OUTPUT_HANDLE, hSaveStdout);
260 SetStdHandle(STD_ERROR_HANDLE, hSaveStderr);
262 /* we don't need it any more, that's for the child */
263 win32_close(fhInherited);
267 win32_close(fhNeeded);
273 * here we steal the file handle in pf and stuff ours in
276 win32_dup2(fhNeeded, win32_fileno(pf));
277 win32_close(fhNeeded);
283 win32_close(fhNeeded);
284 win32_close(fhInherited);
292 long my_pclose(PerlIO *fp)
294 return win32_pclose(fp);
297 static void IdOS(void)
301 memset(&osver, 0, sizeof(OSVERSIONINFO));
302 osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
303 GetVersionEx(&osver);
304 Win32System = osver.dwPlatformId;
308 static char *GetShell(void)
310 static char* szWin95ShellEntry = "Win95Shell";
311 static char* szWin95DefaultShell = "Cmd32.exe";
312 static char* szWinNTDefaultShell = "cmd.exe";
315 IdOS(), ProbeEnv = TRUE;
317 strcpy(szShellPath, szWin95DefaultShell);
320 strcpy(szShellPath, szWinNTDefaultShell);
327 int do_aspawn(void* really, void** mark, void** arglast)
335 SV *sv = (SV*)really;
336 SV** pSv = (SV**)mark;
338 New(1110, argv, (arglast - mark) + 3, char*);
342 cmd = SvPV(sv, length);
347 argv[index++] = "/c";
350 while(pSv <= (SV**)arglast)
353 strPtr = SvPV(sv, length);
354 if(strPtr != NULL && *strPtr != '\0')
355 argv[index++] = strPtr;
359 status = win32_spawnvpe(P_WAIT, cmd, (const char* const*)argv, (const char* const*)environ);
363 // set statusvalue the perl variable $?
364 return (statusvalue = status*256);
367 int do_spawn(char *cmd)
373 BOOL needToTry = TRUE;
376 /* save an extra exec if possible */
379 /* see if there are shell metacharacters in it */
380 if(!HasRedirection(cmd))
382 New(1102,argv, strlen(cmd) / 2 + 2, char*);
384 New(1103,cmd2, strlen(cmd) + 1, char);
389 while(*s && isspace(*s)) s++;
392 while(*s && !isspace(*s)) s++;
399 status = win32_spawnvpe(P_WAIT, argv[0], (const char* const*)argv, (const char* const*)environ);
400 if(status != -1 || errno == 0)
408 status = win32_spawnle(P_WAIT, shell, shell, "/c", cmd, (char*)0, environ);
411 // set statusvalue the perl variable $?
412 return (statusvalue = status*256);
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.
421 DIR *opendir(char *filename)
426 char scannamespc[PATHLEN];
427 char *scanname = scannamespc;
429 WIN32_FIND_DATA FindData;
431 // char root[_MAX_PATH];
432 // char volname[_MAX_PATH];
433 // DWORD serial, maxname, flags;
437 // check to see if filename is a directory
438 if(stat(filename, &sbuf) < 0 || sbuf.st_mode & _S_IFDIR == 0)
443 // get the file system characteristics
444 // if(GetFullPathName(filename, MAX_PATH, root, &dummy))
446 // if(dummy = strchr(root, '\\'))
448 // if(GetVolumeInformation(root, volname, MAX_PATH, &serial, &maxname, &flags, 0, 0))
450 // downcase = !(flags & FS_CASE_IS_PRESERVED);
458 // Get us a DIR structure
459 Newz(1501, p, 1, DIR);
463 // Create the search pattern
464 strcpy(scanname, filename);
466 if(index("/\\", *(scanname + strlen(scanname) - 1)) == NULL)
467 strcat(scanname, "/*");
469 strcat(scanname, "*");
471 // do the FindFirstFile call
472 fh = FindFirstFile(scanname, &FindData);
473 if(fh == INVALID_HANDLE_VALUE)
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);
483 CROAK("opendir: malloc failed!\n");
485 strcpy(p->start, FindData.cFileName);
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.
495 while(FindNextFile(fh, &FindData))
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);
503 CROAK("opendir: malloc failed!\n");
505 strcpy(&p->start[idx], FindData.cFileName);
507 // strlwr(&p->start[idx]);
518 // Readdir just returns the current string pointer and bumps the
519 // string pointer to the nDllExport entry.
520 struct direct *readdir(DIR *dirp)
523 static int dummy = 0;
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;
532 dirp->dirstr.d_ino = dummy++;
534 // Now set up for the nDllExport call to readdir
535 dirp->curr += len + 1;
536 if(dirp->curr >= (dirp->start + dirp->size))
541 return &(dirp->dirstr);
547 // Telldir returns the current string pointer position
548 long telldir(DIR *dirp)
550 return (long) dirp->curr;
554 // Seekdir moves the string pointer to a previously saved position (Saved by telldir).
555 void seekdir(DIR *dirp, long loc)
557 dirp->curr = (char *)loc;
560 // Rewinddir resets the string pointer to the start
561 void rewinddir(DIR *dirp)
563 dirp->curr = dirp->start;
566 // free the memory allocated by opendir
567 int closedir(DIR *dirp)
569 Safefree(dirp->start);
582 // Just pretend that everyone is a superuser. NT will let us know if
583 // we don\'t really have permission to do something.
586 #define ROOT_UID ((uid_t)0)
587 #define ROOT_GID ((gid_t)0)
609 int setuid(uid_t uid)
611 return (uid == ROOT_UID ? 0 : -1);
614 int setgid(gid_t gid)
616 return (gid == ROOT_GID ? 0 : -1);
622 int kill(int pid, int sig)
624 HANDLE hProcess= OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
626 if (hProcess == NULL) {
627 CROAK("kill process failed!\n");
630 if (!TerminateProcess(hProcess, sig)) CROAK("kill process failed!\n");
631 CloseHandle(hProcess);
640 int ioctl(int i, unsigned int u, char *data)
642 CROAK("ioctl not implemented!\n");
646 unsigned int sleep(unsigned int t)
655 int myrename(char *OldFileName, char *newname)
657 if(_access(newname, 0) != -1)
661 return rename(OldFileName, newname);
665 int win32_stat(const char *path, struct stat *buffer)
668 const char *p = path;
669 int l = strlen(path);
672 switch(path[l - 1]) {
675 if (path[l - 2] != ':') {
676 strncpy(t, path, l - 1);
683 return stat(p, buffer);
687 int mytimes(struct tms *timebuf)
690 timebuf->tms_utime = t;
691 timebuf->tms_stime = 0;
692 timebuf->tms_cutime = 0;
693 timebuf->tms_cstime = 0;
699 unsigned int myalarm(unsigned int sec)
701 // we warn the usuage of alarm function
703 WARN("dummy function alarm called, program might not function as expected\n");
708 // redirected io subsystem for all XS modules
712 DllExport int * win32_errno(void)
714 return (pIOSubSystem->pfnerrno());
717 // the rest are the remapped stdio routines
718 DllExport FILE *win32_stderr(void)
720 return (pIOSubSystem->pfnstderr());
723 DllExport FILE *win32_stdin(void)
725 return (pIOSubSystem->pfnstdin());
728 DllExport FILE *win32_stdout()
730 return (pIOSubSystem->pfnstdout());
733 DllExport int win32_ferror(FILE *fp)
735 return (pIOSubSystem->pfnferror(fp));
739 DllExport int win32_feof(FILE *fp)
741 return (pIOSubSystem->pfnfeof(fp));
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.
750 __declspec(thread) char strerror_buffer[512];
752 DllExport char *win32_strerror(int e)
757 if(e < 0 || e > sys_nerr)
762 if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, &source, e, 0, strerror_buffer, sizeof(strerror_buffer), NULL) == 0)
763 strcpy(strerror_buffer, "Unknown Error");
765 return strerror_buffer;
768 return pIOSubSystem->pfnstrerror(e);
771 DllExport int win32_fprintf(FILE *fp, const char *format, ...)
774 va_start(marker, format); /* Initialize variable arguments. */
776 return (pIOSubSystem->pfnvfprintf(fp, format, marker));
779 DllExport int win32_printf(const char *format, ...)
782 va_start(marker, format); /* Initialize variable arguments. */
784 return (pIOSubSystem->pfnvprintf(format, marker));
787 DllExport int win32_vfprintf(FILE *fp, const char *format, va_list args)
789 return (pIOSubSystem->pfnvfprintf(fp, format, args));
792 DllExport size_t win32_fread(void *buf, size_t size, size_t count, FILE *fp)
794 return pIOSubSystem->pfnfread(buf, size, count, fp);
797 DllExport size_t win32_fwrite(const void *buf, size_t size, size_t count, FILE *fp)
799 return pIOSubSystem->pfnfwrite(buf, size, count, fp);
802 DllExport FILE *win32_fopen(const char *filename, const char *mode)
804 if (stricmp(filename, "/dev/null")==0) return pIOSubSystem->pfnfopen("NUL", mode);
805 return pIOSubSystem->pfnfopen(filename, mode);
808 DllExport FILE *win32_fdopen( int handle, const char *mode)
810 return pIOSubSystem->pfnfdopen(handle, mode);
813 DllExport FILE *win32_freopen( const char *path, const char *mode, FILE *stream)
815 if (stricmp(path, "/dev/null")==0) return pIOSubSystem->pfnfreopen("NUL", mode, stream);
816 return pIOSubSystem->pfnfreopen(path, mode, stream);
819 DllExport int win32_fclose(FILE *pf)
821 return pIOSubSystem->pfnfclose(pf);
824 DllExport int win32_fputs(const char *s,FILE *pf)
826 return pIOSubSystem->pfnfputs(s, pf);
829 DllExport int win32_fputc(int c,FILE *pf)
831 return pIOSubSystem->pfnfputc(c,pf);
834 DllExport int win32_ungetc(int c,FILE *pf)
836 return pIOSubSystem->pfnungetc(c,pf);
839 DllExport int win32_getc(FILE *pf)
841 return pIOSubSystem->pfngetc(pf);
844 DllExport int win32_fileno(FILE *pf)
846 return pIOSubSystem->pfnfileno(pf);
849 DllExport void win32_clearerr(FILE *pf)
851 pIOSubSystem->pfnclearerr(pf);
855 DllExport int win32_fflush(FILE *pf)
857 return pIOSubSystem->pfnfflush(pf);
860 DllExport long win32_ftell(FILE *pf)
862 return pIOSubSystem->pfnftell(pf);
865 DllExport int win32_fseek(FILE *pf,long offset,int origin)
867 return pIOSubSystem->pfnfseek(pf, offset, origin);
870 DllExport int win32_fgetpos(FILE *pf,fpos_t *p)
872 return pIOSubSystem->pfnfgetpos(pf, p);
875 DllExport int win32_fsetpos(FILE *pf,const fpos_t *p)
877 return pIOSubSystem->pfnfsetpos(pf, p);
880 DllExport void win32_rewind(FILE *pf)
882 pIOSubSystem->pfnrewind(pf);
886 DllExport FILE* win32_tmpfile(void)
888 return pIOSubSystem->pfntmpfile();
891 DllExport void win32_abort(void)
893 pIOSubSystem->pfnabort();
897 DllExport int win32_fstat(int fd,struct stat *bufptr)
899 return pIOSubSystem->pfnfstat(fd,bufptr);
902 DllExport int win32_pipe(int *pfd, unsigned int size, int mode)
904 return pIOSubSystem->pfnpipe(pfd, size, mode);
907 DllExport FILE* win32_popen(const char *command, const char *mode)
909 return pIOSubSystem->pfnpopen(command, mode);
912 DllExport int win32_pclose(FILE *pf)
914 return pIOSubSystem->pfnpclose(pf);
917 DllExport int win32_setmode(int fd, int mode)
919 return pIOSubSystem->pfnsetmode(fd, mode);
922 DllExport int win32_open(const char *path, int flag, ...)
928 pmode = va_arg(ap, int);
931 if (stricmp(path, "/dev/null")==0) return pIOSubSystem->pfnopen("NUL", flag, pmode);
932 return pIOSubSystem->pfnopen(path,flag,pmode);
935 DllExport int win32_close(int fd)
937 return pIOSubSystem->pfnclose(fd);
940 DllExport int win32_dup(int fd)
942 return pIOSubSystem->pfndup(fd);
945 DllExport int win32_dup2(int fd1,int fd2)
947 return pIOSubSystem->pfndup2(fd1,fd2);
950 DllExport int win32_read(int fd, char *buf, unsigned int cnt)
952 return pIOSubSystem->pfnread(fd, buf, cnt);
955 DllExport int win32_write(int fd, const char *buf, unsigned int cnt)
957 return pIOSubSystem->pfnwrite(fd, buf, cnt);
960 DllExport int win32_spawnvpe(int mode, const char *cmdname, const char *const *argv, const char *const *envp)
962 return pIOSubSystem->pfnspawnvpe(mode, cmdname, argv, envp);
965 DllExport int win32_spawnle(int mode, const char *cmdname, const char *arglist,...)
967 const char* const* envp;
968 const char* const* argp;
973 return pIOSubSystem->pfnspawnvpe(mode, cmdname, &arglist, argp);
976 int stolen_open_osfhandle(long handle, int flags)
978 return pIOSubSystem->pfn_open_osfhandle(handle, flags);
981 long stolen_get_osfhandle(int fd)
983 return pIOSubSystem->pfn_get_osfhandle(fd);