1 {-# OPTIONS_GHC -cpp -fffi #-}
2 -----------------------------------------------------------------------------
4 -- Module : System.Process
5 -- Copyright : (c) The University of Glasgow 2004
6 -- License : BSD-style (see the file libraries/base/LICENSE)
8 -- Maintainer : libraries@haskell.org
9 -- Stability : experimental
10 -- Portability : portable
12 -- Operations for creating and interacting with sub-processes.
14 -----------------------------------------------------------------------------
17 -- * Flag to control whether exiting the parent also kills the child.
18 -- * Windows impl of runProcess should close the Handles.
19 -- * Add system/rawSystem replacements
21 {- NOTES on createPipe:
23 createPipe is no longer exported, because of the following problems:
25 - it wasn't used to implement runInteractiveProcess on Unix, because
26 the file descriptors for the unused ends of the pipe need to be closed
29 - on Windows, a special version of createPipe is needed that sets
30 the inheritance flags correctly on the ends of the pipe (see
34 module System.Process (
35 -- * Running sub-processes
39 runInteractiveCommand,
40 runInteractiveProcess,
42 -- * Process completion
50 import System.Process.Internals
54 import System.IO ( IOMode(..), Handle, hClose )
55 import System.Exit ( ExitCode(..) )
57 import System.Posix.Internals
58 import GHC.IOBase ( FD )
59 import GHC.Handle ( openFd )
61 -- ----------------------------------------------------------------------------
64 {- | Runs a command using the shell.
70 runCommand string = do
71 (cmd,args) <- commandToProcess string
72 #if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
73 runProcessPosix "runCommand" cmd args Nothing Nothing Nothing Nothing Nothing
76 runProcessWin32 "runCommand" cmd [] Nothing Nothing Nothing Nothing Nothing args
79 -- ----------------------------------------------------------------------------
82 {- | Runs a raw command, optionally specifying 'Handle's from which to
83 take the @stdin@, @stdout@ and @stderr@ channels for the new
86 Any 'Handle's passed to 'runProcess' are placed immediately in the
90 :: FilePath -- ^ Filename of the executable
91 -> [String] -- ^ Arguments to pass to the executable
92 -> Maybe FilePath -- ^ Optional path to the working directory
93 -> Maybe [(String,String)] -- ^ Optional environment (otherwise inherit)
94 -> Maybe Handle -- ^ Handle to use for @stdin@
95 -> Maybe Handle -- ^ Handle to use for @stdout@
96 -> Maybe Handle -- ^ Handle to use for @stderr@
99 runProcess cmd args mb_cwd mb_env mb_stdin mb_stdout mb_stderr = do
100 #if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
101 h <- runProcessPosix "runProcess" cmd args mb_cwd mb_env
102 mb_stdin mb_stdout mb_stderr
105 h <- runProcessWin32 "runProcess" cmd args mb_cwd mb_env
106 mb_stdin mb_stdout mb_stderr ""
108 maybe (return ()) hClose mb_stdin
109 maybe (return ()) hClose mb_stdout
110 maybe (return ()) hClose mb_stderr
113 -- ----------------------------------------------------------------------------
114 -- runInteractiveCommand
116 {- | Runs a command using the shell, and returns 'Handle's that may
117 be used to communicate with the process via its @stdin@, @stdout@,
118 and @stderr@ respectively.
120 runInteractiveCommand
122 -> IO (Handle,Handle,Handle,ProcessHandle)
124 runInteractiveCommand string = do
125 (cmd,args) <- commandToProcess string
126 #if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
127 runInteractiveProcess1 "runInteractiveCommand" cmd args Nothing Nothing
129 runInteractiveProcess1 "runInteractiveCommand" cmd [] Nothing Nothing args
132 -- ----------------------------------------------------------------------------
133 -- runInteractiveProcess
135 {- | Runs a raw command, and returns 'Handle's that may be used to communicate
136 with the process via its @stdin@, @stdout@ and @stderr@ respectively.
138 For example, to start a process and feed a string to its stdin:
140 > (inp,out,err,pid) <- runInteractiveProcess "..."
141 > forkIO (hPutStr inp str)
143 runInteractiveProcess
144 :: FilePath -- ^ Filename of the executable
145 -> [String] -- ^ Arguments to pass to the executable
146 -> Maybe FilePath -- ^ Optional path to the working directory
147 -> Maybe [(String,String)] -- ^ Optional environment (otherwise inherit)
148 -> IO (Handle,Handle,Handle,ProcessHandle)
150 #if !defined(mingw32_HOST_OS) && !defined(__MINGW32__)
152 runInteractiveProcess cmd args mb_cwd mb_env =
153 runInteractiveProcess1 "runInteractiveProcess" cmd args mb_cwd mb_env
155 runInteractiveProcess1 fun cmd args mb_cwd mb_env = do
156 withFilePathException cmd $
157 alloca $ \ pfdStdInput ->
158 alloca $ \ pfdStdOutput ->
159 alloca $ \ pfdStdError ->
160 maybeWith withCEnvironment mb_env $ \pEnv ->
161 maybeWith withCString mb_cwd $ \pWorkDir ->
162 withMany withCString (cmd:args) $ \cstrs ->
163 withArray0 nullPtr cstrs $ \pargs -> do
164 proc_handle <- throwErrnoIfMinus1 fun
165 (c_runInteractiveProcess pargs pWorkDir pEnv
166 pfdStdInput pfdStdOutput pfdStdError)
167 hndStdInput <- fdToHandle pfdStdInput WriteMode
168 hndStdOutput <- fdToHandle pfdStdOutput ReadMode
169 hndStdError <- fdToHandle pfdStdError ReadMode
170 return (hndStdInput, hndStdOutput, hndStdError, ProcessHandle proc_handle)
172 foreign import ccall unsafe "runInteractiveProcess"
173 c_runInteractiveProcess
184 runInteractiveProcess cmd args mb_cwd mb_env =
185 runInteractiveProcess1 "runInteractiveProcess" cmd args mb_cwd mb_env ""
187 runInteractiveProcess1 fun cmd args workDir env extra_cmdline
188 = withFilePathException cmd $ do
189 let cmdline = translate cmd ++
190 concat (map ((' ':) . translate) args) ++
191 (if null extra_cmdline then "" else ' ':extra_cmdline)
192 withCString cmdline $ \pcmdline ->
193 alloca $ \ pfdStdInput ->
194 alloca $ \ pfdStdOutput ->
195 alloca $ \ pfdStdError -> do
196 maybeWith withCEnvironment env $ \pEnv -> do
197 maybeWith withCString workDir $ \pWorkDir -> do
198 proc_handle <- throwErrnoIfMinus1 fun $
199 c_runInteractiveProcess pcmdline pWorkDir pEnv
200 pfdStdInput pfdStdOutput pfdStdError
201 hndStdInput <- fdToHandle pfdStdInput WriteMode
202 hndStdOutput <- fdToHandle pfdStdOutput ReadMode
203 hndStdError <- fdToHandle pfdStdError ReadMode
204 return (hndStdInput, hndStdOutput, hndStdError,
205 ProcessHandle proc_handle)
207 foreign import ccall unsafe "runInteractiveProcess"
208 c_runInteractiveProcess
219 fdToHandle :: Ptr FD -> IOMode -> IO Handle
220 fdToHandle pfd mode = do
222 openFd fd (Just Stream)
223 False{-not a socket-}
224 ("fd:" ++ show fd) mode True{-binary-}
226 -- ----------------------------------------------------------------------------
229 {- | Waits for the specified process to terminate, and returns its exit code.
231 GHC Note: in order to call @waitForProcess@ without blocking all the
232 other threads in the system, you must compile the program with
238 waitForProcess (ProcessHandle handle) = do
239 code <- throwErrnoIfMinus1 "waitForProcess" (c_waitForProcess handle)
241 then return ExitSuccess
242 else return (ExitFailure (fromIntegral code))
244 -- ----------------------------------------------------------------------------
247 -- | Attempts to terminate the specified process. This function should
248 -- not be used under normal circumstances - no guarantees are given regarding
249 -- how cleanly the process is terminated. To check whether the process
250 -- has indeed terminated, use 'getProcessExitCode'.
252 -- On Unix systems, 'terminateProcess' sends the process the SIGKILL signal.
253 -- On Windows systems, the Win32 @TerminateProcess@ function is called, passing
254 -- an exit code of 1.
255 terminateProcess :: ProcessHandle -> IO ()
256 terminateProcess (ProcessHandle pid) =
257 throwErrnoIfMinus1_ "terminateProcess" (c_terminateProcess pid)
259 -- ----------------------------------------------------------------------------
260 -- getProcessExitCode
263 This is a non-blocking version of 'waitForProcess'. If the process is
264 still running, 'Nothing' is returned. If the process has exited, then
265 @'Just' e@ is returned where @e@ is the exit code of the process.
266 Subsequent calls to @getProcessExitStatus@ always return @'Just'
267 'ExitSuccess'@, regardless of what the original exit code was.
269 getProcessExitCode :: ProcessHandle -> IO (Maybe ExitCode)
270 getProcessExitCode (ProcessHandle handle) =
271 alloca $ \pExitCode -> do
272 res <- throwErrnoIfMinus1 "getProcessExitCode" (c_getProcessExitCode handle pExitCode)
273 code <- peek pExitCode
277 then return (Just ExitSuccess)
278 else return (Just (ExitFailure (fromIntegral code)))
280 -- ----------------------------------------------------------------------------
281 -- Interface to C bits
283 foreign import ccall unsafe "terminateProcess"
288 foreign import ccall unsafe "getProcessExitCode"
294 foreign import ccall safe "waitForProcess" -- NB. safe - can block