aboutsummaryrefslogtreecommitdiffhomepage
path: root/System/Posix/Process/Internals.hs
diff options
context:
space:
mode:
Diffstat (limited to 'System/Posix/Process/Internals.hs')
-rw-r--r--System/Posix/Process/Internals.hs55
1 files changed, 54 insertions, 1 deletions
diff --git a/System/Posix/Process/Internals.hs b/System/Posix/Process/Internals.hs
index 8639819..deb1992 100644
--- a/System/Posix/Process/Internals.hs
+++ b/System/Posix/Process/Internals.hs
@@ -1,8 +1,20 @@
-module System.Posix.Process.Internals (pPrPr_disableITimers, c_execvpe) where
+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)
+
+-- we had to move this into GHC.Conc in GHC to avoid recursive dependencies.
+-- it can be moved back when the signal handling stuff in base is moved out.
+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.
@@ -11,3 +23,44 @@ foreign import ccall unsafe "pPrPr_disableITimers"
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
+