From 3c44a88685f8bcc42a9acf4811d502221f024489 Mon Sep 17 00:00:00 2001
From: Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>
Date: Sun, 24 Apr 2011 12:30:30 +1200
Subject: [PATCH] Use getProcessId from Win32 package System.Win32.Process

---
 System/Process.hs           | 1260 +++++++++++++++++------------------
 System/Process/Internals.hs |   10 +-
 cbits/runProcess.c          | 1072 ++++++++++++++---------------
 include/runProcess.h        |  154 ++---
 4 files changed, 1250 insertions(+), 1246 deletions(-)

diff --git a/System/Process.hs b/System/Process.hs
index 677b446b..f2e2e7c0 100644
--- a/System/Process.hs
+++ b/System/Process.hs
@@ -1,630 +1,630 @@
-{-# LANGUAGE CPP, ForeignFunctionInterface #-}
------------------------------------------------------------------------------
--- |
--- Module      :  System.Process
--- Copyright   :  (c) The University of Glasgow 2004-2008
--- License     :  BSD-style (see the file libraries/base/LICENSE)
---
--- Maintainer  :  libraries@haskell.org
--- Stability   :  experimental
--- Portability :  non-portable (requires concurrency)
---
--- Operations for creating and interacting with sub-processes.
---
------------------------------------------------------------------------------
-
--- ToDo:
---	* Flag to control whether exiting the parent also kills the child.
-
-{- NOTES on createPipe:
- 
-   createPipe is no longer exported, because of the following problems:
-
-	- it wasn't used to implement runInteractiveProcess on Unix, because
-	  the file descriptors for the unused ends of the pipe need to be closed
-	  in the child process.
-
-        - on Windows, a special version of createPipe is needed that sets
-	  the inheritance flags correctly on the ends of the pipe (see
-	  mkAnonPipe below).
--}
-
-module System.Process (
-#ifndef __HUGS__
-	-- * Running sub-processes
-        createProcess,
-        shell, proc,
-        CreateProcess(..),
-        CmdSpec(..),
-        StdStream(..),
-	ProcessHandle,
-
-        -- ** Specific variants of createProcess
-	runCommand,
-	runProcess,
-	runInteractiveCommand,
-	runInteractiveProcess,
-        readProcess,
-        readProcessWithExitCode,
-#endif
-        system,
-        rawSystem,
-        showCommandForUser,
-
-#ifndef __HUGS__
-	-- * Process completion
-	waitForProcess,
-	getProcessExitCode,
-	terminateProcess,
-	interruptProcessGroupOf,
-#endif
- ) where
-
-import Prelude hiding (mapM)
-
-#ifndef __HUGS__
-import System.Process.Internals
-
-import System.IO.Error
-import qualified Control.Exception as C
-import Control.Concurrent
-import Control.Monad
-import Foreign
-import Foreign.C
-import System.IO
-import Data.Maybe
-#endif
-import System.Exit	( ExitCode(..) )
-
-#ifdef __GLASGOW_HASKELL__
-#if __GLASGOW_HASKELL__ >= 611
-import GHC.IO.Exception	( ioException, IOErrorType(..) )
-#else
-import GHC.IOBase	( ioException, IOErrorType(..) )
-#endif
-#if defined(mingw32_HOST_OS)
-import System.Win32.Console (generateConsoleCtrlEvent, cTRL_BREAK_EVENT)
-#else
-import System.Posix.Signals
-#endif
-#endif
-
-#ifdef __HUGS__
-import Hugs.System
-#endif
-
-#ifdef __NHC__
-import System (system)
-#endif
-
-
-#ifndef __HUGS__
--- ----------------------------------------------------------------------------
--- runCommand
-
-{- | Runs a command using the shell.
- -}
-runCommand
-  :: String
-  -> IO ProcessHandle
-
-runCommand string = do
-  (_,_,_,ph) <- runGenProcess_ "runCommand" (shell string) Nothing Nothing
-  return ph
-
--- ----------------------------------------------------------------------------
--- runProcess
-
-{- | Runs a raw command, optionally specifying 'Handle's from which to
-     take the @stdin@, @stdout@ and @stderr@ channels for the new
-     process (otherwise these handles are inherited from the current
-     process).
-
-     Any 'Handle's passed to 'runProcess' are placed immediately in the 
-     closed state.
-
-     Note: consider using the more general 'createProcess' instead of
-     'runProcess'.
--}
-runProcess
-  :: FilePath			-- ^ Filename of the executable
-  -> [String]			-- ^ Arguments to pass to the executable
-  -> Maybe FilePath		-- ^ Optional path to the working directory
-  -> Maybe [(String,String)]	-- ^ Optional environment (otherwise inherit)
-  -> Maybe Handle		-- ^ Handle to use for @stdin@ (Nothing => use existing @stdin@)
-  -> Maybe Handle		-- ^ Handle to use for @stdout@ (Nothing => use existing @stdout@)
-  -> Maybe Handle		-- ^ Handle to use for @stderr@ (Nothing => use existing @stderr@)
-  -> IO ProcessHandle
-
-runProcess cmd args mb_cwd mb_env mb_stdin mb_stdout mb_stderr = do
-  (_,_,_,ph) <-
-      runGenProcess_ "runProcess"
-         (proc cmd args){ cwd = mb_cwd,
-                          env = mb_env,
-                          std_in  = mbToStd mb_stdin,
-                          std_out = mbToStd mb_stdout,
-                          std_err = mbToStd mb_stderr }
-	  Nothing Nothing
-  maybeClose mb_stdin
-  maybeClose mb_stdout
-  maybeClose mb_stderr
-  return ph
- where
-  maybeClose :: Maybe Handle -> IO ()
-  maybeClose (Just  hdl)
-    | hdl /= stdin && hdl /= stdout && hdl /= stderr = hClose hdl
-  maybeClose _ = return ()
-
-  mbToStd :: Maybe Handle -> StdStream
-  mbToStd Nothing    = Inherit
-  mbToStd (Just hdl) = UseHandle hdl
-
--- ----------------------------------------------------------------------------
--- createProcess
-
--- | Construct a 'CreateProcess' record for passing to 'createProcess',
--- representing a raw command with arguments.
-proc :: FilePath -> [String] -> CreateProcess
-proc cmd args = CreateProcess { cmdspec = RawCommand cmd args,
-                                cwd = Nothing,
-                                env = Nothing,
-                                std_in = Inherit,
-                                std_out = Inherit,
-                                std_err = Inherit,
-                                close_fds = False,
-                                create_group = False}
-
--- | Construct a 'CreateProcess' record for passing to 'createProcess',
--- representing a command to be passed to the shell.
-shell :: String -> CreateProcess
-shell str = CreateProcess { cmdspec = ShellCommand str,
-                            cwd = Nothing,
-                            env = Nothing,
-                            std_in = Inherit,
-                            std_out = Inherit,
-                            std_err = Inherit,
-                            close_fds = False,
-                            create_group = False}
-
-{- |
-This is the most general way to spawn an external process.  The
-process can be a command line to be executed by a shell or a raw command
-with a list of arguments.  The stdin, stdout, and stderr streams of
-the new process may individually be attached to new pipes, to existing
-'Handle's, or just inherited from the parent (the default.)
-
-The details of how to create the process are passed in the
-'CreateProcess' record.  To make it easier to construct a
-'CreateProcess', the functions 'proc' and 'shell' are supplied that
-fill in the fields with default values which can be overriden as
-needed.
-
-'createProcess' returns @(mb_stdin_hdl, mb_stdout_hdl, mb_stderr_hdl, p)@,
-where 
-
- * if @std_in == CreatePipe@, then @mb_stdin_hdl@ will be @Just h@,
-   where @h@ is the write end of the pipe connected to the child
-   process's @stdin@.
-
- * otherwise, @mb_stdin_hdl == Nothing@
-
-Similarly for @mb_stdout_hdl@ and @mb_stderr_hdl@.
-
-For example, to execute a simple @ls@ command:
-
->   r <- createProcess (proc "ls" [])
-
-To create a pipe from which to read the output of @ls@:
-
->   (_, Just hout, _, _) <-
->       createProcess (proc "ls" []){ std_out = CreatePipe }
-
-To also set the directory in which to run @ls@:
-
->   (_, Just hout, _, _) <-
->       createProcess (proc "ls" []){ cwd = Just "\home\bob",
->                                     std_out = CreatePipe }
-
--}
-createProcess
-  :: CreateProcess
-  -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
-createProcess cp = do
-  r <- runGenProcess_ "createProcess" cp Nothing Nothing
-  maybeCloseStd (std_in  cp)
-  maybeCloseStd (std_out cp)
-  maybeCloseStd (std_err cp)
-  return r
- where
-  maybeCloseStd :: StdStream -> IO ()
-  maybeCloseStd (UseHandle hdl)
-    | hdl /= stdin && hdl /= stdout && hdl /= stderr = hClose hdl
-  maybeCloseStd _ = return ()
-
--- ----------------------------------------------------------------------------
--- runInteractiveCommand
-
-{- | Runs a command using the shell, and returns 'Handle's that may
-     be used to communicate with the process via its @stdin@, @stdout@,
-     and @stderr@ respectively. The 'Handle's are initially in binary
-     mode; if you need them to be in text mode then use 'hSetBinaryMode'.
--}
-runInteractiveCommand
-  :: String
-  -> IO (Handle,Handle,Handle,ProcessHandle)
-
-runInteractiveCommand string =
-  runInteractiveProcess1 "runInteractiveCommand" (shell string)
-
--- ----------------------------------------------------------------------------
--- runInteractiveProcess
-
-{- | Runs a raw command, and returns 'Handle's that may be used to communicate
-     with the process via its @stdin@, @stdout@ and @stderr@ respectively.
-
-    For example, to start a process and feed a string to its stdin:
-   
->   (inp,out,err,pid) <- runInteractiveProcess "..."
->   forkIO (hPutStr inp str)
-
-    The 'Handle's are initially in binary mode; if you need them to be
-    in text mode then use 'hSetBinaryMode'.
--}
-runInteractiveProcess
-  :: FilePath			-- ^ Filename of the executable
-  -> [String]			-- ^ Arguments to pass to the executable
-  -> Maybe FilePath		-- ^ Optional path to the working directory
-  -> Maybe [(String,String)]	-- ^ Optional environment (otherwise inherit)
-  -> IO (Handle,Handle,Handle,ProcessHandle)
-
-runInteractiveProcess cmd args mb_cwd mb_env = do
-  runInteractiveProcess1 "runInteractiveProcess" 
-        (proc cmd args){ cwd = mb_cwd, env = mb_env }
-
-runInteractiveProcess1
-  :: String
-  -> CreateProcess
-  -> IO (Handle,Handle,Handle,ProcessHandle)
-runInteractiveProcess1 fun cmd = do
-  (mb_in, mb_out, mb_err, p) <- 
-      runGenProcess_ fun
-           cmd{ std_in  = CreatePipe,
-                std_out = CreatePipe,
-                std_err = CreatePipe } 
-           Nothing Nothing
-  return (fromJust mb_in, fromJust mb_out, fromJust mb_err, p)
-
--- ----------------------------------------------------------------------------
--- waitForProcess
-
-{- | Waits for the specified process to terminate, and returns its exit code.
-   
-     GHC Note: in order to call @waitForProcess@ without blocking all the
-     other threads in the system, you must compile the program with
-     @-threaded@.
--}
-waitForProcess
-  :: ProcessHandle
-  -> IO ExitCode
-waitForProcess ph = do
-  p_ <- withProcessHandle ph $ \p_ -> return (p_,p_)
-  case p_ of
-    ClosedHandle e -> return e
-    OpenHandle h  -> do
-	-- don't hold the MVar while we call c_waitForProcess...
-	-- (XXX but there's a small race window here during which another
-	-- thread could close the handle or call waitForProcess)
-        alloca $ \pret -> do
-          throwErrnoIfMinus1Retry_ "waitForProcess" (c_waitForProcess h pret)
-          withProcessHandle ph $ \p_' ->
-            case p_' of
-              ClosedHandle e -> return (p_',e)
-              OpenHandle ph' -> do
-                closePHANDLE ph'
-                code <- peek pret
-                let e = if (code == 0)
-                       then ExitSuccess
-                       else (ExitFailure (fromIntegral code))
-                return (ClosedHandle e, e)
-
--- -----------------------------------------------------------------------------
---
--- | readProcess forks an external process, reads its standard output
--- strictly, blocking until the process terminates, and returns the output
--- string.
---
--- Output is returned strictly, so this is not suitable for
--- interactive applications.
---
--- Users of this function should compile with @-threaded@ if they
--- want other Haskell threads to keep running while waiting on
--- the result of readProcess.
---
--- >  > readProcess "date" [] []
--- >  "Thu Feb  7 10:03:39 PST 2008\n"
---
--- The arguments are:
---
--- * The command to run, which must be in the $PATH, or an absolute path
---
--- * A list of separate command line arguments to the program
---
--- * A string to pass on the standard input to the program.
---
-readProcess 
-    :: FilePath                 -- ^ command to run
-    -> [String]                 -- ^ any arguments
-    -> String                   -- ^ standard input
-    -> IO String                -- ^ stdout
-readProcess cmd args input = do
-    (Just inh, Just outh, _, pid) <-
-        createProcess (proc cmd args){ std_in  = CreatePipe,
-                                       std_out = CreatePipe,
-                                       std_err = Inherit }
-
-    -- fork off a thread to start consuming the output
-    output  <- hGetContents outh
-    outMVar <- newEmptyMVar
-    _ <- forkIO $ C.evaluate (length output) >> putMVar outMVar ()
-
-    -- now write and flush any input
-    when (not (null input)) $ do hPutStr inh input; hFlush inh
-    hClose inh -- done with stdin
-
-    -- wait on the output
-    takeMVar outMVar
-    hClose outh
-
-    -- wait on the process
-    ex <- waitForProcess pid
-
-    case ex of
-     ExitSuccess   -> return output
-     ExitFailure r -> 
-      ioError (mkIOError OtherError ("readProcess: " ++ cmd ++ 
-                                     ' ':unwords (map show args) ++ 
-                                     " (exit " ++ show r ++ ")")
-                                 Nothing Nothing)
-
-{- |
-readProcessWithExitCode creates an external process, reads its
-standard output and standard error strictly, waits until the process
-terminates, and then returns the 'ExitCode' of the process,
-the standard output, and the standard error.
-
-'readProcess' and 'readProcessWithExitCode' are fairly simple wrappers
-around 'createProcess'.  Constructing variants of these functions is
-quite easy: follow the link to the source code to see how
-'readProcess' is implemented.
--}
-
-readProcessWithExitCode
-    :: FilePath                 -- ^ command to run
-    -> [String]                 -- ^ any arguments
-    -> String                   -- ^ standard input
-    -> IO (ExitCode,String,String) -- ^ exitcode, stdout, stderr
-readProcessWithExitCode cmd args input = do
-    (Just inh, Just outh, Just errh, pid) <-
-        createProcess (proc cmd args){ std_in  = CreatePipe,
-                                       std_out = CreatePipe,
-                                       std_err = CreatePipe }
-
-    outMVar <- newEmptyMVar
-
-    -- fork off a thread to start consuming stdout
-    out  <- hGetContents outh
-    _ <- forkIO $ C.evaluate (length out) >> putMVar outMVar ()
-
-    -- fork off a thread to start consuming stderr
-    err  <- hGetContents errh
-    _ <- forkIO $ C.evaluate (length err) >> putMVar outMVar ()
-
-    -- now write and flush any input
-    when (not (null input)) $ do hPutStr inh input; hFlush inh
-    hClose inh -- done with stdin
-
-    -- wait on the output
-    takeMVar outMVar
-    takeMVar outMVar
-    hClose outh
-    hClose errh
-
-    -- wait on the process
-    ex <- waitForProcess pid
-
-    return (ex, out, err)
-#endif /* !__HUGS__ */
-
--- ---------------------------------------------------------------------------
--- system
-
-{-| 
-Computation @system cmd@ returns the exit code produced when the
-operating system runs the shell command @cmd@.
-
-This computation may fail with
-
-   * @PermissionDenied@: The process has insufficient privileges to
-     perform the operation.
-
-   * @ResourceExhausted@: Insufficient resources are available to
-     perform the operation.
-
-   * @UnsupportedOperation@: The implementation does not support
-     system calls.
-
-On Windows, 'system' passes the command to the Windows command
-interpreter (@CMD.EXE@ or @COMMAND.COM@), hence Unixy shell tricks
-will not work.
--}
-#ifdef __GLASGOW_HASKELL__
-system :: String -> IO ExitCode
-system "" = ioException (ioeSetErrorString (mkIOError InvalidArgument "system" Nothing Nothing) "null command")
-system str = syncProcess "system" (shell str)
-
-
-syncProcess :: String -> CreateProcess -> IO ExitCode
-#if mingw32_HOST_OS
-syncProcess _fun c = do
-  (_,_,_,p) <- createProcess c
-  waitForProcess p
-#else
-syncProcess fun c = do
-  -- The POSIX version of system needs to do some manipulation of signal
-  -- handlers.  Since we're going to be synchronously waiting for the child,
-  -- we want to ignore ^C in the parent, but handle it the default way
-  -- in the child (using SIG_DFL isn't really correct, it should be the
-  -- original signal handler, but the GHC RTS will have already set up
-  -- its own handler and we don't want to use that).
-  old_int  <- installHandler sigINT  Ignore Nothing
-  old_quit <- installHandler sigQUIT Ignore Nothing
-  (_,_,_,p) <- runGenProcess_ fun c
-		(Just defaultSignal) (Just defaultSignal)
-  r <- waitForProcess p
-  _ <- installHandler sigINT  old_int Nothing
-  _ <- installHandler sigQUIT old_quit Nothing
-  return r
-#endif  /* mingw32_HOST_OS */
-#endif  /* __GLASGOW_HASKELL__ */
-
-{-|
-The computation @'rawSystem' cmd args@ runs the operating system command
-@cmd@ in such a way that it receives as arguments the @args@ strings
-exactly as given, with no funny escaping or shell meta-syntax expansion.
-It will therefore behave more portably between operating systems than 'system'.
-
-The return codes and possible failures are the same as for 'system'.
--}
-rawSystem :: String -> [String] -> IO ExitCode
-#ifdef __GLASGOW_HASKELL__
-rawSystem cmd args = syncProcess "rawSystem" (proc cmd args)
-#elif !mingw32_HOST_OS
--- crude fallback implementation: could do much better than this under Unix
-rawSystem cmd args = system (showCommandForUser cmd args)
-#else /* mingw32_HOST_OS &&  ! __GLASGOW_HASKELL__ */
-# if __HUGS__
-rawSystem cmd args = system (cmd ++ showCommandForUser "" args)
-# else
-rawSystem cmd args = system (showCommandForUser cmd args)
-#endif
-#endif
-
--- | Given a program @p@ and arguments @args@,
---   @showCommandForUser p args@ returns a string suitable for pasting
---   into sh (on POSIX OSs) or cmd.exe (on Windows).
-showCommandForUser :: FilePath -> [String] -> String
-showCommandForUser cmd args = unwords (map translate (cmd : args))
-
-#ifndef __HUGS__
--- ----------------------------------------------------------------------------
--- terminateProcess
-
--- | Attempts to terminate the specified process.  This function should
--- not be used under normal circumstances - no guarantees are given regarding
--- how cleanly the process is terminated.  To check whether the process
--- has indeed terminated, use 'getProcessExitCode'.
---
--- On Unix systems, 'terminateProcess' sends the process the SIGTERM signal.
--- On Windows systems, the Win32 @TerminateProcess@ function is called, passing
--- an exit code of 1.
---
--- Note: on Windows, if the process was a shell command created by
--- 'createProcess' with 'shell', or created by 'runCommand' or
--- 'runInteractiveCommand', then 'terminateProcess' will only
--- terminate the shell, not the command itself.  On Unix systems, both
--- processes are in a process group and will be terminated together.
-
-terminateProcess :: ProcessHandle -> IO ()
-terminateProcess ph = do
-  withProcessHandle_ ph $ \p_ ->
-    case p_ of 
-      ClosedHandle _ -> return p_
-      OpenHandle h -> do
-        throwErrnoIfMinus1Retry_ "terminateProcess" $ c_terminateProcess h
-	return p_
-	-- does not close the handle, we might want to try terminating it
-	-- again, or get its exit code.
-
--- ----------------------------------------------------------------------------
--- interruptProcessGroupOf
-
--- | Sends an interrupt signal to the process group of the given process.
---
--- On Unix systems, it sends the group the SIGINT signal.
---
--- On Windows systems, it generates a CTRL_BREAK_EVENT and will only work for
--- processes created using 'createProcess' and setting the 'create_group' flag
-
-interruptProcessGroupOf
-    :: ProcessHandle    -- ^ Lead process in the process group
-    -> IO ()
-interruptProcessGroupOf ph = do
-#if mingw32_HOST_OS
-    withProcessHandle_ ph $ \p_ -> do
-        case p_ of
-            ClosedHandle _ -> return p_
-            OpenHandle h -> do
-				-- getProcessId h
-                -- generateConsoleCtrlEvent cTRL_BREAK_EVENT pid
-                return p_
-            _ -> return p_
-#else
-    withProcessHandle_ ph $ \p_ -> do
-        case p_ of
-            ClosedHandle _ -> return p_
-            OpenHandle h -> do
-                signalProcessGroup sigINT h
-                return p_
-#endif
-
--- ----------------------------------------------------------------------------
--- getProcessExitCode
-
-{- | 
-This is a non-blocking version of 'waitForProcess'.  If the process is
-still running, 'Nothing' is returned.  If the process has exited, then
-@'Just' e@ is returned where @e@ is the exit code of the process.
--}
-getProcessExitCode :: ProcessHandle -> IO (Maybe ExitCode)
-getProcessExitCode ph = do
-  withProcessHandle ph $ \p_ ->
-    case p_ of
-      ClosedHandle e -> return (p_, Just e)
-      OpenHandle h ->
-	alloca $ \pExitCode -> do
-            res <- throwErrnoIfMinus1Retry "getProcessExitCode" $
-	        	c_getProcessExitCode h pExitCode
-	    code <- peek pExitCode
-	    if res == 0
-	      then return (p_, Nothing)
-	      else do
-		   closePHANDLE h
-		   let e  | code == 0 = ExitSuccess
-			  | otherwise = ExitFailure (fromIntegral code)
-		   return (ClosedHandle e, Just e)
-
--- ----------------------------------------------------------------------------
--- Interface to C bits
-
-foreign import ccall unsafe "terminateProcess"
-  c_terminateProcess
-	:: PHANDLE
-	-> IO CInt
-
-foreign import ccall unsafe "getProcessExitCode"
-  c_getProcessExitCode
-	:: PHANDLE
-	-> Ptr CInt
-	-> IO CInt
-
-#if __GLASGOW_HASKELL__ < 700
--- not available prior to 700
-#define interruptible safe
-#endif
-
-foreign import ccall interruptible "waitForProcess" -- NB. safe - can block
-  c_waitForProcess
-	:: PHANDLE
-        -> Ptr CInt
-	-> IO CInt
-#endif /* !__HUGS__ */
+{-# LANGUAGE CPP, ForeignFunctionInterface #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Process
+-- Copyright   :  (c) The University of Glasgow 2004-2008
+-- License     :  BSD-style (see the file libraries/base/LICENSE)
+--
+-- Maintainer  :  libraries@haskell.org
+-- Stability   :  experimental
+-- Portability :  non-portable (requires concurrency)
+--
+-- Operations for creating and interacting with sub-processes.
+--
+-----------------------------------------------------------------------------
+
+-- ToDo:
+--	* Flag to control whether exiting the parent also kills the child.
+
+{- NOTES on createPipe:
+ 
+   createPipe is no longer exported, because of the following problems:
+
+	- it wasn't used to implement runInteractiveProcess on Unix, because
+	  the file descriptors for the unused ends of the pipe need to be closed
+	  in the child process.
+
+        - on Windows, a special version of createPipe is needed that sets
+	  the inheritance flags correctly on the ends of the pipe (see
+	  mkAnonPipe below).
+-}
+
+module System.Process (
+#ifndef __HUGS__
+	-- * Running sub-processes
+        createProcess,
+        shell, proc,
+        CreateProcess(..),
+        CmdSpec(..),
+        StdStream(..),
+	ProcessHandle,
+
+        -- ** Specific variants of createProcess
+	runCommand,
+	runProcess,
+	runInteractiveCommand,
+	runInteractiveProcess,
+        readProcess,
+        readProcessWithExitCode,
+#endif
+        system,
+        rawSystem,
+        showCommandForUser,
+
+#ifndef __HUGS__
+	-- * Process completion
+	waitForProcess,
+	getProcessExitCode,
+	terminateProcess,
+	interruptProcessGroupOf,
+#endif
+ ) where
+
+import Prelude hiding (mapM)
+
+#ifndef __HUGS__
+import System.Process.Internals
+
+import System.IO.Error
+import qualified Control.Exception as C
+import Control.Concurrent
+import Control.Monad
+import Foreign
+import Foreign.C
+import System.IO
+import Data.Maybe
+#endif
+import System.Exit	( ExitCode(..) )
+
+#ifdef __GLASGOW_HASKELL__
+#if __GLASGOW_HASKELL__ >= 611
+import GHC.IO.Exception	( ioException, IOErrorType(..) )
+#else
+import GHC.IOBase	( ioException, IOErrorType(..) )
+#endif
+#if defined(mingw32_HOST_OS)
+import System.Win32.Process (getProcessId)
+import System.Win32.Console (generateConsoleCtrlEvent, cTRL_BREAK_EVENT)
+#else
+import System.Posix.Signals
+#endif
+#endif
+
+#ifdef __HUGS__
+import Hugs.System
+#endif
+
+#ifdef __NHC__
+import System (system)
+#endif
+
+
+#ifndef __HUGS__
+-- ----------------------------------------------------------------------------
+-- runCommand
+
+{- | Runs a command using the shell.
+ -}
+runCommand
+  :: String
+  -> IO ProcessHandle
+
+runCommand string = do
+  (_,_,_,ph) <- runGenProcess_ "runCommand" (shell string) Nothing Nothing
+  return ph
+
+-- ----------------------------------------------------------------------------
+-- runProcess
+
+{- | Runs a raw command, optionally specifying 'Handle's from which to
+     take the @stdin@, @stdout@ and @stderr@ channels for the new
+     process (otherwise these handles are inherited from the current
+     process).
+
+     Any 'Handle's passed to 'runProcess' are placed immediately in the 
+     closed state.
+
+     Note: consider using the more general 'createProcess' instead of
+     'runProcess'.
+-}
+runProcess
+  :: FilePath			-- ^ Filename of the executable
+  -> [String]			-- ^ Arguments to pass to the executable
+  -> Maybe FilePath		-- ^ Optional path to the working directory
+  -> Maybe [(String,String)]	-- ^ Optional environment (otherwise inherit)
+  -> Maybe Handle		-- ^ Handle to use for @stdin@ (Nothing => use existing @stdin@)
+  -> Maybe Handle		-- ^ Handle to use for @stdout@ (Nothing => use existing @stdout@)
+  -> Maybe Handle		-- ^ Handle to use for @stderr@ (Nothing => use existing @stderr@)
+  -> IO ProcessHandle
+
+runProcess cmd args mb_cwd mb_env mb_stdin mb_stdout mb_stderr = do
+  (_,_,_,ph) <-
+      runGenProcess_ "runProcess"
+         (proc cmd args){ cwd = mb_cwd,
+                          env = mb_env,
+                          std_in  = mbToStd mb_stdin,
+                          std_out = mbToStd mb_stdout,
+                          std_err = mbToStd mb_stderr }
+	  Nothing Nothing
+  maybeClose mb_stdin
+  maybeClose mb_stdout
+  maybeClose mb_stderr
+  return ph
+ where
+  maybeClose :: Maybe Handle -> IO ()
+  maybeClose (Just  hdl)
+    | hdl /= stdin && hdl /= stdout && hdl /= stderr = hClose hdl
+  maybeClose _ = return ()
+
+  mbToStd :: Maybe Handle -> StdStream
+  mbToStd Nothing    = Inherit
+  mbToStd (Just hdl) = UseHandle hdl
+
+-- ----------------------------------------------------------------------------
+-- createProcess
+
+-- | Construct a 'CreateProcess' record for passing to 'createProcess',
+-- representing a raw command with arguments.
+proc :: FilePath -> [String] -> CreateProcess
+proc cmd args = CreateProcess { cmdspec = RawCommand cmd args,
+                                cwd = Nothing,
+                                env = Nothing,
+                                std_in = Inherit,
+                                std_out = Inherit,
+                                std_err = Inherit,
+                                close_fds = False,
+                                create_group = False}
+
+-- | Construct a 'CreateProcess' record for passing to 'createProcess',
+-- representing a command to be passed to the shell.
+shell :: String -> CreateProcess
+shell str = CreateProcess { cmdspec = ShellCommand str,
+                            cwd = Nothing,
+                            env = Nothing,
+                            std_in = Inherit,
+                            std_out = Inherit,
+                            std_err = Inherit,
+                            close_fds = False,
+                            create_group = False}
+
+{- |
+This is the most general way to spawn an external process.  The
+process can be a command line to be executed by a shell or a raw command
+with a list of arguments.  The stdin, stdout, and stderr streams of
+the new process may individually be attached to new pipes, to existing
+'Handle's, or just inherited from the parent (the default.)
+
+The details of how to create the process are passed in the
+'CreateProcess' record.  To make it easier to construct a
+'CreateProcess', the functions 'proc' and 'shell' are supplied that
+fill in the fields with default values which can be overriden as
+needed.
+
+'createProcess' returns @(mb_stdin_hdl, mb_stdout_hdl, mb_stderr_hdl, p)@,
+where 
+
+ * if @std_in == CreatePipe@, then @mb_stdin_hdl@ will be @Just h@,
+   where @h@ is the write end of the pipe connected to the child
+   process's @stdin@.
+
+ * otherwise, @mb_stdin_hdl == Nothing@
+
+Similarly for @mb_stdout_hdl@ and @mb_stderr_hdl@.
+
+For example, to execute a simple @ls@ command:
+
+>   r <- createProcess (proc "ls" [])
+
+To create a pipe from which to read the output of @ls@:
+
+>   (_, Just hout, _, _) <-
+>       createProcess (proc "ls" []){ std_out = CreatePipe }
+
+To also set the directory in which to run @ls@:
+
+>   (_, Just hout, _, _) <-
+>       createProcess (proc "ls" []){ cwd = Just "\home\bob",
+>                                     std_out = CreatePipe }
+
+-}
+createProcess
+  :: CreateProcess
+  -> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
+createProcess cp = do
+  r <- runGenProcess_ "createProcess" cp Nothing Nothing
+  maybeCloseStd (std_in  cp)
+  maybeCloseStd (std_out cp)
+  maybeCloseStd (std_err cp)
+  return r
+ where
+  maybeCloseStd :: StdStream -> IO ()
+  maybeCloseStd (UseHandle hdl)
+    | hdl /= stdin && hdl /= stdout && hdl /= stderr = hClose hdl
+  maybeCloseStd _ = return ()
+
+-- ----------------------------------------------------------------------------
+-- runInteractiveCommand
+
+{- | Runs a command using the shell, and returns 'Handle's that may
+     be used to communicate with the process via its @stdin@, @stdout@,
+     and @stderr@ respectively. The 'Handle's are initially in binary
+     mode; if you need them to be in text mode then use 'hSetBinaryMode'.
+-}
+runInteractiveCommand
+  :: String
+  -> IO (Handle,Handle,Handle,ProcessHandle)
+
+runInteractiveCommand string =
+  runInteractiveProcess1 "runInteractiveCommand" (shell string)
+
+-- ----------------------------------------------------------------------------
+-- runInteractiveProcess
+
+{- | Runs a raw command, and returns 'Handle's that may be used to communicate
+     with the process via its @stdin@, @stdout@ and @stderr@ respectively.
+
+    For example, to start a process and feed a string to its stdin:
+   
+>   (inp,out,err,pid) <- runInteractiveProcess "..."
+>   forkIO (hPutStr inp str)
+
+    The 'Handle's are initially in binary mode; if you need them to be
+    in text mode then use 'hSetBinaryMode'.
+-}
+runInteractiveProcess
+  :: FilePath			-- ^ Filename of the executable
+  -> [String]			-- ^ Arguments to pass to the executable
+  -> Maybe FilePath		-- ^ Optional path to the working directory
+  -> Maybe [(String,String)]	-- ^ Optional environment (otherwise inherit)
+  -> IO (Handle,Handle,Handle,ProcessHandle)
+
+runInteractiveProcess cmd args mb_cwd mb_env = do
+  runInteractiveProcess1 "runInteractiveProcess" 
+        (proc cmd args){ cwd = mb_cwd, env = mb_env }
+
+runInteractiveProcess1
+  :: String
+  -> CreateProcess
+  -> IO (Handle,Handle,Handle,ProcessHandle)
+runInteractiveProcess1 fun cmd = do
+  (mb_in, mb_out, mb_err, p) <- 
+      runGenProcess_ fun
+           cmd{ std_in  = CreatePipe,
+                std_out = CreatePipe,
+                std_err = CreatePipe } 
+           Nothing Nothing
+  return (fromJust mb_in, fromJust mb_out, fromJust mb_err, p)
+
+-- ----------------------------------------------------------------------------
+-- waitForProcess
+
+{- | Waits for the specified process to terminate, and returns its exit code.
+   
+     GHC Note: in order to call @waitForProcess@ without blocking all the
+     other threads in the system, you must compile the program with
+     @-threaded@.
+-}
+waitForProcess
+  :: ProcessHandle
+  -> IO ExitCode
+waitForProcess ph = do
+  p_ <- withProcessHandle ph $ \p_ -> return (p_,p_)
+  case p_ of
+    ClosedHandle e -> return e
+    OpenHandle h  -> do
+	-- don't hold the MVar while we call c_waitForProcess...
+	-- (XXX but there's a small race window here during which another
+	-- thread could close the handle or call waitForProcess)
+        alloca $ \pret -> do
+          throwErrnoIfMinus1Retry_ "waitForProcess" (c_waitForProcess h pret)
+          withProcessHandle ph $ \p_' ->
+            case p_' of
+              ClosedHandle e -> return (p_',e)
+              OpenHandle ph' -> do
+                closePHANDLE ph'
+                code <- peek pret
+                let e = if (code == 0)
+                       then ExitSuccess
+                       else (ExitFailure (fromIntegral code))
+                return (ClosedHandle e, e)
+
+-- -----------------------------------------------------------------------------
+--
+-- | readProcess forks an external process, reads its standard output
+-- strictly, blocking until the process terminates, and returns the output
+-- string.
+--
+-- Output is returned strictly, so this is not suitable for
+-- interactive applications.
+--
+-- Users of this function should compile with @-threaded@ if they
+-- want other Haskell threads to keep running while waiting on
+-- the result of readProcess.
+--
+-- >  > readProcess "date" [] []
+-- >  "Thu Feb  7 10:03:39 PST 2008\n"
+--
+-- The arguments are:
+--
+-- * The command to run, which must be in the $PATH, or an absolute path
+--
+-- * A list of separate command line arguments to the program
+--
+-- * A string to pass on the standard input to the program.
+--
+readProcess 
+    :: FilePath                 -- ^ command to run
+    -> [String]                 -- ^ any arguments
+    -> String                   -- ^ standard input
+    -> IO String                -- ^ stdout
+readProcess cmd args input = do
+    (Just inh, Just outh, _, pid) <-
+        createProcess (proc cmd args){ std_in  = CreatePipe,
+                                       std_out = CreatePipe,
+                                       std_err = Inherit }
+
+    -- fork off a thread to start consuming the output
+    output  <- hGetContents outh
+    outMVar <- newEmptyMVar
+    _ <- forkIO $ C.evaluate (length output) >> putMVar outMVar ()
+
+    -- now write and flush any input
+    when (not (null input)) $ do hPutStr inh input; hFlush inh
+    hClose inh -- done with stdin
+
+    -- wait on the output
+    takeMVar outMVar
+    hClose outh
+
+    -- wait on the process
+    ex <- waitForProcess pid
+
+    case ex of
+     ExitSuccess   -> return output
+     ExitFailure r -> 
+      ioError (mkIOError OtherError ("readProcess: " ++ cmd ++ 
+                                     ' ':unwords (map show args) ++ 
+                                     " (exit " ++ show r ++ ")")
+                                 Nothing Nothing)
+
+{- |
+readProcessWithExitCode creates an external process, reads its
+standard output and standard error strictly, waits until the process
+terminates, and then returns the 'ExitCode' of the process,
+the standard output, and the standard error.
+
+'readProcess' and 'readProcessWithExitCode' are fairly simple wrappers
+around 'createProcess'.  Constructing variants of these functions is
+quite easy: follow the link to the source code to see how
+'readProcess' is implemented.
+-}
+
+readProcessWithExitCode
+    :: FilePath                 -- ^ command to run
+    -> [String]                 -- ^ any arguments
+    -> String                   -- ^ standard input
+    -> IO (ExitCode,String,String) -- ^ exitcode, stdout, stderr
+readProcessWithExitCode cmd args input = do
+    (Just inh, Just outh, Just errh, pid) <-
+        createProcess (proc cmd args){ std_in  = CreatePipe,
+                                       std_out = CreatePipe,
+                                       std_err = CreatePipe }
+
+    outMVar <- newEmptyMVar
+
+    -- fork off a thread to start consuming stdout
+    out  <- hGetContents outh
+    _ <- forkIO $ C.evaluate (length out) >> putMVar outMVar ()
+
+    -- fork off a thread to start consuming stderr
+    err  <- hGetContents errh
+    _ <- forkIO $ C.evaluate (length err) >> putMVar outMVar ()
+
+    -- now write and flush any input
+    when (not (null input)) $ do hPutStr inh input; hFlush inh
+    hClose inh -- done with stdin
+
+    -- wait on the output
+    takeMVar outMVar
+    takeMVar outMVar
+    hClose outh
+    hClose errh
+
+    -- wait on the process
+    ex <- waitForProcess pid
+
+    return (ex, out, err)
+#endif /* !__HUGS__ */
+
+-- ---------------------------------------------------------------------------
+-- system
+
+{-| 
+Computation @system cmd@ returns the exit code produced when the
+operating system runs the shell command @cmd@.
+
+This computation may fail with
+
+   * @PermissionDenied@: The process has insufficient privileges to
+     perform the operation.
+
+   * @ResourceExhausted@: Insufficient resources are available to
+     perform the operation.
+
+   * @UnsupportedOperation@: The implementation does not support
+     system calls.
+
+On Windows, 'system' passes the command to the Windows command
+interpreter (@CMD.EXE@ or @COMMAND.COM@), hence Unixy shell tricks
+will not work.
+-}
+#ifdef __GLASGOW_HASKELL__
+system :: String -> IO ExitCode
+system "" = ioException (ioeSetErrorString (mkIOError InvalidArgument "system" Nothing Nothing) "null command")
+system str = syncProcess "system" (shell str)
+
+
+syncProcess :: String -> CreateProcess -> IO ExitCode
+#if mingw32_HOST_OS
+syncProcess _fun c = do
+  (_,_,_,p) <- createProcess c
+  waitForProcess p
+#else
+syncProcess fun c = do
+  -- The POSIX version of system needs to do some manipulation of signal
+  -- handlers.  Since we're going to be synchronously waiting for the child,
+  -- we want to ignore ^C in the parent, but handle it the default way
+  -- in the child (using SIG_DFL isn't really correct, it should be the
+  -- original signal handler, but the GHC RTS will have already set up
+  -- its own handler and we don't want to use that).
+  old_int  <- installHandler sigINT  Ignore Nothing
+  old_quit <- installHandler sigQUIT Ignore Nothing
+  (_,_,_,p) <- runGenProcess_ fun c
+		(Just defaultSignal) (Just defaultSignal)
+  r <- waitForProcess p
+  _ <- installHandler sigINT  old_int Nothing
+  _ <- installHandler sigQUIT old_quit Nothing
+  return r
+#endif  /* mingw32_HOST_OS */
+#endif  /* __GLASGOW_HASKELL__ */
+
+{-|
+The computation @'rawSystem' cmd args@ runs the operating system command
+@cmd@ in such a way that it receives as arguments the @args@ strings
+exactly as given, with no funny escaping or shell meta-syntax expansion.
+It will therefore behave more portably between operating systems than 'system'.
+
+The return codes and possible failures are the same as for 'system'.
+-}
+rawSystem :: String -> [String] -> IO ExitCode
+#ifdef __GLASGOW_HASKELL__
+rawSystem cmd args = syncProcess "rawSystem" (proc cmd args)
+#elif !mingw32_HOST_OS
+-- crude fallback implementation: could do much better than this under Unix
+rawSystem cmd args = system (showCommandForUser cmd args)
+#else /* mingw32_HOST_OS &&  ! __GLASGOW_HASKELL__ */
+# if __HUGS__
+rawSystem cmd args = system (cmd ++ showCommandForUser "" args)
+# else
+rawSystem cmd args = system (showCommandForUser cmd args)
+#endif
+#endif
+
+-- | Given a program @p@ and arguments @args@,
+--   @showCommandForUser p args@ returns a string suitable for pasting
+--   into sh (on POSIX OSs) or cmd.exe (on Windows).
+showCommandForUser :: FilePath -> [String] -> String
+showCommandForUser cmd args = unwords (map translate (cmd : args))
+
+#ifndef __HUGS__
+-- ----------------------------------------------------------------------------
+-- terminateProcess
+
+-- | Attempts to terminate the specified process.  This function should
+-- not be used under normal circumstances - no guarantees are given regarding
+-- how cleanly the process is terminated.  To check whether the process
+-- has indeed terminated, use 'getProcessExitCode'.
+--
+-- On Unix systems, 'terminateProcess' sends the process the SIGTERM signal.
+-- On Windows systems, the Win32 @TerminateProcess@ function is called, passing
+-- an exit code of 1.
+--
+-- Note: on Windows, if the process was a shell command created by
+-- 'createProcess' with 'shell', or created by 'runCommand' or
+-- 'runInteractiveCommand', then 'terminateProcess' will only
+-- terminate the shell, not the command itself.  On Unix systems, both
+-- processes are in a process group and will be terminated together.
+
+terminateProcess :: ProcessHandle -> IO ()
+terminateProcess ph = do
+  withProcessHandle_ ph $ \p_ ->
+    case p_ of 
+      ClosedHandle _ -> return p_
+      OpenHandle h -> do
+        throwErrnoIfMinus1Retry_ "terminateProcess" $ c_terminateProcess h
+	return p_
+	-- does not close the handle, we might want to try terminating it
+	-- again, or get its exit code.
+
+-- ----------------------------------------------------------------------------
+-- interruptProcessGroupOf
+
+-- | Sends an interrupt signal to the process group of the given process.
+--
+-- On Unix systems, it sends the group the SIGINT signal.
+--
+-- On Windows systems, it generates a CTRL_BREAK_EVENT and will only work for
+-- processes created using 'createProcess' and setting the 'create_group' flag
+
+interruptProcessGroupOf
+    :: ProcessHandle    -- ^ Lead process in the process group
+    -> IO ()
+interruptProcessGroupOf ph = do
+#if mingw32_HOST_OS
+    withProcessHandle_ ph $ \p_ -> do
+        case p_ of
+            ClosedHandle _ -> return p_
+            OpenHandle h -> do
+                pid <- getProcessId h
+                generateConsoleCtrlEvent cTRL_BREAK_EVENT pid
+                return p_
+#else
+    withProcessHandle_ ph $ \p_ -> do
+        case p_ of
+            ClosedHandle _ -> return p_
+            OpenHandle h -> do
+                signalProcessGroup sigINT h
+                return p_
+#endif
+
+-- ----------------------------------------------------------------------------
+-- getProcessExitCode
+
+{- | 
+This is a non-blocking version of 'waitForProcess'.  If the process is
+still running, 'Nothing' is returned.  If the process has exited, then
+@'Just' e@ is returned where @e@ is the exit code of the process.
+-}
+getProcessExitCode :: ProcessHandle -> IO (Maybe ExitCode)
+getProcessExitCode ph = do
+  withProcessHandle ph $ \p_ ->
+    case p_ of
+      ClosedHandle e -> return (p_, Just e)
+      OpenHandle h ->
+	alloca $ \pExitCode -> do
+            res <- throwErrnoIfMinus1Retry "getProcessExitCode" $
+	        	c_getProcessExitCode h pExitCode
+	    code <- peek pExitCode
+	    if res == 0
+	      then return (p_, Nothing)
+	      else do
+		   closePHANDLE h
+		   let e  | code == 0 = ExitSuccess
+			  | otherwise = ExitFailure (fromIntegral code)
+		   return (ClosedHandle e, Just e)
+
+-- ----------------------------------------------------------------------------
+-- Interface to C bits
+
+foreign import ccall unsafe "terminateProcess"
+  c_terminateProcess
+	:: PHANDLE
+	-> IO CInt
+
+foreign import ccall unsafe "getProcessExitCode"
+  c_getProcessExitCode
+	:: PHANDLE
+	-> Ptr CInt
+	-> IO CInt
+
+#if __GLASGOW_HASKELL__ < 700
+-- not available prior to 700
+#define interruptible safe
+#endif
+
+foreign import ccall interruptible "waitForProcess" -- NB. safe - can block
+  c_waitForProcess
+	:: PHANDLE
+        -> Ptr CInt
+	-> IO CInt
+#endif /* !__HUGS__ */
diff --git a/System/Process/Internals.hs b/System/Process/Internals.hs
index 5056055e..2c984ad7 100644
--- a/System/Process/Internals.hs
+++ b/System/Process/Internals.hs
@@ -75,6 +75,7 @@ import System.IO.Error
 import Data.Typeable
 #if defined(mingw32_HOST_OS)
 import GHC.IO.IOMode
+import System.Win32.DebugApi (PHANDLE)
 #endif
 #else
 import GHC.IOBase	( haFD, FD, IOException(..) )
@@ -136,6 +137,9 @@ withProcessHandle_ (ProcessHandle m) io = modifyMVar_ m io
 
 type PHANDLE = CPid
 
+throwErrnoIfBadPHandle :: String -> IO PHANDLE -> IO PHANDLE  
+throwErrnoIfBadPHandle = throwErrnoIfMinus1
+
 mkProcessHandle :: PHANDLE -> IO ProcessHandle
 mkProcessHandle p = do
   m <- newMVar (OpenHandle p)
@@ -146,7 +150,8 @@ closePHANDLE _ = return ()
 
 #else
 
-type PHANDLE = Word32
+throwErrnoIfBadPHandle :: String -> IO PHANDLE -> IO PHANDLE  
+throwErrnoIfBadPHandle = throwErrnoIfNull
 
 -- On Windows, we have to close this HANDLE when it is no longer required,
 -- hence we add a finalizer to it, using an IORef as the box on which to
@@ -334,7 +339,7 @@ runGenProcess_ fun CreateProcess{ cmdspec = cmdsp,
      -- the C code.  Also the MVar will be cheaper when not running
      -- the threaded RTS.
      proc_handle <- withMVar runInteractiveProcess_lock $ \_ ->
-                    throwErrnoIfMinus1 fun $
+                    throwErrnoIfBadPHandle fun $
 	                 c_runInteractiveProcess pcmdline pWorkDir pEnv 
                                 fdin fdout fderr
 				pfdStdInput pfdStdOutput pfdStdError
@@ -364,7 +369,6 @@ foreign import ccall unsafe "runInteractiveProcess"
         -> Ptr FD
         -> Ptr FD
         -> CInt                         -- flags
-        -> Ptr Word32                   -- pPid
         -> IO PHANDLE
 
 #endif /* __GLASGOW_HASKELL__ */
diff --git a/cbits/runProcess.c b/cbits/runProcess.c
index 6a2520fc..2c1028ff 100644
--- a/cbits/runProcess.c
+++ b/cbits/runProcess.c
@@ -1,536 +1,536 @@
-/* ----------------------------------------------------------------------------
-   (c) The University of Glasgow 2004
-   
-   Support for System.Process
-   ------------------------------------------------------------------------- */
-
-#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)
-#define UNICODE
-#endif
-
-/* XXX This is a nasty hack; should put everything necessary in this package */
-#include "HsBase.h"
-#include "Rts.h"
-
-#include "runProcess.h"
-
-#if !(defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32))
-
-#include "execvpe.h"
-
-/* ----------------------------------------------------------------------------
-   UNIX versions
-   ------------------------------------------------------------------------- */
-
-static long max_fd = 0;
-
-// Rts internal API, not exposed in a public header file:
-extern void blockUserSignals(void);
-extern void unblockUserSignals(void);
-
-ProcHandle
-runInteractiveProcess (char *const args[], 
-		       char *workingDirectory, char **environment,
-                       int fdStdIn, int fdStdOut, int fdStdErr,
-		       int *pfdStdInput, int *pfdStdOutput, int *pfdStdError,
-                       int set_inthandler, long inthandler, 
-                       int set_quithandler, long quithandler,
-                       int flags)
-{
-    int close_fds = ((flags & RUN_PROCESS_IN_CLOSE_FDS) != 0);
-    int pid;
-    int fdStdInput[2], fdStdOutput[2], fdStdError[2];
-    int r;
-    struct sigaction dfl;
-
-    // Ordering matters here, see below [Note #431].
-    if (fdStdIn == -1) {
-        r = pipe(fdStdInput);
-        if (r == -1) { 
-            sysErrorBelch("runInteractiveProcess: pipe");
-            return -1;
-        }
-        
-    }
-    if (fdStdOut == -1) {
-        r = pipe(fdStdOutput);
-        if (r == -1) { 
-            sysErrorBelch("runInteractiveProcess: pipe");
-            return -1;
-        }
-    }
-    if (fdStdErr == -1) {
-        r = pipe(fdStdError);
-        if (r == -1) { 
-            sysErrorBelch("runInteractiveProcess: pipe");
-            return -1;
-        }
-    }
-
-    // Block signals with Haskell handlers.  The danger here is that
-    // with the threaded RTS, a signal arrives in the child process,
-    // the RTS writes the signal information into the pipe (which is
-    // shared between parent and child), and the parent behaves as if
-    // the signal had been raised.
-    blockUserSignals();
-
-    // See #4074.  Sometimes fork() gets interrupted by the timer
-    // signal and keeps restarting indefinitely.
-    stopTimer();
-
-    switch(pid = fork())
-    {
-    case -1:
-        unblockUserSignals();
-#if __GLASGOW_HASKELL__ > 612
-        startTimer();
-#endif
-        if (fdStdIn == -1) {
-            close(fdStdInput[0]);
-            close(fdStdInput[1]);
-        }
-        if (fdStdOut == -1) {
-            close(fdStdOutput[0]);
-            close(fdStdOutput[1]);
-        }
-        if (fdStdErr == -1) {
-            close(fdStdError[0]);
-            close(fdStdError[1]);
-        }
-	return -1;
-	
-    case 0:
-    {
-        // WARNING!  we are now in the child of vfork(), so any memory
-        // we modify below will also be seen in the parent process.
-
-        if ((flags & RUN_PROCESS_IN_NEW_GROUP) != 0) {
-            setpgid(0, 0);
-        }
-        unblockUserSignals();
-
-	if (workingDirectory) {
-	    if (chdir (workingDirectory) < 0) {
-                // See #1593.  The convention for the exit code when
-                // exec() fails seems to be 127 (gleened from C's
-                // system()), but there's no equivalent convention for
-                // chdir(), so I'm picking 126 --SimonM.
-                _exit(126);
-	    }
-	}
-	
-        // [Note #431]: Ordering matters here.  If any of the FDs
-        // 0,1,2 were initially closed, then our pipes may have used
-        // these FDs.  So when we dup2 the pipe FDs down to 0,1,2, we
-        // must do it in that order, otherwise we could overwrite an
-        // FD that we need later.
-
-        if (fdStdIn == -1) {
-            if (fdStdInput[0] != STDIN_FILENO) {
-                dup2 (fdStdInput[0], STDIN_FILENO);
-                close(fdStdInput[0]);
-            }
-            close(fdStdInput[1]);
-        } else {
-            dup2(fdStdIn,  STDIN_FILENO);
-        }
-
-        if (fdStdOut == -1) {
-            if (fdStdOutput[1] != STDOUT_FILENO) {
-                dup2 (fdStdOutput[1], STDOUT_FILENO);
-                close(fdStdOutput[1]);
-            }
-            close(fdStdOutput[0]);
-        } else {
-            dup2(fdStdOut,  STDOUT_FILENO);
-        }
-
-        if (fdStdErr == -1) {
-            if (fdStdError[1] != STDERR_FILENO) {
-                dup2 (fdStdError[1], STDERR_FILENO);
-                close(fdStdError[1]);
-            }
-            close(fdStdError[0]);
-        } else {
-            dup2(fdStdErr,  STDERR_FILENO);
-        }
-            
-        if (close_fds) {
-            int i;
-            if (max_fd == 0) {
-#if HAVE_SYSCONF
-                max_fd = sysconf(_SC_OPEN_MAX);
-                if (max_fd == -1) {
-                    max_fd = 256;
-                }
-#else
-                max_fd = 256;
-#endif
-            }
-            for (i = 3; i < max_fd; i++) {
-                close(i);
-            }
-        }
-
-	/* Set the SIGINT/SIGQUIT signal handlers in the child, if requested 
-	 */
-        (void)sigemptyset(&dfl.sa_mask);
-        dfl.sa_flags = 0;
-	if (set_inthandler) {
-	    dfl.sa_handler = (void *)inthandler;
-	    (void)sigaction(SIGINT, &dfl, NULL);
-	}
-	if (set_quithandler) {
-	    dfl.sa_handler = (void *)quithandler;
-	    (void)sigaction(SIGQUIT,  &dfl, NULL);
-	}
-
-	/* the child */
-	if (environment) {
-	    execvpe(args[0], args, environment);
-	} else {
-	    execvp(args[0], args);
-	}
-    }
-    _exit(127);
-    
-    default:
-	if ((flags & RUN_PROCESS_IN_NEW_GROUP) != 0) {
-            setpgid(pid, pid);
-	}
-	if (fdStdIn  == -1) {
-            close(fdStdInput[0]);
-            fcntl(fdStdInput[1], F_SETFD, FD_CLOEXEC);
-            *pfdStdInput  = fdStdInput[1];
-        }
-	if (fdStdOut == -1) {
-            close(fdStdOutput[1]);
-            fcntl(fdStdOutput[0], F_SETFD, FD_CLOEXEC);
-            *pfdStdOutput = fdStdOutput[0];
-        }
-        if (fdStdErr == -1) {
-            close(fdStdError[1]);
-            fcntl(fdStdError[0], F_SETFD, FD_CLOEXEC);
-            *pfdStdError  = fdStdError[0];
-        }
-	break;
-    }
-    unblockUserSignals();
-    startTimer();
-    
-    return pid;
-}
-
-int
-terminateProcess (ProcHandle handle)
-{
-    return (kill(handle, SIGTERM) == 0);
-}
-
-int
-getProcessExitCode (ProcHandle handle, int *pExitCode)
-{
-    int wstat, res;
-    
-    *pExitCode = 0;
-    
-    if ((res = waitpid(handle, &wstat, WNOHANG)) > 0)
-    {
-	if (WIFEXITED(wstat))
-	{
-	    *pExitCode = WEXITSTATUS(wstat);
-	    return 1;
-	}
-	else
-	    if (WIFSIGNALED(wstat))
-	    {
-		errno = EINTR;
-		return -1;
-	    }
-	    else
-	    {
-		/* This should never happen */
-	    }
-    }
-    
-    if (res == 0) return 0;
-
-    if (errno == ECHILD) 
-    {
-	    *pExitCode = 0;
-	    return 1;
-    }
-
-    return -1;
-}
-
-int waitForProcess (ProcHandle handle, int *pret)
-{
-    int wstat;
-    
-    if (waitpid(handle, &wstat, 0) < 0)
-    {
-        return -1;
-    }
-    
-    if (WIFEXITED(wstat)) {
-        *pret = WEXITSTATUS(wstat);
-	return 0;
-    }
-    else
-	if (WIFSIGNALED(wstat))
-	{
-            *pret = wstat;
-	    return 0;
-	}
-	else
-	{
-	    /* This should never happen */
-	}
-    
-    return -1;
-}
-
-#else
-/* ----------------------------------------------------------------------------
-   Win32 versions
-   ------------------------------------------------------------------------- */
-
-/* -------------------- WINDOWS VERSION --------------------- */
-
-/*
- * Function: mkAnonPipe
- *
- * Purpose:  create an anonymous pipe with read and write ends being
- *           optionally (non-)inheritable.
- */
-static BOOL
-mkAnonPipe (HANDLE* pHandleIn, BOOL isInheritableIn, 
-	    HANDLE* pHandleOut, BOOL isInheritableOut)
-{
-	HANDLE hTemporaryIn  = NULL;
-	HANDLE hTemporaryOut = NULL;
-
-	/* Create the anon pipe with both ends inheritable */
-	if (!CreatePipe(&hTemporaryIn, &hTemporaryOut, NULL, 0))
-	{
-		maperrno();
-		*pHandleIn  = NULL;
-		*pHandleOut = NULL;
-		return FALSE;
-	}
-
-	if (isInheritableIn) {
-            // SetHandleInformation requires at least Win2k
-            if (!SetHandleInformation(hTemporaryIn,
-                                      HANDLE_FLAG_INHERIT, 
-                                      HANDLE_FLAG_INHERIT))
-            {
-                maperrno();
-                *pHandleIn  = NULL;
-                *pHandleOut = NULL;
-                CloseHandle(hTemporaryIn);
-                CloseHandle(hTemporaryOut);
-                return FALSE;
-            }
-	}
-        *pHandleIn = hTemporaryIn;
-
-	if (isInheritableOut) {
-            if (!SetHandleInformation(hTemporaryOut,
-                                      HANDLE_FLAG_INHERIT, 
-                                      HANDLE_FLAG_INHERIT))
-            {
-                maperrno();
-                *pHandleIn  = NULL;
-                *pHandleOut = NULL;
-                CloseHandle(hTemporaryIn);
-                CloseHandle(hTemporaryOut);
-                return FALSE;
-            }
-        }
-        *pHandleOut = hTemporaryOut;
-        
-	return TRUE;
-}
-
-ProcHandle
-runInteractiveProcess (wchar_t *cmd, wchar_t *workingDirectory, 
-                       void *environment,
-                       int fdStdIn, int fdStdOut, int fdStdErr,
-		       int *pfdStdInput, int *pfdStdOutput, int *pfdStdError,
-                       int flags)
-{
-	STARTUPINFO sInfo;
-	PROCESS_INFORMATION pInfo;
-	HANDLE hStdInputRead   = INVALID_HANDLE_VALUE;
-        HANDLE hStdInputWrite  = INVALID_HANDLE_VALUE;
-	HANDLE hStdOutputRead  = INVALID_HANDLE_VALUE;
-        HANDLE hStdOutputWrite = INVALID_HANDLE_VALUE;
-	HANDLE hStdErrorRead   = INVALID_HANDLE_VALUE;
-        HANDLE hStdErrorWrite  = INVALID_HANDLE_VALUE;
-    BOOL close_fds = ((flags & RUN_PROCESS_IN_CLOSE_FDS) != 0);
-	DWORD dwFlags = 0;
-	BOOL status;
-        BOOL inherit;
-
-	ZeroMemory(&sInfo, sizeof(sInfo));
-	sInfo.cb = sizeof(sInfo);
-	sInfo.dwFlags = STARTF_USESTDHANDLES;
-
-	if (fdStdIn == -1) {
-            if (!mkAnonPipe(&hStdInputRead,  TRUE, &hStdInputWrite,  FALSE))
-                goto cleanup_err;
-            sInfo.hStdInput = hStdInputRead;
-        } else if (fdStdIn == 0) {
-            // Don't duplicate stdin, as console handles cannot be
-            // duplicated and inherited. urg.
-            sInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
-        } else {
-            // The handle might not be inheritable, so duplicate it
-            status = DuplicateHandle(GetCurrentProcess(), 
-                                     (HANDLE) _get_osfhandle(fdStdIn),
-                                     GetCurrentProcess(), &hStdInputRead,
-                                     0,
-                                     TRUE, /* inheritable */
-                                     DUPLICATE_SAME_ACCESS);
-            if (!status) goto cleanup_err;
-            sInfo.hStdInput = hStdInputRead;
-        }
-
-	if (fdStdOut == -1) {
-            if (!mkAnonPipe(&hStdOutputRead,  FALSE, &hStdOutputWrite,  TRUE))
-                goto cleanup_err;
-            sInfo.hStdOutput = hStdOutputWrite;
-        } else if (fdStdOut == 1) {
-            // Don't duplicate stdout, as console handles cannot be
-            // duplicated and inherited. urg.
-            sInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
-        } else {
-            // The handle might not be inheritable, so duplicate it
-            status = DuplicateHandle(GetCurrentProcess(), 
-                                     (HANDLE) _get_osfhandle(fdStdOut),
-                                     GetCurrentProcess(), &hStdOutputWrite,
-                                     0,
-                                     TRUE, /* inheritable */
-                                     DUPLICATE_SAME_ACCESS);
-            if (!status) goto cleanup_err;
-            sInfo.hStdOutput = hStdOutputWrite;
-        }
-
-	if (fdStdErr == -1) {
-            if (!mkAnonPipe(&hStdErrorRead,  TRUE, &hStdErrorWrite,  TRUE))
-                goto cleanup_err;
-            sInfo.hStdError = hStdErrorWrite;
-        } else if (fdStdErr == 2) {
-            // Don't duplicate stderr, as console handles cannot be
-            // duplicated and inherited. urg.
-            sInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
-        } else {
-            /* The handle might not be inheritable, so duplicate it */
-            status = DuplicateHandle(GetCurrentProcess(), 
-                                     (HANDLE) _get_osfhandle(fdStdErr),
-                                     GetCurrentProcess(), &hStdErrorWrite,
-                                     0,
-                                     TRUE, /* inheritable */
-                                     DUPLICATE_SAME_ACCESS);
-            if (!status) goto cleanup_err;
-            sInfo.hStdError = hStdErrorWrite;
-        }
-
-	if (sInfo.hStdInput  != GetStdHandle(STD_INPUT_HANDLE)  &&
-	    sInfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE) &&
-	    sInfo.hStdError  != GetStdHandle(STD_ERROR_HANDLE)  &&
-	    (flags & RUN_PROCESS_IN_NEW_GROUP) == 0)
-		dwFlags |= CREATE_NO_WINDOW;   // Run without console window only when both output and error are redirected
-
-        // See #3231
-        if (close_fds && fdStdIn == 0 && fdStdOut == 1 && fdStdErr == 2) {
-            inherit = FALSE;
-        } else {
-            inherit = TRUE;
-        }
-
-        if ((flags & RUN_PROCESS_IN_NEW_GROUP) != 0) {
-            dwFlags |= CREATE_NEW_PROCESS_GROUP;
-        }
-
-	if (!CreateProcess(NULL, cmd, NULL, NULL, inherit, dwFlags, environment, workingDirectory, &sInfo, &pInfo))
-	{
-                goto cleanup_err;
-	}
-	CloseHandle(pInfo.hThread);
-
-	// Close the ends of the pipes that were inherited by the
-	// child process.  This is important, otherwise we won't see
-	// EOF on these pipes when the child process exits.
-        if (hStdInputRead   != INVALID_HANDLE_VALUE) CloseHandle(hStdInputRead);
-        if (hStdOutputWrite != INVALID_HANDLE_VALUE) CloseHandle(hStdOutputWrite);
-        if (hStdErrorWrite  != INVALID_HANDLE_VALUE) CloseHandle(hStdErrorWrite);
-
-	*pfdStdInput  = _open_osfhandle((intptr_t) hStdInputWrite, _O_WRONLY);
-	*pfdStdOutput = _open_osfhandle((intptr_t) hStdOutputRead, _O_RDONLY);
-  	*pfdStdError  = _open_osfhandle((intptr_t) hStdErrorRead,  _O_RDONLY);
-
-  	return (int) pInfo.hProcess;
-
-cleanup_err:
-        if (hStdInputRead   != INVALID_HANDLE_VALUE) CloseHandle(hStdInputRead);
-        if (hStdInputWrite  != INVALID_HANDLE_VALUE) CloseHandle(hStdInputWrite);
-        if (hStdOutputRead  != INVALID_HANDLE_VALUE) CloseHandle(hStdOutputRead);
-        if (hStdOutputWrite != INVALID_HANDLE_VALUE) CloseHandle(hStdOutputWrite);
-        if (hStdErrorRead   != INVALID_HANDLE_VALUE) CloseHandle(hStdErrorRead);
-        if (hStdErrorWrite  != INVALID_HANDLE_VALUE) CloseHandle(hStdErrorWrite);
-        maperrno();
-        return -1;
-}
-
-int
-terminateProcess (ProcHandle handle)
-{
-    if (!TerminateProcess((HANDLE) handle, 1)) {
-	maperrno();
-	return -1;
-    }
-    return 0;
-}
-
-int
-getProcessExitCode (ProcHandle handle, int *pExitCode)
-{
-    *pExitCode = 0;
-
-    if (WaitForSingleObject((HANDLE) handle, 1) == WAIT_OBJECT_0)
-    {
-	if (GetExitCodeProcess((HANDLE) handle, (DWORD *) pExitCode) == 0)
-	{
-	    maperrno();
-	    return -1;
-	}
-	return 1;
-    }
-    
-    return 0;
-}
-
-int
-waitForProcess (ProcHandle handle, int *pret)
-{
-    DWORD retCode;
-
-    if (WaitForSingleObject((HANDLE) handle, INFINITE) == WAIT_OBJECT_0)
-    {
-	if (GetExitCodeProcess((HANDLE) handle, &retCode) == 0)
-	{
-	    maperrno();
-	    return -1;
-	}
-        *pret = retCode;
-	return 0;
-    }
-    
-    maperrno();
-    return -1;
-}
-
-#endif /* Win32 */
+/* ----------------------------------------------------------------------------
+   (c) The University of Glasgow 2004
+   
+   Support for System.Process
+   ------------------------------------------------------------------------- */
+
+#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)
+#define UNICODE
+#endif
+
+/* XXX This is a nasty hack; should put everything necessary in this package */
+#include "HsBase.h"
+#include "Rts.h"
+
+#include "runProcess.h"
+
+#if !(defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32))
+
+#include "execvpe.h"
+
+/* ----------------------------------------------------------------------------
+   UNIX versions
+   ------------------------------------------------------------------------- */
+
+static long max_fd = 0;
+
+// Rts internal API, not exposed in a public header file:
+extern void blockUserSignals(void);
+extern void unblockUserSignals(void);
+
+ProcHandle
+runInteractiveProcess (char *const args[], 
+		       char *workingDirectory, char **environment,
+                       int fdStdIn, int fdStdOut, int fdStdErr,
+		       int *pfdStdInput, int *pfdStdOutput, int *pfdStdError,
+                       int set_inthandler, long inthandler, 
+                       int set_quithandler, long quithandler,
+                       int flags)
+{
+    int close_fds = ((flags & RUN_PROCESS_IN_CLOSE_FDS) != 0);
+    int pid;
+    int fdStdInput[2], fdStdOutput[2], fdStdError[2];
+    int r;
+    struct sigaction dfl;
+
+    // Ordering matters here, see below [Note #431].
+    if (fdStdIn == -1) {
+        r = pipe(fdStdInput);
+        if (r == -1) { 
+            sysErrorBelch("runInteractiveProcess: pipe");
+            return -1;
+        }
+        
+    }
+    if (fdStdOut == -1) {
+        r = pipe(fdStdOutput);
+        if (r == -1) { 
+            sysErrorBelch("runInteractiveProcess: pipe");
+            return -1;
+        }
+    }
+    if (fdStdErr == -1) {
+        r = pipe(fdStdError);
+        if (r == -1) { 
+            sysErrorBelch("runInteractiveProcess: pipe");
+            return -1;
+        }
+    }
+
+    // Block signals with Haskell handlers.  The danger here is that
+    // with the threaded RTS, a signal arrives in the child process,
+    // the RTS writes the signal information into the pipe (which is
+    // shared between parent and child), and the parent behaves as if
+    // the signal had been raised.
+    blockUserSignals();
+
+    // See #4074.  Sometimes fork() gets interrupted by the timer
+    // signal and keeps restarting indefinitely.
+    stopTimer();
+
+    switch(pid = fork())
+    {
+    case -1:
+        unblockUserSignals();
+#if __GLASGOW_HASKELL__ > 612
+        startTimer();
+#endif
+        if (fdStdIn == -1) {
+            close(fdStdInput[0]);
+            close(fdStdInput[1]);
+        }
+        if (fdStdOut == -1) {
+            close(fdStdOutput[0]);
+            close(fdStdOutput[1]);
+        }
+        if (fdStdErr == -1) {
+            close(fdStdError[0]);
+            close(fdStdError[1]);
+        }
+	return -1;
+	
+    case 0:
+    {
+        // WARNING!  we are now in the child of vfork(), so any memory
+        // we modify below will also be seen in the parent process.
+
+        if ((flags & RUN_PROCESS_IN_NEW_GROUP) != 0) {
+            setpgid(0, 0);
+        }
+        unblockUserSignals();
+
+	if (workingDirectory) {
+	    if (chdir (workingDirectory) < 0) {
+                // See #1593.  The convention for the exit code when
+                // exec() fails seems to be 127 (gleened from C's
+                // system()), but there's no equivalent convention for
+                // chdir(), so I'm picking 126 --SimonM.
+                _exit(126);
+	    }
+	}
+	
+        // [Note #431]: Ordering matters here.  If any of the FDs
+        // 0,1,2 were initially closed, then our pipes may have used
+        // these FDs.  So when we dup2 the pipe FDs down to 0,1,2, we
+        // must do it in that order, otherwise we could overwrite an
+        // FD that we need later.
+
+        if (fdStdIn == -1) {
+            if (fdStdInput[0] != STDIN_FILENO) {
+                dup2 (fdStdInput[0], STDIN_FILENO);
+                close(fdStdInput[0]);
+            }
+            close(fdStdInput[1]);
+        } else {
+            dup2(fdStdIn,  STDIN_FILENO);
+        }
+
+        if (fdStdOut == -1) {
+            if (fdStdOutput[1] != STDOUT_FILENO) {
+                dup2 (fdStdOutput[1], STDOUT_FILENO);
+                close(fdStdOutput[1]);
+            }
+            close(fdStdOutput[0]);
+        } else {
+            dup2(fdStdOut,  STDOUT_FILENO);
+        }
+
+        if (fdStdErr == -1) {
+            if (fdStdError[1] != STDERR_FILENO) {
+                dup2 (fdStdError[1], STDERR_FILENO);
+                close(fdStdError[1]);
+            }
+            close(fdStdError[0]);
+        } else {
+            dup2(fdStdErr,  STDERR_FILENO);
+        }
+            
+        if (close_fds) {
+            int i;
+            if (max_fd == 0) {
+#if HAVE_SYSCONF
+                max_fd = sysconf(_SC_OPEN_MAX);
+                if (max_fd == -1) {
+                    max_fd = 256;
+                }
+#else
+                max_fd = 256;
+#endif
+            }
+            for (i = 3; i < max_fd; i++) {
+                close(i);
+            }
+        }
+
+	/* Set the SIGINT/SIGQUIT signal handlers in the child, if requested 
+	 */
+        (void)sigemptyset(&dfl.sa_mask);
+        dfl.sa_flags = 0;
+	if (set_inthandler) {
+	    dfl.sa_handler = (void *)inthandler;
+	    (void)sigaction(SIGINT, &dfl, NULL);
+	}
+	if (set_quithandler) {
+	    dfl.sa_handler = (void *)quithandler;
+	    (void)sigaction(SIGQUIT,  &dfl, NULL);
+	}
+
+	/* the child */
+	if (environment) {
+	    execvpe(args[0], args, environment);
+	} else {
+	    execvp(args[0], args);
+	}
+    }
+    _exit(127);
+    
+    default:
+	if ((flags & RUN_PROCESS_IN_NEW_GROUP) != 0) {
+            setpgid(pid, pid);
+	}
+	if (fdStdIn  == -1) {
+            close(fdStdInput[0]);
+            fcntl(fdStdInput[1], F_SETFD, FD_CLOEXEC);
+            *pfdStdInput  = fdStdInput[1];
+        }
+	if (fdStdOut == -1) {
+            close(fdStdOutput[1]);
+            fcntl(fdStdOutput[0], F_SETFD, FD_CLOEXEC);
+            *pfdStdOutput = fdStdOutput[0];
+        }
+        if (fdStdErr == -1) {
+            close(fdStdError[1]);
+            fcntl(fdStdError[0], F_SETFD, FD_CLOEXEC);
+            *pfdStdError  = fdStdError[0];
+        }
+	break;
+    }
+    unblockUserSignals();
+    startTimer();
+    
+    return pid;
+}
+
+int
+terminateProcess (ProcHandle handle)
+{
+    return (kill(handle, SIGTERM) == 0);
+}
+
+int
+getProcessExitCode (ProcHandle handle, int *pExitCode)
+{
+    int wstat, res;
+    
+    *pExitCode = 0;
+    
+    if ((res = waitpid(handle, &wstat, WNOHANG)) > 0)
+    {
+	if (WIFEXITED(wstat))
+	{
+	    *pExitCode = WEXITSTATUS(wstat);
+	    return 1;
+	}
+	else
+	    if (WIFSIGNALED(wstat))
+	    {
+		errno = EINTR;
+		return -1;
+	    }
+	    else
+	    {
+		/* This should never happen */
+	    }
+    }
+    
+    if (res == 0) return 0;
+
+    if (errno == ECHILD) 
+    {
+	    *pExitCode = 0;
+	    return 1;
+    }
+
+    return -1;
+}
+
+int waitForProcess (ProcHandle handle, int *pret)
+{
+    int wstat;
+    
+    if (waitpid(handle, &wstat, 0) < 0)
+    {
+        return -1;
+    }
+    
+    if (WIFEXITED(wstat)) {
+        *pret = WEXITSTATUS(wstat);
+	return 0;
+    }
+    else
+	if (WIFSIGNALED(wstat))
+	{
+            *pret = wstat;
+	    return 0;
+	}
+	else
+	{
+	    /* This should never happen */
+	}
+    
+    return -1;
+}
+
+#else
+/* ----------------------------------------------------------------------------
+   Win32 versions
+   ------------------------------------------------------------------------- */
+
+/* -------------------- WINDOWS VERSION --------------------- */
+
+/*
+ * Function: mkAnonPipe
+ *
+ * Purpose:  create an anonymous pipe with read and write ends being
+ *           optionally (non-)inheritable.
+ */
+static BOOL
+mkAnonPipe (HANDLE* pHandleIn, BOOL isInheritableIn, 
+	    HANDLE* pHandleOut, BOOL isInheritableOut)
+{
+	HANDLE hTemporaryIn  = NULL;
+	HANDLE hTemporaryOut = NULL;
+
+	/* Create the anon pipe with both ends inheritable */
+	if (!CreatePipe(&hTemporaryIn, &hTemporaryOut, NULL, 0))
+	{
+		maperrno();
+		*pHandleIn  = NULL;
+		*pHandleOut = NULL;
+		return FALSE;
+	}
+
+	if (isInheritableIn) {
+            // SetHandleInformation requires at least Win2k
+            if (!SetHandleInformation(hTemporaryIn,
+                                      HANDLE_FLAG_INHERIT, 
+                                      HANDLE_FLAG_INHERIT))
+            {
+                maperrno();
+                *pHandleIn  = NULL;
+                *pHandleOut = NULL;
+                CloseHandle(hTemporaryIn);
+                CloseHandle(hTemporaryOut);
+                return FALSE;
+            }
+	}
+        *pHandleIn = hTemporaryIn;
+
+	if (isInheritableOut) {
+            if (!SetHandleInformation(hTemporaryOut,
+                                      HANDLE_FLAG_INHERIT, 
+                                      HANDLE_FLAG_INHERIT))
+            {
+                maperrno();
+                *pHandleIn  = NULL;
+                *pHandleOut = NULL;
+                CloseHandle(hTemporaryIn);
+                CloseHandle(hTemporaryOut);
+                return FALSE;
+            }
+        }
+        *pHandleOut = hTemporaryOut;
+        
+	return TRUE;
+}
+
+ProcHandle
+runInteractiveProcess (wchar_t *cmd, wchar_t *workingDirectory, 
+                       void *environment,
+                       int fdStdIn, int fdStdOut, int fdStdErr,
+		       int *pfdStdInput, int *pfdStdOutput, int *pfdStdError,
+                       int flags)
+{
+	STARTUPINFO sInfo;
+	PROCESS_INFORMATION pInfo;
+	HANDLE hStdInputRead   = INVALID_HANDLE_VALUE;
+        HANDLE hStdInputWrite  = INVALID_HANDLE_VALUE;
+	HANDLE hStdOutputRead  = INVALID_HANDLE_VALUE;
+        HANDLE hStdOutputWrite = INVALID_HANDLE_VALUE;
+	HANDLE hStdErrorRead   = INVALID_HANDLE_VALUE;
+        HANDLE hStdErrorWrite  = INVALID_HANDLE_VALUE;
+    BOOL close_fds = ((flags & RUN_PROCESS_IN_CLOSE_FDS) != 0);
+	DWORD dwFlags = 0;
+	BOOL status;
+        BOOL inherit;
+
+	ZeroMemory(&sInfo, sizeof(sInfo));
+	sInfo.cb = sizeof(sInfo);
+	sInfo.dwFlags = STARTF_USESTDHANDLES;
+
+	if (fdStdIn == -1) {
+            if (!mkAnonPipe(&hStdInputRead,  TRUE, &hStdInputWrite,  FALSE))
+                goto cleanup_err;
+            sInfo.hStdInput = hStdInputRead;
+        } else if (fdStdIn == 0) {
+            // Don't duplicate stdin, as console handles cannot be
+            // duplicated and inherited. urg.
+            sInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+        } else {
+            // The handle might not be inheritable, so duplicate it
+            status = DuplicateHandle(GetCurrentProcess(), 
+                                     (HANDLE) _get_osfhandle(fdStdIn),
+                                     GetCurrentProcess(), &hStdInputRead,
+                                     0,
+                                     TRUE, /* inheritable */
+                                     DUPLICATE_SAME_ACCESS);
+            if (!status) goto cleanup_err;
+            sInfo.hStdInput = hStdInputRead;
+        }
+
+	if (fdStdOut == -1) {
+            if (!mkAnonPipe(&hStdOutputRead,  FALSE, &hStdOutputWrite,  TRUE))
+                goto cleanup_err;
+            sInfo.hStdOutput = hStdOutputWrite;
+        } else if (fdStdOut == 1) {
+            // Don't duplicate stdout, as console handles cannot be
+            // duplicated and inherited. urg.
+            sInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
+        } else {
+            // The handle might not be inheritable, so duplicate it
+            status = DuplicateHandle(GetCurrentProcess(), 
+                                     (HANDLE) _get_osfhandle(fdStdOut),
+                                     GetCurrentProcess(), &hStdOutputWrite,
+                                     0,
+                                     TRUE, /* inheritable */
+                                     DUPLICATE_SAME_ACCESS);
+            if (!status) goto cleanup_err;
+            sInfo.hStdOutput = hStdOutputWrite;
+        }
+
+	if (fdStdErr == -1) {
+            if (!mkAnonPipe(&hStdErrorRead,  TRUE, &hStdErrorWrite,  TRUE))
+                goto cleanup_err;
+            sInfo.hStdError = hStdErrorWrite;
+        } else if (fdStdErr == 2) {
+            // Don't duplicate stderr, as console handles cannot be
+            // duplicated and inherited. urg.
+            sInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+        } else {
+            /* The handle might not be inheritable, so duplicate it */
+            status = DuplicateHandle(GetCurrentProcess(), 
+                                     (HANDLE) _get_osfhandle(fdStdErr),
+                                     GetCurrentProcess(), &hStdErrorWrite,
+                                     0,
+                                     TRUE, /* inheritable */
+                                     DUPLICATE_SAME_ACCESS);
+            if (!status) goto cleanup_err;
+            sInfo.hStdError = hStdErrorWrite;
+        }
+
+	if (sInfo.hStdInput  != GetStdHandle(STD_INPUT_HANDLE)  &&
+	    sInfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE) &&
+	    sInfo.hStdError  != GetStdHandle(STD_ERROR_HANDLE)  &&
+	    (flags & RUN_PROCESS_IN_NEW_GROUP) == 0)
+		dwFlags |= CREATE_NO_WINDOW;   // Run without console window only when both output and error are redirected
+
+        // See #3231
+        if (close_fds && fdStdIn == 0 && fdStdOut == 1 && fdStdErr == 2) {
+            inherit = FALSE;
+        } else {
+            inherit = TRUE;
+        }
+
+        if ((flags & RUN_PROCESS_IN_NEW_GROUP) != 0) {
+            dwFlags |= CREATE_NEW_PROCESS_GROUP;
+        }
+
+	if (!CreateProcess(NULL, cmd, NULL, NULL, inherit, dwFlags, environment, workingDirectory, &sInfo, &pInfo))
+	{
+                goto cleanup_err;
+	}
+	CloseHandle(pInfo.hThread);
+
+	// Close the ends of the pipes that were inherited by the
+	// child process.  This is important, otherwise we won't see
+	// EOF on these pipes when the child process exits.
+        if (hStdInputRead   != INVALID_HANDLE_VALUE) CloseHandle(hStdInputRead);
+        if (hStdOutputWrite != INVALID_HANDLE_VALUE) CloseHandle(hStdOutputWrite);
+        if (hStdErrorWrite  != INVALID_HANDLE_VALUE) CloseHandle(hStdErrorWrite);
+
+	*pfdStdInput  = _open_osfhandle((intptr_t) hStdInputWrite, _O_WRONLY);
+	*pfdStdOutput = _open_osfhandle((intptr_t) hStdOutputRead, _O_RDONLY);
+  	*pfdStdError  = _open_osfhandle((intptr_t) hStdErrorRead,  _O_RDONLY);
+
+  	return pInfo.hProcess;
+
+cleanup_err:
+        if (hStdInputRead   != INVALID_HANDLE_VALUE) CloseHandle(hStdInputRead);
+        if (hStdInputWrite  != INVALID_HANDLE_VALUE) CloseHandle(hStdInputWrite);
+        if (hStdOutputRead  != INVALID_HANDLE_VALUE) CloseHandle(hStdOutputRead);
+        if (hStdOutputWrite != INVALID_HANDLE_VALUE) CloseHandle(hStdOutputWrite);
+        if (hStdErrorRead   != INVALID_HANDLE_VALUE) CloseHandle(hStdErrorRead);
+        if (hStdErrorWrite  != INVALID_HANDLE_VALUE) CloseHandle(hStdErrorWrite);
+        maperrno();
+        return NULL;
+}
+
+int
+terminateProcess (ProcHandle handle)
+{
+    if (!TerminateProcess((HANDLE) handle, 1)) {
+	maperrno();
+	return -1;
+    }
+    return 0;
+}
+
+int
+getProcessExitCode (ProcHandle handle, int *pExitCode)
+{
+    *pExitCode = 0;
+
+    if (WaitForSingleObject((HANDLE) handle, 1) == WAIT_OBJECT_0)
+    {
+	if (GetExitCodeProcess((HANDLE) handle, (DWORD *) pExitCode) == 0)
+	{
+	    maperrno();
+	    return -1;
+	}
+	return 1;
+    }
+    
+    return 0;
+}
+
+int
+waitForProcess (ProcHandle handle, int *pret)
+{
+    DWORD retCode;
+
+    if (WaitForSingleObject((HANDLE) handle, INFINITE) == WAIT_OBJECT_0)
+    {
+	if (GetExitCodeProcess((HANDLE) handle, &retCode) == 0)
+	{
+	    maperrno();
+	    return -1;
+	}
+        *pret = retCode;
+	return 0;
+    }
+    
+    maperrno();
+    return -1;
+}
+
+#endif /* Win32 */
diff --git a/include/runProcess.h b/include/runProcess.h
index 6838f5b4..818a96f9 100644
--- a/include/runProcess.h
+++ b/include/runProcess.h
@@ -1,77 +1,77 @@
-/* ----------------------------------------------------------------------------
-   (c) The University of Glasgow 2004
-
-   Interface for code in runProcess.c (providing support for System.Process)
-   ------------------------------------------------------------------------- */
-
-#include "HsProcessConfig.h"
-// Otherwise these clash with similar definitions from other packages:
-#undef PACKAGE_BUGREPORT
-#undef PACKAGE_NAME
-#undef PACKAGE_STRING
-#undef PACKAGE_TARNAME
-#undef PACKAGE_VERSION
-
-#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)
-#define UNICODE
-#include <windows.h>
-#include <stdlib.h>
-#endif
-
-#include <unistd.h>
-#include <sys/types.h>
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#ifdef HAVE_VFORK_H
-#include <vfork.h>
-#endif
-
-#ifdef HAVE_VFORK
-#define fork vfork
-#endif
-
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-
-#if !(defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32))
-typedef pid_t ProcHandle;
-#else
-// Should really be intptr_t, but we don't have that type on the Haskell side
-typedef long ProcHandle;
-#endif
-
-#include "processFlags.h"
-
-#if !(defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32))
-
-extern ProcHandle runInteractiveProcess( char *const args[], 
-					 char *workingDirectory, 
-					 char **environment, 
-                                         int fdStdIn, int fdStdOut, int fdStdErr,
-					 int *pfdStdInput, 
-					 int *pfdStdOutput, 
-					 int *pfdStdError,
-                                         int set_inthandler, long inthandler, 
-                                         int set_quithandler, long quithandler,
-                                         int flags);
-
-#else
-
-extern ProcHandle runInteractiveProcess( wchar_t *cmd,
-					 wchar_t *workingDirectory,
-					 void *environment,
-                                         int fdStdIn, int fdStdOut, int fdStdErr,
-					 int *pfdStdInput,
-					 int *pfdStdOutput,
-					 int *pfdStdError,
-                                         int flags);
-
-#endif
-
-extern int terminateProcess( ProcHandle handle );
-extern int getProcessExitCode( ProcHandle handle, int *pExitCode );
-extern int waitForProcess( ProcHandle handle, int *ret );
+/* ----------------------------------------------------------------------------
+   (c) The University of Glasgow 2004
+
+   Interface for code in runProcess.c (providing support for System.Process)
+   ------------------------------------------------------------------------- */
+
+#include "HsProcessConfig.h"
+// Otherwise these clash with similar definitions from other packages:
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+
+#if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)
+#define UNICODE
+#include <windows.h>
+#include <stdlib.h>
+#endif
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_VFORK_H
+#include <vfork.h>
+#endif
+
+#ifdef HAVE_VFORK
+#define fork vfork
+#endif
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#if !(defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32))
+typedef pid_t ProcHandle;
+#else
+// Should really be intptr_t, but we don't have that type on the Haskell side
+typedef PHANDLE ProcHandle;
+#endif
+
+#include "processFlags.h"
+
+#if !(defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32))
+
+extern ProcHandle runInteractiveProcess( char *const args[], 
+					 char *workingDirectory, 
+					 char **environment, 
+                                         int fdStdIn, int fdStdOut, int fdStdErr,
+					 int *pfdStdInput, 
+					 int *pfdStdOutput, 
+					 int *pfdStdError,
+                                         int set_inthandler, long inthandler, 
+                                         int set_quithandler, long quithandler,
+                                         int flags);
+
+#else
+
+extern ProcHandle runInteractiveProcess( wchar_t *cmd,
+					 wchar_t *workingDirectory,
+					 void *environment,
+                                         int fdStdIn, int fdStdOut, int fdStdErr,
+					 int *pfdStdInput,
+					 int *pfdStdOutput,
+					 int *pfdStdError,
+                                         int flags);
+
+#endif
+
+extern int terminateProcess( ProcHandle handle );
+extern int getProcessExitCode( ProcHandle handle, int *pExitCode );
+extern int waitForProcess( ProcHandle handle, int *ret );
-- 
GitLab