{-# LINE 1 "libraries/unix/System/Posix/Process/ByteString.hsc" #-}

{-# LINE 2 "libraries/unix/System/Posix/Process/ByteString.hsc" #-}
{-# LANGUAGE Safe #-}

{-# LINE 6 "libraries/unix/System/Posix/Process/ByteString.hsc" #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  System.Posix.Process.ByteString
-- Copyright   :  (c) The University of Glasgow 2002
-- License     :  BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer  :  libraries@haskell.org
-- Stability   :  provisional
-- Portability :  non-portable (requires POSIX)
--
-- POSIX process support.  See also the System.Cmd and System.Process
-- modules in the process package.
--
-----------------------------------------------------------------------------

module System.Posix.Process.ByteString (
    -- * Processes

    -- ** Forking and executing
    forkProcess,
    forkProcessWithUnmask,
    executeFile,

    -- ** Exiting
    exitImmediately,

    -- ** Process environment
    getProcessID,
    getParentProcessID,

    -- ** Process groups
    getProcessGroupID,
    getProcessGroupIDOf,
    createProcessGroupFor,
    joinProcessGroup,
    setProcessGroupIDOf,

    -- ** Sessions
    createSession,

    -- ** Process times
    ProcessTimes(..),
    getProcessTimes,

    -- ** Scheduling priority
    nice,
    getProcessPriority,
    getProcessGroupPriority,
    getUserPriority,
    setProcessPriority,
    setProcessGroupPriority,
    setUserPriority,

    -- ** Process status
    ProcessStatus(..),
    getProcessStatus,
    getAnyProcessStatus,
    getGroupProcessStatus,

    -- ** Deprecated
    createProcessGroup,
    setProcessGroupID,

 ) where



import Foreign
import System.Posix.Process.Internals
import System.Posix.Process.Common

import Foreign.C hiding (
     throwErrnoPath,
     throwErrnoPathIf,
     throwErrnoPathIf_,
     throwErrnoPathIfNull,
     throwErrnoPathIfMinus1,
     throwErrnoPathIfMinus1_ )

import Data.ByteString (ByteString)
import qualified Data.ByteString.Char8 as BC

import System.Posix.ByteString.FilePath

-- | @'executeFile' cmd args env@ calls one of the
--   @execv*@ family, depending on whether or not the current
--   PATH is to be searched for the command, and whether or not an
--   environment is provided to supersede the process's current
--   environment.  The basename (leading directory names suppressed) of
--   the command is passed to @execv*@ as @arg[0]@;
--   the argument list passed to 'executeFile' therefore
--   begins with @arg[1]@.
executeFile :: RawFilePath                          -- ^ Command
            -> Bool                         -- ^ Search PATH?
            -> [ByteString]                 -- ^ Arguments
            -> Maybe [(ByteString, ByteString)]     -- ^ Environment
            -> IO a
executeFile :: forall a.
RawFilePath
-> Bool
-> [RawFilePath]
-> Maybe [(RawFilePath, RawFilePath)]
-> IO a
executeFile RawFilePath
path Bool
search [RawFilePath]
args Maybe [(RawFilePath, RawFilePath)]
Nothing = do
  RawFilePath -> (Ptr CChar -> IO a) -> IO a
forall a. RawFilePath -> (Ptr CChar -> IO a) -> IO a
withFilePath RawFilePath
path ((Ptr CChar -> IO a) -> IO a) -> (Ptr CChar -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
s ->
    (RawFilePath -> (Ptr CChar -> IO a) -> IO a)
-> [RawFilePath] -> ([Ptr CChar] -> IO a) -> IO a
forall a b res.
(a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res
withMany RawFilePath -> (Ptr CChar -> IO a) -> IO a
forall a. RawFilePath -> (Ptr CChar -> IO a) -> IO a
withFilePath (RawFilePath
pathRawFilePath -> [RawFilePath] -> [RawFilePath]
forall a. a -> [a] -> [a]
:[RawFilePath]
args) (([Ptr CChar] -> IO a) -> IO a) -> ([Ptr CChar] -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \[Ptr CChar]
cstrs ->
      Ptr CChar -> [Ptr CChar] -> (Ptr (Ptr CChar) -> IO a) -> IO a
forall a b. Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
withArray0 Ptr CChar
forall a. Ptr a
nullPtr [Ptr CChar]
cstrs ((Ptr (Ptr CChar) -> IO a) -> IO a)
-> (Ptr (Ptr CChar) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr CChar)
arr -> do
        IO ()
pPrPr_disableITimers
        if Bool
search
           then String -> RawFilePath -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIfMinus1_ String
"executeFile" RawFilePath
path (Ptr CChar -> Ptr (Ptr CChar) -> IO CInt
c_execvp Ptr CChar
s Ptr (Ptr CChar)
arr)
           else String -> RawFilePath -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIfMinus1_ String
"executeFile" RawFilePath
path (Ptr CChar -> Ptr (Ptr CChar) -> IO CInt
c_execv Ptr CChar
s Ptr (Ptr CChar)
arr)
        a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
forall a. HasCallStack => a
undefined -- never reached

executeFile RawFilePath
path Bool
search [RawFilePath]
args (Just [(RawFilePath, RawFilePath)]
env) = do
  RawFilePath -> (Ptr CChar -> IO a) -> IO a
forall a. RawFilePath -> (Ptr CChar -> IO a) -> IO a
withFilePath RawFilePath
path ((Ptr CChar -> IO a) -> IO a) -> (Ptr CChar -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
s ->
    (RawFilePath -> (Ptr CChar -> IO a) -> IO a)
-> [RawFilePath] -> ([Ptr CChar] -> IO a) -> IO a
forall a b res.
(a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res
withMany RawFilePath -> (Ptr CChar -> IO a) -> IO a
forall a. RawFilePath -> (Ptr CChar -> IO a) -> IO a
withFilePath (RawFilePath
pathRawFilePath -> [RawFilePath] -> [RawFilePath]
forall a. a -> [a] -> [a]
:[RawFilePath]
args) (([Ptr CChar] -> IO a) -> IO a) -> ([Ptr CChar] -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \[Ptr CChar]
cstrs ->
      Ptr CChar -> [Ptr CChar] -> (Ptr (Ptr CChar) -> IO a) -> IO a
forall a b. Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
withArray0 Ptr CChar
forall a. Ptr a
nullPtr [Ptr CChar]
cstrs ((Ptr (Ptr CChar) -> IO a) -> IO a)
-> (Ptr (Ptr CChar) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr CChar)
arg_arr ->
    let env' :: [RawFilePath]
env' = ((RawFilePath, RawFilePath) -> RawFilePath)
-> [(RawFilePath, RawFilePath)] -> [RawFilePath]
forall a b. (a -> b) -> [a] -> [b]
map (\ (RawFilePath
name, RawFilePath
val) -> RawFilePath
name RawFilePath -> RawFilePath -> RawFilePath
`BC.append` (Char
'=' Char -> RawFilePath -> RawFilePath
`BC.cons` RawFilePath
val)) [(RawFilePath, RawFilePath)]
env in
    (RawFilePath -> (Ptr CChar -> IO a) -> IO a)
-> [RawFilePath] -> ([Ptr CChar] -> IO a) -> IO a
forall a b res.
(a -> (b -> res) -> res) -> [a] -> ([b] -> res) -> res
withMany RawFilePath -> (Ptr CChar -> IO a) -> IO a
forall a. RawFilePath -> (Ptr CChar -> IO a) -> IO a
withFilePath [RawFilePath]
env' (([Ptr CChar] -> IO a) -> IO a) -> ([Ptr CChar] -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \[Ptr CChar]
cenv ->
      Ptr CChar -> [Ptr CChar] -> (Ptr (Ptr CChar) -> IO a) -> IO a
forall a b. Storable a => a -> [a] -> (Ptr a -> IO b) -> IO b
withArray0 Ptr CChar
forall a. Ptr a
nullPtr [Ptr CChar]
cenv ((Ptr (Ptr CChar) -> IO a) -> IO a)
-> (Ptr (Ptr CChar) -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \Ptr (Ptr CChar)
env_arr -> do
        IO ()
pPrPr_disableITimers
        if Bool
search
           then String -> RawFilePath -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIfMinus1_ String
"executeFile" RawFilePath
path
                   (Ptr CChar -> Ptr (Ptr CChar) -> Ptr (Ptr CChar) -> IO CInt
c_execvpe Ptr CChar
s Ptr (Ptr CChar)
arg_arr Ptr (Ptr CChar)
env_arr)
           else String -> RawFilePath -> IO CInt -> IO ()
forall a. (Eq a, Num a) => String -> RawFilePath -> IO a -> IO ()
throwErrnoPathIfMinus1_ String
"executeFile" RawFilePath
path
                   (Ptr CChar -> Ptr (Ptr CChar) -> Ptr (Ptr CChar) -> IO CInt
c_execve Ptr CChar
s Ptr (Ptr CChar)
arg_arr Ptr (Ptr CChar)
env_arr)
        a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return a
forall a. HasCallStack => a
undefined -- never reached

foreign import ccall unsafe "execvp"
  c_execvp :: CString -> Ptr CString -> IO CInt

foreign import ccall unsafe "execv"
  c_execv :: CString -> Ptr CString -> IO CInt

foreign import ccall unsafe "execve"
  c_execve :: CString -> Ptr CString -> Ptr CString -> IO CInt