System.Process (wa: RE: Subprocesses)
Simon Marlow
simonmar@microsoft.com
Tue, 13 May 2003 16:57:56 +0100
This is a multi-part message in MIME format.
------=_NextPart_000_00A7_01C31970.CF54AB50
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Thanks to all who responded about subprocesses. I've put together a proposal (attached) which I think does a reasonable job of
providing both flexibility and ease of use for the common cases. Please comment!
Rationale:
- Terminology: a "command" is run by the shell, whereas a "process"
is a raw filename and list of arguments. A command is turned into
a process by means of the system-specific commandToProcess eg. on
Unix this wraps it in "/bin/sh -c", but depending on the system it
might do nothing except split the command into words.
- The "command" versions are defined in terms of the "process" versions
in the obvious way.
- The "interactive" versions create pipes for stdin/stdout/stderr which
can be used to communicate with the process, whereas the non-interactive
versions will inherit the parent's stdin/stdout/stderr mappings.
- We still need a low-level runProcess which takes Handles for the
stdin/stdout/stderr of the sub-process, because this allows for
redirection. In conjuction with a separate createPipe, runProcess
can be used to build the popen-style interfaces (eg.
runInteractiveProcess), but by supplying these as functions in their
own right we can simplify the implementation by not creating and
immediately destroying redundant Handles produced by createPipe. This
should amount to a useful reduction in overhead for the interactive
variants.
- To send a string to the processes stdin without blocking, use:
(in,out,err,pid) <- runInteractiveProcess "..."
forkIO (hPutStr in str)
- Waiting for sub-processes to terminate and retrieving their
exit-codes is provided for; GHC's RTS will need some extra support
so that waitForProcess doesn't block other threads.
- If you want to change the working directory for the sub-process
(provided by the old runProcess abstraction), use runCommand with
"cd <dir>; ...".
Cheers,
Simon
------=_NextPart_000_00A7_01C31970.CF54AB50
Content-Type: text/html;
name="System.Process.html"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="System.Process.html"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" =
"http://www.w3.org/TR/html4/loose.dtd">=0A=
<!--Rendered using the Haskell Html Library v0.2-->=0A=
<HTML>=0A=
<style type=3D"text/css">=0A=
/* -------- Global things --------- */=0A=
=0A=
BODY { =0A=
background-color: #ffffff;=0A=
color: #000000;=0A=
font-family: sans-serif;=0A=
} =0A=
=0A=
A:link { color: #0000e0; text-decoration: none }=0A=
A:visited { color: #0000a0; text-decoration: none }=0A=
A:hover { background-color: #e0e0ff; text-decoration: none }=0A=
=0A=
TABLE.vanilla {=0A=
width: 100%;=0A=
border-width: 0px;=0A=
/* I can't seem to specify cellspacing or cellpadding properly using =
CSS... */=0A=
}=0A=
=0A=
TD {=0A=
border-width: 0px;=0A=
}=0A=
=0A=
TABLE.narrow {=0A=
border-width: 0px;=0A=
}=0A=
=0A=
TD.s8 { height: 8px; }=0A=
TD.s15 { height: 15px; }=0A=
=0A=
SPAN.keyword { text-decoration: underline; }=0A=
=0A=
/* --------- Documentation elements ---------- */=0A=
=0A=
TD.children {=0A=
padding-left: 25px;=0A=
}=0A=
=0A=
TD.synopsis {=0A=
padding: 2px;=0A=
background-color: #f0f0f0;=0A=
font-family: monospace=0A=
}=0A=
=0A=
TD.decl { =0A=
padding: 2px;=0A=
background-color: #f0f0f0; =0A=
font-family: monospace;=0A=
white-space: nowrap;=0A=
vertical-align: top;=0A=
}=0A=
=0A=
TD.recfield { padding-left: 20px }=0A=
=0A=
TD.doc { =0A=
padding-top: 2px;=0A=
padding-left: 10px;=0A=
}=0A=
=0A=
TD.ndoc { =0A=
padding: 2px;=0A=
}=0A=
=0A=
TD.rdoc { =0A=
padding: 2px;=0A=
padding-left: 10px;=0A=
width: 100%;=0A=
}=0A=
=0A=
TD.body { =0A=
padding-left: 10px=0A=
}=0A=
=0A=
/* ------- Section Headings ------- */=0A=
=0A=
TD.section1 {=0A=
padding-top: 15px;=0A=
font-weight: bold;=0A=
font-size: 150%=0A=
}=0A=
=0A=
TD.section2 {=0A=
padding-top: 10px;=0A=
font-weight: bold;=0A=
font-size: 130%=0A=
}=0A=
=0A=
TD.section3 {=0A=
padding-top: 5px;=0A=
font-weight: bold;=0A=
font-size: 110%=0A=
}=0A=
=0A=
TD.section4 {=0A=
font-weight: bold;=0A=
font-size: 100%=0A=
}=0A=
=0A=
/* -------------- The title bar at the top of the page */=0A=
=0A=
TD.infohead {=0A=
color: #ffffff;=0A=
font-weight: bold;=0A=
padding-right: 10px;=0A=
text-align: left;=0A=
}=0A=
=0A=
TD.infoval {=0A=
color: #ffffff;=0A=
padding-right: 10px;=0A=
text-align: left;=0A=
}=0A=
=0A=
TD.topbar {=0A=
background-color: #000099;=0A=
padding: 5px;=0A=
}=0A=
=0A=
TD.title {=0A=
color: #ffffff;=0A=
padding-left: 10px;=0A=
width: 100%=0A=
}=0A=
=0A=
TD.topbut {=0A=
padding-left: 5px;=0A=
padding-right: 5px;=0A=
border-left-width: 1px;=0A=
border-left-color: #ffffff;=0A=
border-left-style: solid;=0A=
white-space: nowrap;=0A=
}=0A=
=0A=
TD.topbut A:link {=0A=
color: #ffffff=0A=
}=0A=
=0A=
TD.topbut A:visited {=0A=
color: #ffff00=0A=
}=0A=
=0A=
TD.topbut A:hover {=0A=
background-color: #6060ff;=0A=
}=0A=
=0A=
TD.topbut:hover {=0A=
background-color: #6060ff=0A=
}=0A=
=0A=
TD.modulebar { =0A=
background-color: #0077dd;=0A=
padding: 5px;=0A=
border-top-width: 1px;=0A=
border-top-color: #ffffff;=0A=
border-top-style: solid;=0A=
}=0A=
=0A=
/* --------- The page footer --------- */=0A=
=0A=
TD.botbar {=0A=
background-color: #000099;=0A=
color: #ffffff;=0A=
padding: 5px=0A=
}=0A=
TD.botbar A:link {=0A=
color: #ffffff;=0A=
text-decoration: underline=0A=
}=0A=
TD.botbar A:visited {=0A=
color: #ffff00=0A=
}=0A=
TD.botbar A:hover {=0A=
background-color: #6060ff=0A=
}=0A=
</style>=0A=
<HEAD=0A=
><TITLE=0A=
>System.Process</TITLE=0A=
><LINK HREF =3D "haddock.css" REL =3D "stylesheet" TYPE =3D =
"text/css"=0A=
></HEAD=0A=
><BODY=0A=
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"=0A=
><TR=0A=
><TD CLASS =3D "topbar"=0A=
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"=0A=
><TR=0A=
><TD=0A=
><IMG SRC =3D "haskell_icon.gif" WIDTH =3D "16" HEIGHT =3D "16" =
ALT =3D " "=0A=
></TD=0A=
><TD CLASS =3D "title"=0A=
></TD=0A=
><TD CLASS =3D "topbut"=0A=
><A HREF =3D "System.html"=0A=
>Parent</A=0A=
></TD=0A=
><TD CLASS =3D "topbut"=0A=
><A HREF =3D "index.html"=0A=
>Contents</A=0A=
></TD=0A=
><TD CLASS =3D "topbut"=0A=
><A HREF =3D "doc-index.html"=0A=
>Index</A=0A=
></TD=0A=
></TR=0A=
></TABLE=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "modulebar"=0A=
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"=0A=
><TR=0A=
><TD=0A=
><FONT SIZE =3D "6"=0A=
>System.Process</FONT=0A=
></TD=0A=
><TD ALIGN =3D "right"=0A=
><TABLE CLASS =3D "narrow" CELLSPACING =3D "0" CELLPADDING =3D "0"=0A=
><TR=0A=
><TD CLASS =3D "infohead"=0A=
>Portability</TD=0A=
><TD CLASS =3D "infoval"=0A=
> portable</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "infohead"=0A=
>Stability</TD=0A=
><TD CLASS =3D "infoval"=0A=
> experimental</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "infohead"=0A=
>Maintainer</TD=0A=
><TD CLASS =3D "infoval"=0A=
> libraries@haskell.org</TD=0A=
></TR=0A=
></TABLE=0A=
></TD=0A=
></TR=0A=
></TABLE=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD=0A=
><TR=0A=
><TD CLASS =3D "section4"=0A=
><B=0A=
>Contents</B=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD=0A=
><DL=0A=
><DT=0A=
><A HREF =3D "#1"=0A=
> Running sub-processes</A=0A=
></DT=0A=
><DT=0A=
><A HREF =3D "#2"=0A=
> Waiting for process termination</A=0A=
></DT=0A=
><DT=0A=
><A HREF =3D "#3"=0A=
> Creating pipes</A=0A=
></DT=0A=
></DL=0A=
></TD=0A=
></TR=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "section1"=0A=
>Description</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "doc"=0A=
> Operations for creating and interacting with sub-processes.=0A=
</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "section1"=0A=
>Synopsis</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "body"=0A=
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D =
"0"=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><SPAN CLASS =3D "keyword"=0A=
>data</SPAN=0A=
> <A HREF =3D "#ProcessHandle"=0A=
>ProcessHandle</A=0A=
> </TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "body"=0A=
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"=0A=
></TABLE=0A=
></TD=0A=
></TR=0A=
></TABLE=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s8"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A HREF =3D "#runCommand"=0A=
>runCommand</A=0A=
> :: String -> IO <A HREF =3D "System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s8"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A HREF =3D "#runProcess"=0A=
>runProcess</A=0A=
> :: FilePath -> [String] -> Maybe [(String, String)] -> =
Maybe Handle -> Maybe Handle -> Maybe Handle -> IO <A HREF =3D =
"System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s8"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A HREF =3D "#runInteractiveCommand"=0A=
>runInteractiveCommand</A=0A=
> :: String -> IO (Handle, Handle, Handle, <A HREF =3D =
"System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
>)</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s8"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A HREF =3D "#runInteractiveProcess"=0A=
>runInteractiveProcess</A=0A=
> :: FilePath -> [String] -> Maybe [(String, String)] -> IO =
(Handle, Handle, Handle, <A HREF =3D "System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
>)</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s8"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A HREF =3D "#commandToProcess"=0A=
>commandToProcess</A=0A=
> :: String -> (FilePath, [String])</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s8"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A HREF =3D "#waitForProcess"=0A=
>waitForProcess</A=0A=
> :: <A HREF =3D "System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
> -> IO ExitCode</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s8"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A HREF =3D "#createPipe"=0A=
>createPipe</A=0A=
> :: IO (Handle, Handle)</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s8"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A HREF =3D "#createPipeEx"=0A=
>createPipeEx</A=0A=
> :: IOModeEx -> IO (Handle, Handle)</TD=0A=
></TR=0A=
></TABLE=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "section1"=0A=
><A NAME =3D "1"=0A=
> Running sub-processes</A=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><SPAN CLASS =3D "keyword"=0A=
>data</SPAN=0A=
> <A NAME =3D "ProcessHandle"=0A=
></A=0A=
><B=0A=
>ProcessHandle</B=0A=
> </TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "body"=0A=
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"=0A=
><TR=0A=
><TD CLASS =3D "ndoc"=0A=
><P=0A=
> A handle to a process, which can be used to wait for termination=0A=
of the process using <TT=0A=
><A HREF =3D "System.Process.html#waitForProcess"=0A=
>waitForProcess</A=0A=
></TT=0A=
>.</P=0A=
><P=0A=
> None of the process-creation functions in this library wait for=0A=
termination: they all return a <TT=0A=
><A HREF =3D "System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
></TT=0A=
> which may be used=0A=
to wait for the process later.=0A=
</P=0A=
></TD=0A=
></TR=0A=
></TABLE=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A NAME =3D "runCommand"=0A=
></A=0A=
><B=0A=
>runCommand</B=0A=
> :: String -> IO <A HREF =3D "System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "doc"=0A=
> Runs a command using the shell.=0A=
</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A NAME =3D "runProcess"=0A=
></A=0A=
><B=0A=
>runProcess</B=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "body"=0A=
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>:: FilePath</TD=0A=
><TD CLASS =3D "rdoc"=0A=
> Filename of the executable</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>-> [String]</TD=0A=
><TD CLASS =3D "rdoc"=0A=
> Arguments to pass to the executable</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>-> Maybe [(String, String)]</TD=0A=
><TD CLASS =3D "rdoc"=0A=
> Optional environment (otherwise inherit)</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>-> Maybe Handle</TD=0A=
><TD CLASS =3D "rdoc"=0A=
> Handle to use for <TT=0A=
>stdin</TT=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>-> Maybe Handle</TD=0A=
><TD CLASS =3D "rdoc"=0A=
> Handle to use for <TT=0A=
>stdout</TT=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>-> Maybe Handle</TD=0A=
><TD CLASS =3D "rdoc"=0A=
> Handle to use for <TT=0A=
>stderr</TT=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>-> IO <A HREF =3D "System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
></TD=0A=
><TD CLASS =3D "rdoc"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "ndoc" COLSPAN =3D "2"=0A=
><P=0A=
> Runs a raw command, optionally specifying Handles from which to=0A=
take the <TT=0A=
>stdin</TT=0A=
>, <TT=0A=
>stdout</TT=0A=
> and <TT=0A=
>stderr</TT=0A=
> channels for the new=0A=
process.</P=0A=
><P=0A=
> These Handles may be created by <TT=0A=
><A HREF =3D "System.Process.html#createPipe"=0A=
>createPipe</A=0A=
></TT=0A=
>, in order to set=0A=
up communication channels with the remote process (but see also=0A=
<TT=0A=
><A HREF =3D "System.Process.html#runInteractiveProcess"=0A=
>runInteractiveProcess</A=0A=
></TT=0A=
> if you want to do this).=0A=
</P=0A=
></TD=0A=
></TR=0A=
></TABLE=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A NAME =3D "runInteractiveCommand"=0A=
></A=0A=
><B=0A=
>runInteractiveCommand</B=0A=
> :: String -> IO (Handle, Handle, Handle, <A HREF =3D =
"System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
>)</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "doc"=0A=
> Runs a command using the shell, and returns Handles that may=0A=
be used to communicate with the process via its <TT=0A=
>stdin</TT=0A=
>, <TT=0A=
>stdout</TT=0A=
>,=0A=
and <TT=0A=
>stderr</TT=0A=
> respectively.=0A=
</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A NAME =3D "runInteractiveProcess"=0A=
></A=0A=
><B=0A=
>runInteractiveProcess</B=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "body"=0A=
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>:: FilePath</TD=0A=
><TD CLASS =3D "rdoc"=0A=
> Filename of the executable</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>-> [String]</TD=0A=
><TD CLASS =3D "rdoc"=0A=
> Arguments to pass to the executable</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>-> Maybe [(String, String)]</TD=0A=
><TD CLASS =3D "rdoc"=0A=
> Optional environment (otherwise inherit)</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
>-> IO (Handle, Handle, Handle, <A HREF =3D =
"System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
>)</TD=0A=
><TD CLASS =3D "rdoc"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "ndoc" COLSPAN =3D "2"=0A=
><P=0A=
> Runs a raw command, and returns Handles that may be used to =
communicate=0A=
with the process via its <TT=0A=
>stdin</TT=0A=
>, <TT=0A=
>stdout</TT=0A=
> and <TT=0A=
>stderr</TT=0A=
> respectively.</P=0A=
><P=0A=
> <TT=0A=
><A HREF =3D "System.Process.html#runInteractiveProcess"=0A=
>runInteractiveProcess</A=0A=
></TT=0A=
> can be implemented in terms of=0A=
<TT=0A=
><A HREF =3D "System.Process.html#runProcess"=0A=
>runProcess</A=0A=
></TT=0A=
> and <TT=0A=
><A HREF =3D "System.Process.html#createPipe"=0A=
>createPipe</A=0A=
></TT=0A=
>, but it is recommended that you use=0A=
<TT=0A=
><A HREF =3D "System.Process.html#runInteractiveCommand"=0A=
>runInteractiveCommand</A=0A=
></TT=0A=
> directly if possible since it is likely=0A=
to be more efficient than combining the lower-level operations.=0A=
</P=0A=
></TD=0A=
></TR=0A=
></TABLE=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A NAME =3D "commandToProcess"=0A=
></A=0A=
><B=0A=
>commandToProcess</B=0A=
> :: String -> (FilePath, [String])</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "doc"=0A=
> Turns a shell command into a raw command. Usually this involves=0A=
wrapping it in an invocation of the shell.=0A=
</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "section1"=0A=
><A NAME =3D "2"=0A=
> Waiting for process termination</A=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A NAME =3D "waitForProcess"=0A=
></A=0A=
><B=0A=
>waitForProcess</B=0A=
> :: <A HREF =3D "System.Process.html#ProcessHandle"=0A=
>ProcessHandle</A=0A=
> -> IO ExitCode</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "doc"=0A=
> Waits for the specified process to terminate, and returns its exit =
code.=0A=
</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "section1"=0A=
><A NAME =3D "3"=0A=
> Creating pipes</A=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A NAME =3D "createPipe"=0A=
></A=0A=
><B=0A=
>createPipe</B=0A=
> :: IO (Handle, Handle)</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "doc"=0A=
><P=0A=
>Creates an anonymous <EM=0A=
>pipe</EM=0A=
> and returns a pair of =0A=
handles, the first for reading and the second for writing. Both=0A=
pipe ends can be inherited by a child process.</P=0A=
><PRE=0A=
> createPipe =3D createPipeEx (BinaryMode AppendMode) =0A=
</PRE=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "decl"=0A=
><A NAME =3D "createPipeEx"=0A=
></A=0A=
><B=0A=
>createPipeEx</B=0A=
> :: IOModeEx -> IO (Handle, Handle)</TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "doc"=0A=
><P=0A=
> =0A=
(<TT=0A=
>createPipeEx modeEx</TT=0A=
>) creates an anonymous <EM=0A=
>pipe</EM=0A=
> and returns a pair of =0A=
handles, the first for reading and the second for writing. =0A=
The pipe mode <TT=0A=
>modeEx</TT=0A=
> can be:</P=0A=
><UL=0A=
><LI=0A=
><P=0A=
> <TT=0A=
>TextMode mode</TT=0A=
> -- the pipe is opened in text mode.</P=0A=
></LI=0A=
><LI=0A=
><P=0A=
> <TT=0A=
>BinaryMode mode</TT=0A=
> -- the pipe is opened in binary mode.</P=0A=
></LI=0A=
></UL=0A=
><P=0A=
>The <TT=0A=
>mode</TT=0A=
> determines if child processes can inherit the pipe handles:</P=0A=
><UL=0A=
><LI=0A=
><P=0A=
> ReadMode -- The <EM=0A=
>read</EM=0A=
> handle of the pipe is private to this process. </P=0A=
></LI=0A=
><LI=0A=
><P=0A=
> WriteMode -- The <EM=0A=
>write</EM=0A=
> handle of the pipe is private to this process. </P=0A=
></LI=0A=
><LI=0A=
><P=0A=
> ReadWriteMode -- Both handles are private to this process.</P=0A=
></LI=0A=
><LI=0A=
><P=0A=
> AppendMode -- Both handles are available (inheritable) to child =
processes.=0A=
This mode can be used to <EM=0A=
>append</EM=0A=
> (|) two seperate child processes.</P=0A=
></LI=0A=
></UL=0A=
><P=0A=
>If a broken pipe is read, an end-of-file (<TT=0A=
><A HREF =3D "GHC.IOBase.html#EOF"=0A=
>EOF</A=0A=
></TT=0A=
>) =0A=
exception is raised. If a broken pipe is written to, an invalid argument =
exception=0A=
is raised (<TT=0A=
><A HREF =3D "GHC.IOBase.html#InvalidArgument"=0A=
>InvalidArgument</A=0A=
></TT=0A=
>).=0A=
</P=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "s15"=0A=
></TD=0A=
></TR=0A=
><TR=0A=
><TD CLASS =3D "botbar"=0A=
>Produced by <A HREF =3D "http://www.haskell.org/haddock"=0A=
>Haddock</A=0A=
> version 0.4</TD=0A=
></TR=0A=
></TABLE=0A=
></BODY=0A=
></HTML=0A=
>=0A=
------=_NextPart_000_00A7_01C31970.CF54AB50--