Protect against having no such command as 'cc'
[p5sagit/p5-mst-13.2.git] / win32 / win32.c
index 7bb003d..9a0f910 100644 (file)
 #define CROAK croak
 #define WARN warn
 
+static DWORD IdOS(void);
+
 extern WIN32_IOSUBSYSTEM       win32stdio;
 __declspec(thread) PWIN32_IOSUBSYSTEM  pIOSubSystem = &win32stdio;
 /*__declspec(thread) PWIN32_IOSUBSYSTEM        pIOSubSystem = NULL;*/
 
 BOOL  ProbeEnv = FALSE;
-DWORD Win32System;
+DWORD Win32System = (DWORD)-1;
 char  szShellPath[MAX_PATH+1];
 char  szPerlLibRoot[MAX_PATH+1];
 HANDLE PerlDllHandle = INVALID_HANDLE_VALUE;
 
 int 
 IsWin95(void) {
-    return (Win32System == VER_PLATFORM_WIN32_WINDOWS);
+    return (IdOS() == VER_PLATFORM_WIN32_WINDOWS);
 }
 
 int
 IsWinNT(void) {
-    return (Win32System == VER_PLATFORM_WIN32_NT);
+    return (IdOS() == VER_PLATFORM_WIN32_NT);
 }
 
 void *
 SetIOSubSystem(void *p)
 {
+    PWIN32_IOSUBSYSTEM old = pIOSubSystem;
     if (p) {
        PWIN32_IOSUBSYSTEM pio = (PWIN32_IOSUBSYSTEM)p;
-
        if (pio->signature_begin == 12345678L
            && pio->signature_end == 87654321L) {
-           PWIN32_IOSUBSYSTEM pold = pIOSubSystem;
            pIOSubSystem = pio;
-           return pold;
        }
     }
     else {
-       /* re-assign our stuff */
-/*     pIOSubSystem = &win32stdio; */
-       pIOSubSystem = NULL;
+       pIOSubSystem = &win32stdio;
     }
-    return pIOSubSystem;
+    return old;
 }
 
 char *
@@ -302,16 +300,18 @@ my_pclose(PerlIO *fp)
     return win32_pclose(fp);
 }
 
-static void
+static DWORD
 IdOS(void)
 {
-    OSVERSIONINFO osver;
+    static OSVERSIONINFO osver;
 
-    memset(&osver, 0, sizeof(OSVERSIONINFO));
-    osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-    GetVersionEx(&osver);
-    Win32System = osver.dwPlatformId;
-    return;
+    if (osver.dwPlatformId != Win32System) {
+       memset(&osver, 0, sizeof(OSVERSIONINFO));
+       osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+       GetVersionEx(&osver);
+       Win32System = osver.dwPlatformId;
+    }
+    return (Win32System);
 }
 
 static char *
@@ -322,7 +322,7 @@ GetShell(void)
     static char* szWinNTDefaultShell = "cmd.exe";
    
     if (!ProbeEnv) {
-       IdOS(), ProbeEnv = TRUE;
+       ProbeEnv = TRUE;
        if (IsWin95()) {
            strcpy(szShellPath, szWin95DefaultShell);
        }
@@ -345,7 +345,7 @@ do_aspawn(void* really, void** mark, void** arglast)
     SV *sv = (SV*)really;
     SV** pSv = (SV**)mark;
 
-    New(1110, argv, (arglast - mark) + 4, char*);
+    New(1310, argv, (arglast - mark) + 4, char*);
 
     if(sv != Nullsv) {
        cmd = SvPV(sv, length);
@@ -392,8 +392,8 @@ do_spawn(char *cmd)
 
     /* see if there are shell metacharacters in it */
     if(!HasRedirection(cmd)) {
-       New(1102,argv, strlen(cmd) / 2 + 2, char*);
-       New(1103,cmd2, strlen(cmd) + 1, char);
+       New(1301,argv, strlen(cmd) / 2 + 2, char*);
+       New(1302,cmd2, strlen(cmd) + 1, char);
        strcpy(cmd2, cmd);
        a = argv;
        for (s = cmd2; *s;) {
@@ -477,7 +477,7 @@ opendir(char *filename)
  *  }
  */
     /* Get us a DIR structure */
-    Newz(1501, p, 1, DIR);
+    Newz(1303, p, 1, DIR);
     if(p == NULL)
        return NULL;
 
@@ -499,7 +499,7 @@ opendir(char *filename)
      * the filenames that we find.
      */
     idx = strlen(FindData.cFileName)+1;
-    New(1502, p->start, idx, char);
+    New(1304, p->start, idx, char);
     if(p->start == NULL) {
        CROAK("opendir: malloc failed!\n");
     }
@@ -756,6 +756,12 @@ win32_errno(void)
     return (pIOSubSystem->pfnerrno());
 }
 
+DllExport char ***
+win32_environ(void)
+{
+    return (pIOSubSystem->pfnenviron());
+}
+
 /* the rest are the remapped stdio routines */
 DllExport FILE *
 win32_stderr(void)
@@ -839,6 +845,12 @@ win32_vfprintf(FILE *fp, const char *format, va_list args)
     return (pIOSubSystem->pfnvfprintf(fp, format, args));
 }
 
+DllExport int
+win32_vprintf(const char *format, va_list args)
+{
+    return (pIOSubSystem->pfnvprintf(format, args));
+}
+
 DllExport size_t
 win32_fread(void *buf, size_t size, size_t count, FILE *fp)
 {
@@ -996,6 +1008,18 @@ win32_setmode(int fd, int mode)
     return pIOSubSystem->pfnsetmode(fd, mode);
 }
 
+DllExport long
+win32_lseek(int fd, long offset, int origin)
+{
+    return pIOSubSystem->pfnlseek(fd, offset, origin);
+}
+
+DllExport long
+win32_tell(int fd)
+{
+    return pIOSubSystem->pfntell(fd);
+}
+
 DllExport int
 win32_open(const char *path, int flag, ...)
 {
@@ -1018,6 +1042,12 @@ win32_close(int fd)
 }
 
 DllExport int
+win32_eof(int fd)
+{
+    return pIOSubSystem->pfneof(fd);
+}
+
+DllExport int
 win32_dup(int fd)
 {
     return pIOSubSystem->pfndup(fd);
@@ -1046,16 +1076,19 @@ win32_mkdir(const char *dir, int mode)
 {
     return pIOSubSystem->pfnmkdir(dir); /* just ignore mode */
 }
+
 DllExport int
 win32_rmdir(const char *dir)
 {
     return pIOSubSystem->pfnrmdir(dir);
 }
+
 DllExport int
 win32_chdir(const char *dir)
 {
     return pIOSubSystem->pfnchdir(dir);
 }
+
 DllExport int
 win32_spawnvpe(int mode, const char *cmdname,
               const char *const *argv, const char *const *envp)
@@ -1087,3 +1120,57 @@ stolen_get_osfhandle(int fd)
 {
     return pIOSubSystem->pfn_get_osfhandle(fd);
 }
+
+
+/*
+ * Extras.
+ */
+
+/* simulate flock by locking a range on the file */
+
+#define LK_ERR(f,i)    ((f) ? (i = 0) : (errno = GetLastError()))
+#define LK_LEN         0xffff0000
+
+DllExport int
+win32_flock(int fd, int oper)
+{
+    OVERLAPPED o;
+    int i = -1;
+    HANDLE fh;
+
+    if (!IsWinNT()) {
+       croak("flock() unimplemented on this platform");
+       return -1;
+    }
+
+    fh = (HANDLE)stolen_get_osfhandle(fd);
+    memset(&o, 0, sizeof(o));
+
+    switch(oper) {
+    case LOCK_SH:              /* shared lock */
+       LK_ERR(LockFileEx(fh, 0, 0, LK_LEN, 0, &o),i);
+       break;
+    case LOCK_EX:              /* exclusive lock */
+       LK_ERR(LockFileEx(fh, LOCKFILE_EXCLUSIVE_LOCK, 0, LK_LEN, 0, &o),i);
+       break;
+    case LOCK_SH|LOCK_NB:      /* non-blocking shared lock */
+       LK_ERR(LockFileEx(fh, LOCKFILE_FAIL_IMMEDIATELY, 0, LK_LEN, 0, &o),i);
+       break;
+    case LOCK_EX|LOCK_NB:      /* non-blocking exclusive lock */
+       LK_ERR(LockFileEx(fh,
+                      LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY,
+                      0, LK_LEN, 0, &o),i);
+       break;
+    case LOCK_UN:              /* unlock lock */
+       LK_ERR(UnlockFileEx(fh, 0, LK_LEN, 0, &o),i);
+       break;
+    default:                   /* unknown */
+       errno = EINVAL;
+       break;
+    }
+    return i;
+}
+
+#undef LK_ERR
+#undef LK_LEN
+