on windows, the return values from wait() and waitpid() don't
[p5sagit/p5-mst-13.2.git] / win32 / win32.c
index b4ad80c..56ebdaf 100644 (file)
 #define Win32_Winsock
 #endif
 #include <windows.h>
+#ifndef __MINGW32__    /* GCC/Mingw32-2.95.2 forgot the WINAPI on CommandLineToArgvW() */
+#  include <shellapi.h>
+#else
+   LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCommandLine, int * pNumArgs);
+#endif
 #include <winnt.h>
 #include <io.h>
 
@@ -41,7 +46,6 @@
 #endif
 #include <string.h>
 #include <stdarg.h>
-#include <stdlib.h> /* get a real declaration of sys_nerr */
 #include <float.h>
 #include <time.h>
 #if defined(_MSC_VER) || defined(__MINGW32__)
@@ -49,7 +53,6 @@
 #else
 #include <utime.h>
 #endif
-
 #ifdef __GNUC__
 /* Mingw32 defaults to globing command line 
  * So we turn it off like this:
@@ -1609,11 +1612,7 @@ win32_uname(struct utsname *name)
        GetSystemInfo(&info);
 
 #if defined(__BORLANDC__) || defined(__MINGW32__)
-#ifndef _STRUCT_NAME
-#  define _STRUCT_NAME(s) s
-#  define _UNION_NAME(u) u
-#endif
-       switch (info._UNION_NAME(u.)_STRUCT_NAME(s.)wProcessorArchitecture) {
+       switch (info.u.s.wProcessorArchitecture) {
 #else
        switch (info.wProcessorArchitecture) {
 #endif
@@ -1645,13 +1644,17 @@ win32_waitpid(int pid, int *status, int flags)
        long child = find_pseudo_pid(-pid);
        if (child >= 0) {
            HANDLE hThread = w32_pseudo_child_handles[child];
-           DWORD waitcode = WaitForSingleObject(hThread, INFINITE);
-           if (waitcode != WAIT_FAILED) {
+           DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE;
+           DWORD waitcode = WaitForSingleObject(hThread, timeout);
+           if (waitcode == WAIT_TIMEOUT) {
+               return 0;
+           }
+           else if (waitcode != WAIT_FAILED) {
                if (GetExitCodeThread(hThread, &waitcode)) {
                    *status = (int)((waitcode & 0xff) << 8);
                    retval = (int)w32_pseudo_child_pids[child];
                    remove_dead_pseudo_process(child);
-                   return retval;
+                   return -retval;
                }
            }
            else
@@ -1663,14 +1666,18 @@ win32_waitpid(int pid, int *status, int flags)
        long child = find_pid(pid);
        if (child >= 0) {
            HANDLE hProcess = w32_child_handles[child];
-           DWORD waitcode = WaitForSingleObject(hProcess, INFINITE);
-           if (waitcode != WAIT_FAILED) {
-               if (GetExitCodeProcess(hProcess, &waitcode)) {
-                   *status = (int)((waitcode & 0xff) << 8);
-                   retval = (int)w32_child_pids[child];
-                   remove_dead_process(child);
-                   return retval;
-               }
+           DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE;
+           DWORD waitcode = WaitForSingleObject(hProcess, timeout);
+           if (waitcode == WAIT_TIMEOUT) {
+               return 0;
+           }
+           else if (waitcode != WAIT_FAILED) {
+                if (GetExitCodeProcess(hProcess, &waitcode)) {
+                    *status = (int)((waitcode & 0xff) << 8);
+                    retval = (int)w32_child_pids[child];
+                    remove_dead_process(child);
+                    return retval;
+                }
            }
            else
                errno = ECHILD;
@@ -1713,7 +1720,7 @@ win32_wait(int *status)
                *status = (int)((exitcode & 0xff) << 8);
                retval = (int)w32_pseudo_child_pids[i];
                remove_dead_pseudo_process(i);
-               return retval;
+               return -retval;
            }
        }
     }
@@ -2057,6 +2064,9 @@ win32_feof(FILE *fp)
 DllExport char *
 win32_strerror(int e) 
 {
+#ifndef __BORLANDC__           /* Borland intolerance */
+    extern int sys_nerr;
+#endif
     DWORD source = 0;
 
     if (e < 0 || e > sys_nerr) {
@@ -2390,9 +2400,9 @@ win32_popen(const char *command, const char *mode)
        /* close saved handle */
        win32_close(oldfd);
 
-       MUTEX_LOCK(&PL_fdpid_mutex);
+       LOCK_FDPID_MUTEX;
        sv_setiv(*av_fetch(w32_fdpid, p[parent], TRUE), childpid);
-       MUTEX_UNLOCK(&PL_fdpid_mutex);
+       UNLOCK_FDPID_MUTEX;
 
        /* set process id so that it can be returned by perl's open() */
        PL_forkprocess = childpid;
@@ -2428,9 +2438,9 @@ win32_pclose(FILE *pf)
     int childpid, status;
     SV *sv;
 
-    MUTEX_LOCK(&PL_fdpid_mutex);
+    LOCK_FDPID_MUTEX;
     sv = *av_fetch(w32_fdpid, win32_fileno(pf), TRUE);
-    MUTEX_UNLOCK(&PL_fdpid_mutex);
+
     if (SvIOK(sv))
        childpid = SvIVX(sv);
     else
@@ -2443,6 +2453,7 @@ win32_pclose(FILE *pf)
 
     win32_fclose(pf);
     SvIVX(sv) = 0;
+    UNLOCK_FDPID_MUTEX;
 
     if (win32_waitpid(childpid, &status, 0) == -1)
         return -1;
@@ -2490,8 +2501,8 @@ Nt4CreateHardLinkW(
     StreamId.dwStreamAttributes = 0;
     StreamId.dwStreamNameSize = 0;
 #if defined(__BORLANDC__) || defined(__MINGW32__)
-    StreamId.Size._UNION_NAME(u.)HighPart = 0;
-    StreamId.Size._UNION_NAME(u.)LowPart = dwLen;
+    StreamId.Size.u.HighPart = 0;
+    StreamId.Size.u.LowPart = dwLen;
 #else
     StreamId.Size.HighPart = 0;
     StreamId.Size.LowPart = dwLen;
@@ -4055,6 +4066,18 @@ Perl_sys_intern_init(pTHX)
     w32_init_socktype          = 0;
 }
 
+void
+Perl_sys_intern_clear(pTHX)
+{
+    Safefree(w32_perlshell_tokens);
+    Safefree(w32_perlshell_vec);
+    /* NOTE: w32_fdpid is freed by sv_clean_all() */
+    Safefree(w32_children);
+#  ifdef USE_ITHREADS
+    Safefree(w32_pseudo_children);
+#  endif
+}
+
 #  ifdef USE_ITHREADS
 
 void
@@ -4069,18 +4092,6 @@ Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst)
     Newz(1313, dst->pseudo_children, 1, child_tab);
     dst->thr_intern.Winit_socktype = src->thr_intern.Winit_socktype;
 }
-
-void
-Perl_sys_intern_clear(pTHX)
-{
-    Safefree(w32_perlshell_tokens);
-    Safefree(w32_perlshell_vec);
-    /* NOTE: w32_fdpid is freed by sv_clean_all() */
-    Safefree(w32_children);
-#  ifdef USE_ITHREADS
-    Safefree(w32_pseudo_children);
-#  endif
-}
 #  endif /* USE_ITHREADS */
 #endif /* HAVE_INTERP_INTERN */
 
@@ -4099,21 +4110,13 @@ win32_free_argvw(pTHXo_ void *ptr)
     }
 }
 
-typedef LPWSTR* (WINAPI CLTARGVW)(LPCWSTR lpCommandLine, int * pNumArgs);
-/* load shell32.dll on demand (reduces number of DLLs loaded on startup by 1/3)
-       -- BKS 5-28-2000 */
 void
 win32_argv2utf8(int argc, char** argv)
 {
     dTHXo;
     char* psz;
     int length, wargc;
-    HANDLE hDll = LoadLibraryA("shell32.dll");
-    CLTARGVW *pCommandLineToArgvW = NULL;
-    LPWSTR* lpwStr = NULL;
-    if (hDll && (pCommandLineToArgvW = (CLTARGVW*)GetProcAddress(hDll, "CommandLineToArgvW"))) {
-       lpwStr = (*pCommandLineToArgvW)(GetCommandLineW(), &wargc);
-    }
+    LPWSTR* lpwStr = CommandLineToArgvW(GetCommandLineW(), &wargc);
     if (lpwStr && argc) {
        while (argc--) {
            length = WideCharToMultiByte(CP_UTF8, 0, lpwStr[--wargc], -1, NULL, 0, NULL, NULL);
@@ -4123,7 +4126,6 @@ win32_argv2utf8(int argc, char** argv)
        }
        call_atexit(win32_free_argvw, argv);
     }
-    if (hDll)
-       FreeLibrary(hDll);
     GlobalFree((HGLOBAL)lpwStr);
 }
+