1 {-# OPTIONS -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
48 import System.Process.Internals
52 import Data.Maybe ( fromMaybe )
53 import System.IO ( IOMode(..), Handle )
54 import System.Exit ( ExitCode(..) )
55 import Control.Exception ( handle, throwIO )
57 import System.Posix.Internals
58 import GHC.IOBase ( haFD, FD, Exception(..), IOException(..) )
59 import GHC.Handle ( stdin, stdout, stderr, withHandle_, openFd )
61 -- ----------------------------------------------------------------------------
64 {- | Runs a command using the shell.
70 runCommand string = do
71 (cmd,args) <- commandToProcess string
72 #if !defined(mingw32_TARGET_OS) && !defined(__MINGW32__)
73 runProcess1 "runCommand" cmd args Nothing Nothing Nothing Nothing Nothing
75 runProcess1 "runCommand" cmd [] Nothing Nothing Nothing Nothing Nothing args
78 -- ----------------------------------------------------------------------------
81 {- | Runs a raw command, optionally specifying 'Handle's from which to
82 take the @stdin@, @stdout@ and @stderr@ channels for the new
85 Any 'Handle's passed to 'runProcess' are placed immediately in the
86 closed state, so may no longer be referenced by the Haskell process.
89 :: FilePath -- ^ Filename of the executable
90 -> [String] -- ^ Arguments to pass to the executable
91 -> Maybe FilePath -- ^ Optional path to the working directory
92 -> Maybe [(String,String)] -- ^ Optional environment (otherwise inherit)
93 -> Maybe Handle -- ^ Handle to use for @stdin@
94 -> Maybe Handle -- ^ Handle to use for @stdout@
95 -> Maybe Handle -- ^ Handle to use for @stderr@
98 #if !defined(mingw32_TARGET_OS) && !defined(__MINGW32__)
100 runProcess cmd args mb_cwd mb_env mb_stdin mb_stdout mb_stderr
101 = runProcess1 "runProcess" cmd args mb_cwd mb_env mb_stdin mb_stdout mb_stderr
103 runProcess1 fun cmd args mb_cwd mb_env mb_stdin mb_stdout mb_stderr
104 = withFilePathException cmd $
105 withHandle_ fun (fromMaybe stdin mb_stdin) $ \hndStdInput ->
106 withHandle_ fun (fromMaybe stdout mb_stdout) $ \hndStdOutput ->
107 withHandle_ fun (fromMaybe stderr mb_stderr) $ \hndStdError ->
108 maybeWith withCEnvironment mb_env $ \pEnv ->
109 maybeWith withCString mb_cwd $ \pWorkDir ->
110 withMany withCString (cmd:args) $ \cstrs ->
111 withArray0 nullPtr cstrs $ \pargs -> do
112 ph <- throwErrnoIfMinus1 fun
113 (c_runProcess pargs pWorkDir pEnv
117 return (ProcessHandle ph)
119 foreign import ccall unsafe "runProcess"
121 :: Ptr CString -- args
122 -> CString -- working directory (or NULL)
123 -> Ptr CString -- env (or NULL)
131 runProcess cmd args mb_cwd mb_env mb_stdin mb_stdout mb_stderr =
132 runProcess1 "runProcess" cmd args mb_cwd mb_env
133 mb_stdin mb_stdout mb_stderr ""
135 runProcess1 fun cmd args mb_cwd mb_env
136 mb_stdin mb_stdout mb_stderr extra_cmdline
137 = withFilePathException cmd $
138 withHandle_ fun (fromMaybe stdin mb_stdin) $ \hndStdInput ->
139 withHandle_ fun (fromMaybe stdout mb_stdout) $ \hndStdOutput ->
140 withHandle_ fun (fromMaybe stderr mb_stderr) $ \hndStdError ->
141 maybeWith withCEnvironment mb_env $ \pEnv -> do
142 maybeWith withCString mb_cwd $ \pWorkDir -> do
143 let cmdline = translate cmd ++
144 concat (map ((' ':) . translate) args) ++
145 (if null extra_cmdline then "" else ' ':extra_cmdline)
146 withCString cmdline $ \pcmdline -> do
147 proc_handle <- throwErrnoIfMinus1 fun
148 (c_runProcess pcmdline pWorkDir pEnv
152 return (ProcessHandle proc_handle)
154 foreign import ccall unsafe "runProcess"
164 -- Set the standard HANDLEs for the child process appropriately. NOTE:
165 -- this relies on the HANDLEs being inheritable. By default, the
166 -- runtime open() function creates inheritable handles (unless O_NOINHERIT
167 -- is specified). But perhaps we should DuplicateHandle() to make sure
168 -- the handle is inheritable?
171 -- ----------------------------------------------------------------------------
172 -- runInteractiveCommand
174 {- | Runs a command using the shell, and returns 'Handle's that may
175 be used to communicate with the process via its @stdin@, @stdout@,
176 and @stderr@ respectively.
178 runInteractiveCommand
180 -> IO (Handle,Handle,Handle,ProcessHandle)
182 runInteractiveCommand string = do
183 (cmd,args) <- commandToProcess string
184 #if !defined(mingw32_TARGET_OS) && !defined(__MINGW32__)
185 runInteractiveProcess1 "runInteractiveCommand" cmd args Nothing Nothing
187 runInteractiveProcess1 "runInteractiveCommand" cmd [] Nothing Nothing args
190 -- ----------------------------------------------------------------------------
191 -- runInteractiveProcess
193 {- | Runs a raw command, and returns 'Handle's that may be used to communicate
194 with the process via its @stdin@, @stdout@ and @stderr@ respectively.
196 For example, to start a process and feed a string to its stdin:
198 > (in,out,err,pid) <- runInteractiveProcess "..."
199 > forkIO (hPutStr in str)
201 runInteractiveProcess
202 :: FilePath -- ^ Filename of the executable
203 -> [String] -- ^ Arguments to pass to the executable
204 -> Maybe FilePath -- ^ Optional path to the working directory
205 -> Maybe [(String,String)] -- ^ Optional environment (otherwise inherit)
206 -> IO (Handle,Handle,Handle,ProcessHandle)
208 #if !defined(mingw32_TARGET_OS) && !defined(__MINGW32__)
210 runInteractiveProcess cmd args mb_cwd mb_env =
211 runInteractiveProcess1 "runInteractiveProcess" cmd args mb_cwd mb_env
213 runInteractiveProcess1 fun cmd args mb_cwd mb_env = do
214 withFilePathException cmd $
215 alloca $ \ pfdStdInput ->
216 alloca $ \ pfdStdOutput ->
217 alloca $ \ pfdStdError ->
218 maybeWith withCEnvironment mb_env $ \pEnv ->
219 maybeWith withCString mb_cwd $ \pWorkDir ->
220 withMany withCString (cmd:args) $ \cstrs ->
221 withArray0 nullPtr cstrs $ \pargs -> do
222 proc_handle <- throwErrnoIfMinus1 fun
223 (c_runInteractiveProcess pargs pWorkDir pEnv
224 pfdStdInput pfdStdOutput pfdStdError)
225 hndStdInput <- fdToHandle pfdStdInput WriteMode
226 hndStdOutput <- fdToHandle pfdStdOutput ReadMode
227 hndStdError <- fdToHandle pfdStdError ReadMode
228 return (hndStdInput, hndStdOutput, hndStdError, ProcessHandle proc_handle)
230 foreign import ccall unsafe "runInteractiveProcess"
231 c_runInteractiveProcess
242 runInteractiveProcess cmd args mb_cwd mb_env =
243 runInteractiveProcess1 "runInteractiveProcess" cmd args mb_cwd mb_env ""
245 runInteractiveProcess1 fun cmd args workDir env extra_cmdline
246 = withFilePathException cmd $ do
247 let cmdline = translate cmd ++
248 concat (map ((' ':) . translate) args) ++
249 (if null extra_cmdline then "" else ' ':extra_cmdline)
250 withCString cmdline $ \pcmdline ->
251 alloca $ \ pfdStdInput ->
252 alloca $ \ pfdStdOutput ->
253 alloca $ \ pfdStdError -> do
254 maybeWith withCEnvironment env $ \pEnv -> do
255 maybeWith withCString workDir $ \pWorkDir -> do
256 proc_handle <- throwErrnoIfMinus1 fun $
257 c_runInteractiveProcess pcmdline pWorkDir pEnv
258 pfdStdInput pfdStdOutput pfdStdError
259 hndStdInput <- fdToHandle pfdStdInput WriteMode
260 hndStdOutput <- fdToHandle pfdStdOutput ReadMode
261 hndStdError <- fdToHandle pfdStdError ReadMode
262 return (hndStdInput, hndStdOutput, hndStdError,
263 ProcessHandle proc_handle)
265 foreign import ccall unsafe "runInteractiveProcess"
266 c_runInteractiveProcess
277 fdToHandle :: Ptr FD -> IOMode -> IO Handle
278 fdToHandle pfd mode = do
280 openFd fd (Just Stream)
281 #if __GLASGOW_HASKELL__ >= 603
282 False{-not a socket-}
284 ("fd:" ++ show fd) mode True{-binary-} False{-no truncate-}
286 -- ----------------------------------------------------------------------------
289 {- | Waits for the specified process to terminate, and returns its exit code.
291 GHC Note: in order to call waitForProcess without blocking all the
292 other threads in the system, you must compile the program with
298 waitForProcess (ProcessHandle handle) = do
299 code <- throwErrnoIfMinus1 "waitForProcess" (c_waitForProcess handle)
301 then return ExitSuccess
302 else return (ExitFailure (fromIntegral code))
304 -- ----------------------------------------------------------------------------
307 -- | Attempts to terminate the specified process. This function should
308 -- not be used under normal circumstances - no guarantees are given regarding
309 -- how cleanly the process is terminated. To check whether the process
310 -- has indeed terminated, use 'getProcessExitCode'.
312 -- On Unix systems, 'terminateProcess' sends the process the SIGKILL signal.
313 -- On Windows systems, the Win32 @TerminateProcess@ function is called, passing
314 -- an exit code of 1.
315 terminateProcess :: ProcessHandle -> IO ()
316 terminateProcess (ProcessHandle pid) =
317 throwErrnoIfMinus1_ "terminateProcess" (c_terminateProcess pid)
319 -- ----------------------------------------------------------------------------
320 -- getProcessExitCode
322 {- | Verifies whether the process is completed and if it is then returns the exit code.
323 If the process is still running the function returns Nothing
325 getProcessExitCode :: ProcessHandle -> IO (Maybe ExitCode)
326 getProcessExitCode (ProcessHandle handle) =
327 alloca $ \pExitCode -> do
328 res <- throwErrnoIfMinus1 "getProcessExitCode" (c_getProcessExitCode handle pExitCode)
329 code <- peek pExitCode
333 then return (Just ExitSuccess)
334 else return (Just (ExitFailure (fromIntegral code)))
336 -- ----------------------------------------------------------------------------
339 {- | Turns a shell command into a raw command. Usually this involves
340 wrapping it in an invocation of the shell.
342 There's a difference in the signature of commandToProcess between
343 the Windows and Unix versions. On Unix, exec takes a list of strings,
344 and we want to pass our command to /bin/sh as a single argument.
346 On Windows, CreateProcess takes a single string for the command,
347 which is later decomposed by cmd.exe. In this case, we just want
348 to prepend @\"c:\WINDOWS\CMD.EXE \/c\"@ to our command line. The
349 command-line translation that we normally do for arguments on
350 Windows isn't required (or desirable) here.
353 #if !defined(mingw32_TARGET_OS) && !defined(__MINGW32__)
357 -> IO (FilePath,[String])
358 commandToProcess string = return ("/bin/sh", ["-c", string])
364 -> IO (FilePath,String)
365 commandToProcess string = do
366 sysDir <- allocaBytes 1024 (\pdir -> c_getSystemDirectory pdir 1024 >> peekCString pdir)
367 return (sysDir ++ "\\CMD.EXE", "/c " ++ string)
368 -- We don't want to put the cmd into a single
369 -- argument, because cmd.exe will not try to split it up. Instead,
370 -- we just tack the command on the end of the cmd.exe command line,
371 -- which partly works. There seem to be some quoting issues, but
372 -- I don't have the energy to find+fix them right now (ToDo). --SDM
374 foreign import stdcall unsafe "GetSystemDirectoryA"
382 -- ----------------------------------------------------------------------------
385 withFilePathException :: FilePath -> IO a -> IO a
386 withFilePathException fpath act = handle mapEx act
388 mapEx (IOException (IOError h iot fun str _)) = ioError (IOError h iot fun str (Just fpath))
391 #if !defined(mingw32_TARGET_OS) && !defined(__MINGW32__)
392 withCEnvironment :: [(String,String)] -> (Ptr CString -> IO a) -> IO a
393 withCEnvironment env act =
394 let env' = map (\(name, val) -> name ++ ('=':val)) env
395 in withMany withCString env' (\pEnv -> withArray0 nullPtr pEnv act)
397 withCEnvironment :: [(String,String)] -> (Ptr () -> IO a) -> IO a
398 withCEnvironment env act =
399 let env' = foldr (\(name, val) env -> name ++ ('=':val)++'\0':env) "\0" env
400 in withCString env' (act . castPtr)
404 -- ----------------------------------------------------------------------------
405 -- Interface to C bits
407 foreign import ccall unsafe "terminateProcess"
412 foreign import ccall unsafe "getProcessExitCode"
418 foreign import ccall safe "waitForProcess" -- NB. safe - can block
423 -- ------------------------------------------------------------------------
424 -- Passing commands to the OS on Windows
427 On Windows this is tricky. We use CreateProcess, passing a single
428 command-line string (lpCommandLine) as its argument. (CreateProcess
429 is well documented on http://msdn.microsoft/com.)
431 - It parses the beginning of the string to find the command. If the
432 file name has embedded spaces, it must be quoted, using double
434 "foo\this that\cmd" arg1 arg2
436 - The invoked command can in turn access the entire lpCommandLine string,
437 and the C runtime does indeed do so, parsing it to generate the
438 traditional argument vector argv[0], argv[1], etc. It does this
439 using a complex and arcane set of rules which are described here:
441 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/progs_12.asp
443 (if this URL stops working, you might be able to find it by
444 searching for "Parsing C Command-Line Arguments" on MSDN. Also,
445 the code in the Microsoft C runtime that does this translation
446 is shipped with VC++).
448 Our goal in runProcess is to take a command filename and list of
449 arguments, and construct a string which inverts the translatsions
450 described above, such that the program at the other end sees exactly
451 the same arguments in its argv[] that we passed to rawSystem.
453 This inverse translation is implemented by 'translate' below.
455 Here are some pages that give informations on Windows-related
456 limitations and deviations from Unix conventions:
458 http://support.microsoft.com/default.aspx?scid=kb;en-us;830473
459 Command lines and environment variables effectively limited to 8191
460 characters on Win XP, 2047 on NT/2000 (probably even less on Win 9x):
462 http://www.microsoft.com/windowsxp/home/using/productdoc/en/default.asp?url=/WINDOWSXP/home/using/productdoc/en/percent.asp
463 Command-line substitution under Windows XP. IIRC these facilities (or at
464 least a large subset of them) are available on Win NT and 2000. Some
465 might be available on Win 9x.
467 http://www.microsoft.com/windowsxp/home/using/productdoc/en/default.asp?url=/WINDOWSXP/home/using/productdoc/en/Cmd.asp
468 How CMD.EXE processes command lines.
471 Note: CreateProcess does have a separate argument (lpApplicationName)
472 with which you can specify the command, but we have to slap the
473 command into lpCommandLine anyway, so that argv[0] is what a C program
474 expects (namely the application name). So it seems simpler to just
475 use lpCommandLine alone, which CreateProcess supports.
478 #if defined(mingw32_TARGET_OS)
480 -- Translate command-line arguments for passing to CreateProcess().
481 translate :: String -> String
482 translate str = '"' : snd (foldr escape (True,"\"") str)
483 where escape '"' (b, str) = (True, '\\' : '"' : str)
484 escape '\\' (True, str) = (True, '\\' : '\\' : str)
485 escape '\\' (False, str) = (False, '\\' : str)
486 escape c (b, str) = (False, c : str)
487 -- See long comment above for what this function is trying to do.
489 -- The Bool passed back along the string is True iff the
490 -- rest of the string is a sequence of backslashes followed by