    module System.Posix.Process.Internals (
           pPrPr_disableITimers, c_execvpe,
           decipherWaitStatus, ProcessStatus(..) ) where

    import Foreign
    import Foreign.C
    import System.Exit
    import System.IO.Error
    import GHC.Conc (Signal)

    data ProcessStatus = Exited ExitCode
                       | Terminated Signal
                       | Stopped Signal
    		   deriving (Eq, Ord, Show)

    -- this function disables the itimer, which would otherwise cause confusing
    -- signals to be sent to the new process.
    foreign import ccall unsafe "pPrPr_disableITimers"
      pPrPr_disableITimers :: IO ()

    foreign import ccall unsafe "execvpe"
      c_execvpe :: CString -> Ptr CString -> Ptr CString -> IO CInt

    decipherWaitStatus :: CInt -> IO ProcessStatus
    decipherWaitStatus wstat =
      if c_WIFEXITED wstat /= 0
          then do
            let exitstatus = c_WEXITSTATUS wstat
            if exitstatus == 0
    	   then return (Exited ExitSuccess)
    	   else return (Exited (ExitFailure (fromIntegral exitstatus)))
          else do
            if c_WIFSIGNALED wstat /= 0
    	   then do
    		let termsig = c_WTERMSIG wstat
    		return (Terminated (fromIntegral termsig))
    	   else do
    		if c_WIFSTOPPED wstat /= 0
    		   then do
    			let stopsig = c_WSTOPSIG wstat
    			return (Stopped (fromIntegral stopsig))
    		   else do
    			ioError (mkIOError illegalOperationErrorType
    				   "waitStatus" Nothing Nothing)

    foreign import ccall unsafe "__hsunix_wifexited"
      c_WIFEXITED :: CInt -> CInt

    foreign import ccall unsafe "__hsunix_wexitstatus"
      c_WEXITSTATUS :: CInt -> CInt

    foreign import ccall unsafe "__hsunix_wifsignaled"
      c_WIFSIGNALED :: CInt -> CInt

    foreign import ccall unsafe "__hsunix_wtermsig"
      c_WTERMSIG :: CInt -> CInt

    foreign import ccall unsafe "__hsunix_wifstopped"
      c_WIFSTOPPED :: CInt -> CInt

    foreign import ccall unsafe "__hsunix_wstopsig"
      c_WSTOPSIG :: CInt -> CInt