Subprocesses (was: [ANNOUNCE] shell-haskell 1.0.0)
Daan Leijen
daan@cs.uu.nl
Fri, 9 May 2003 12:51:56 +0200
This is a multi-part message in MIME format.
------=_NextPart_000_00B0_01C31629.C5998A30
Content-Type: multipart/alternative;
boundary="----=_NextPart_001_00B1_01C31629.C59B10D0"
------=_NextPart_001_00B1_01C31629.C59B10D0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Sigh, I just realised you need to have the stylesheet
to see the documentation properly --- so here is a new
version with the style sheet inlined.
-- Daan.
----- Original Message -----=20
From: Daan Leijen=20
To: Simon Marlow ; libraries@haskell.org=20
Sent: Friday, May 09, 2003 12:45 PM
Subject: Re: Subprocesses (was: [ANNOUNCE] shell-haskell 1.0.0)
Hi all,
I have implemented a generalised library for communicating with child =
processes some
time ago for windows (but it is easy to implement for unix's too). I =
believe that
the interface encompasses all current mechanism around (system, =
runProcess, popen, launch).
Basically, it allows one to create pipes in Haskell that can be read =
and written just like
normal file "Handle"s. Furthermore, you can start a child process that =
can get its stdin, stdout,
and stderr redirected to one of those pipes. This "runProcess" call is =
basically the same to
"Posix.runProcess".
I have attached the documentation and description of the functions to =
this mail in HTML format.
It also contains an example of a "spawn" function that closely =
resemebles the "launch" function
of shell-haskell.
I think that this interface is a good starting point for a discussion =
on the final library interface
for sub-processes.
All the best,
Daan.
----- Original Message -----
From: "Simon Marlow" <simonmar@microsoft.com>
To: <libraries@haskell.org>
Sent: Friday, May 09, 2003 12:03 PM
Subject: Subprocesses (was: [ANNOUNCE] shell-haskell 1.0.0)
> Libraries people,
>
> There are currently two ways to create and communicate with external
> processes:
>
> - System.Cmd.system (very basic, doesn't give you access to the
> process's output but you can use shell primitives to redirect =
its
> input/output).
>
> - Posix.runProcess (can specify Handles for the process's
> input/output,
> but it doesn't create pipes so you can't actually communicate =
with
> the subprocess using these Handles.).
>
> - POpen.popen (can specify an input String, and gives you lazy =
output
> Strings. No interactive communication is possible.)
>
> Ok, *three* ways. System.Cmd.system, Posix.runProcess, POpen.popen, =
and
> shell-haskell. Er. *Four* ways.
>
> David Sankel's shell-haskell creates pipes for stdin/stdout/stderr, =
and
> lets you communicate interactively with the sub-process via Handles. =
It
> could do with a way to specify the environment and working directory =
of
> the sub-process (ala POpen and runProcess), but apart from that it =
seems
> to be the most flexible of the four. It could be simplified =
slightly by
> using one Handle rather than two for stdin/stdout.
>
> We should think about what functionality we want to provide in the =
core
> libraries. My preference would be to go for a full version with =
three
> pipes (like shell-haskell) and perhaps one or two more specialised
> versions covering common cases (I don't know what these should be,
> though).
>
> What do people think?
>
> Cheers,
> Simon
>
> -----Original Message-----
> From: haskell-admin@haskell.org [mailto:haskell-admin@haskell.org] =
On
> Behalf Of David Sankel
> Sent: 06 May 2003 03:06
> To: haskell@haskell.org
> Subject: [ANNOUNCE] shell-haskell 1.0.0
>
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> shell-haskell 1.0.0
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>
> shell-haskell provides utilities to communicate with
> other process's via Haskell code. This library can be
> used for something as simple as getting the output of
> another program or as complex as interacting with an
> interpreter.
>
> see
>
> http://www.electronconsulting.com/shell-haskell
>
> for details.
>
> David J. Sankel
> _______________________________________________
> Haskell mailing list
> Haskell@haskell.org
> http://www.haskell.org/mailman/listinfo/haskell
>
>
> _______________________________________________
> Libraries mailing list
> Libraries@haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
>
>
>
------=_NextPart_001_00B1_01C31629.C59B10D0
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2713.1100" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DArial size=3D2>Sigh, I just realised you need to have =
the=20
stylesheet</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>to see the documentation properly --- =
so here is a=20
new</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>version with the style sheet =
inlined.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
<DIV><FONT face=3DArial size=3D2>-- Daan.</FONT></DIV>
<BLOCKQUOTE=20
style=3D"PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; =
BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">
<DIV style=3D"FONT: 10pt arial">----- Original Message ----- </DIV>
<DIV=20
style=3D"BACKGROUND: #e4e4e4; FONT: 10pt arial; font-color: =
black"><B>From:</B>=20
<A title=3Ddaan@cs.uu.nl href=3D"mailto:daan@cs.uu.nl">Daan Leijen</A> =
</DIV>
<DIV style=3D"FONT: 10pt arial"><B>To:</B> <A =
title=3Dsimonmar@microsoft.com=20
href=3D"mailto:simonmar@microsoft.com">Simon Marlow</A> ; <A=20
title=3Dlibraries@haskell.org=20
href=3D"mailto:libraries@haskell.org">libraries@haskell.org</A> </DIV>
<DIV style=3D"FONT: 10pt arial"><B>Sent:</B> Friday, May 09, 2003 =
12:45 PM</DIV>
<DIV style=3D"FONT: 10pt arial"><B>Subject:</B> Re: Subprocesses (was: =
[ANNOUNCE] shell-haskell 1.0.0)</DIV>
<DIV><BR></DIV>Hi all,<BR><BR>I have implemented a generalised library =
for=20
communicating with child processes some<BR>time ago for windows (but =
it is=20
easy to implement for unix's too). I believe that<BR>the =
interface=20
encompasses all current mechanism around (system, runProcess, =
popen,=20
launch).<BR><BR>Basically, it allows one to create pipes in Haskell =
that can=20
be read and written just like<BR>normal file "Handle"s. Furthermore, =
you can=20
start a child process that can get its stdin, stdout,<BR>and stderr =
redirected=20
to one of those pipes. This "runProcess" call is basically the same=20
to<BR>"Posix.runProcess".<BR><BR>I have attached the documentation and =
description of the functions to this mail in HTML format.<BR>It also =
contains=20
an example of a "spawn" function that closely resemebles the "launch"=20
function<BR>of shell-haskell.<BR><BR>I think that this interface is a =
good=20
starting point for a discussion on the final library interface<BR>for=20
sub-processes.<BR><BR>All the best,<BR> Daan.<BR><BR><BR>----- =
Original=20
Message -----<BR>From: "Simon Marlow" =
<simonmar@microsoft.com><BR>To:=20
<libraries@haskell.org><BR>Sent: Friday, May 09, 2003 12:03=20
PM<BR>Subject: Subprocesses (was: [ANNOUNCE] shell-haskell=20
1.0.0)<BR><BR><BR>> Libraries people,<BR>><BR>> There are =
currently=20
two ways to create and communicate with external<BR>>=20
processes:<BR>><BR>> - System.Cmd.system (very =
basic,=20
doesn't give you access to the<BR>> =
process's=20
output but you can use shell primitives to redirect=20
its<BR>> =
input/output).<BR>><BR>> =20
- Posix.runProcess (can specify Handles for the process's<BR>>=20
input/output,<BR>> but it doesn't create =
pipes so=20
you can't actually communicate with<BR>> =
the=20
subprocess using these Handles.).<BR>><BR>> - =
POpen.popen=20
(can specify an input String, and gives you lazy=20
output<BR>> Strings. No interactive=20
communication is possible.)<BR>><BR>> Ok, *three* ways. =20
System.Cmd.system, Posix.runProcess, POpen.popen, and<BR>>=20
shell-haskell. Er. *Four* ways.<BR>><BR>> David =
Sankel's=20
shell-haskell creates pipes for stdin/stdout/stderr, and<BR>> lets =
you=20
communicate interactively with the sub-process via Handles. =
It<BR>>=20
could do with a way to specify the environment and working directory=20
of<BR>> the sub-process (ala POpen and runProcess), but apart from =
that it=20
seems<BR>> to be the most flexible of the four. It could be=20
simplified slightly by<BR>> using one Handle rather than two for=20
stdin/stdout.<BR>><BR>> We should think about what functionality =
we want=20
to provide in the core<BR>> libraries. My preference would be =
to go=20
for a full version with three<BR>> pipes (like shell-haskell) and =
perhaps=20
one or two more specialised<BR>> versions covering common cases (I =
don't=20
know what these should be,<BR>> though).<BR>><BR>> What do =
people=20
think?<BR>><BR>> Cheers,<BR>> Simon<BR>><BR>> =
-----Original=20
Message-----<BR>> From: haskell-admin@haskell.org=20
[mailto:haskell-admin@haskell.org] On<BR>> Behalf Of David =
Sankel<BR>>=20
Sent: 06 May 2003 03:06<BR>> To: haskell@haskell.org<BR>> =
Subject:=20
[ANNOUNCE] shell-haskell 1.0.0<BR>><BR>> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<BR>>=20
shell-haskell 1.0.0<BR>> =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<BR>><BR>>=
=20
shell-haskell provides utilities to communicate with<BR>> other =
process's=20
via Haskell code. This library can be<BR>> used for something =
as=20
simple as getting the output of<BR>> another program or as complex =
as=20
interacting with an<BR>> interpreter.<BR>><BR>>=20
see<BR>><BR>> =20
http://www.electronconsulting.com/shell-haskell<BR>><BR>> for=20
details.<BR>><BR>> David J. Sankel<BR>>=20
_______________________________________________<BR>> Haskell =
mailing=20
list<BR>> Haskell@haskell.org<BR>>=20
=
http://www.haskell.org/mailman/listinfo/haskell<BR>><BR>><BR>>=20
_______________________________________________<BR>> Libraries =
mailing=20
list<BR>> Libraries@haskell.org<BR>>=20
=
http://www.haskell.org/mailman/listinfo/libraries<BR>><BR>><BR>>=
<BR></BLOCKQUOTE></BODY></HTML>
------=_NextPart_001_00B1_01C31629.C59B10D0--
------=_NextPart_000_00B0_01C31629.C5998A30
Content-Type: text/html;
name="RunProcess.html"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="RunProcess.html"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" =
"http://www.w3.org/TR/html4/loose.dtd">
<!--Rendered using the Haskell Html Library v0.2-->
<HTML
><HEAD
><TITLE
>RunProcess</TITLE
>
<style type=3D"text/css">
TT { font-size: 100% }
LI P { margin: 0pt }
/* -------- Global things --------- */
BODY {=20
background-color: #ffffff;
color: #000000;
font-family: sans-serif;
}=20
A:link { color: #0000e0; text-decoration: none }
A:visited { color: #0000a0; text-decoration: none }
A:hover { background-color: #e0e0ff; text-decoration: none }
TABLE.vanilla {
width: 100%;
border-width: 0px;
/* I can't seem to specify cellspacing or cellpadding properly using =
CSS... */
}
TD {
border-width: 0px;
}
TABLE.narrow {
border-width: 0px;
}
TD.s8 { height: 8px; }
TD.s15 { height: 15px; }
SPAN.keyword { text-decoration: underline; }
/* --------- Documentation elements ---------- */
TD.children {
padding-left: 25px;
}
TD.synopsis {
padding: 2px;
background-color: #f0f0f0;
font-family: monospace
}
TD.decl {=20
padding: 2px;
background-color: #f0f0f0;=20
font-family: monospace;
white-space: nowrap;
vertical-align: top;
}
TD.recfield { padding-left: 20px }
TD.doc {=20
padding-top: 2px;
padding-left: 10px;
}
TD.ndoc {=20
padding: 2px;
}
TD.rdoc {=20
padding: 2px;
padding-left: 10px;
width: 100%;
}
TD.body {=20
padding-left: 10px
}
/* ------- Section Headings ------- */
TD.section1 {
padding-top: 15px;
font-weight: bold;
font-size: 150%
}
TD.section2 {
padding-top: 10px;
font-weight: bold;
font-size: 130%
}
TD.section3 {
padding-top: 5px;
font-weight: bold;
font-size: 110%
}
TD.section4 {
font-weight: bold;
font-size: 100%
}
/* -------------- The title bar at the top of the page */
TD.infohead {
color: #ffffff;
font-weight: bold;
padding-right: 10px;
text-align: left;
}
TD.infoval {
color: #ffffff;
padding-right: 10px;
text-align: left;
}
TD.topbar {
background-color: #000099;
padding: 5px;
}
TD.title {
color: #ffffff;
padding-left: 10px;
width: 100%
}
TD.topbut {
padding-left: 5px;
padding-right: 5px;
border-left-width: 1px;
border-left-color: #ffffff;
border-left-style: solid;
white-space: nowrap;
}
TD.topbut A:link {
color: #ffffff
}
TD.topbut A:visited {
color: #ffff00
}
TD.topbut A:hover {
background-color: #6060ff;
}
TD.topbut:hover {
background-color: #6060ff
}
TD.modulebar {=20
background-color: #0077dd;
padding: 5px;
border-top-width: 1px;
border-top-color: #ffffff;
border-top-style: solid;
}
/* --------- The page footer --------- */
TD.botbar {
background-color: #000099;
color: #ffffff;
padding: 5px
}
TD.botbar A:link {
color: #ffffff;
text-decoration: underline
}
TD.botbar A:visited {
color: #ffff00
}
TD.botbar A:hover {
background-color: #6060ff
}
</style>
</HEAD
><BODY
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"
><TR
><TD CLASS =3D "topbar"
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"
><TR
><TD
><IMG SRC =3D "haskell_icon.gif" WIDTH =3D "16" HEIGHT =3D "16" =
ALT =3D " "
></TD
><TD CLASS =3D "title"
></TD
><TD CLASS =3D "topbut"
><A HREF =3D "index.html"
>Contents</A
></TD
><TD CLASS =3D "topbut"
><A HREF =3D "doc-index.html"
>Index</A
></TD
></TR
></TABLE
></TD
></TR
><TR
><TD CLASS =3D "modulebar"
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"
><TR
><TD
><FONT SIZE =3D "6"
>Win32RunProcess</FONT
></TD
><TD ALIGN =3D "right"
><TABLE CLASS =3D "narrow" CELLSPACING =3D "0" CELLPADDING =3D =
"0"
><TR
><TD CLASS =3D "infohead"
>Portability</TD
><TD CLASS =3D "infoval"
> win32</TD
></TR
><TR
><TD CLASS =3D "infohead"
>Stability</TD
><TD CLASS =3D "infoval"
> provisional</TD
></TR
><TR
><TD CLASS =3D "infohead"
>Maintainer</TD
><TD CLASS =3D "infoval"
> daan@cs.uu.nl</TD
></TR
></TABLE
></TD
></TR
></TABLE
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD
><TR
><TD CLASS =3D "section4"
><B
>Contents</B
></TD
></TR
><TR
><TD
><DL
><DT
><A HREF =3D "#1"
> Process control</A
></DT
><DT
><A HREF =3D "#2"
> Pipes</A
></DT
><DT
><A HREF =3D "#3"
> Data types (<TT
>IOModeEx</TT
>) </A
></DT
></DL
></TD
></TR
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "section1"
>Description</TD
></TR
><TR
><TD CLASS =3D "doc"
> High level primitives for process spawning on windows.
</TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "section1"
>Synopsis</TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "body"
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"
><TR
><TD CLASS =3D "decl"
><A HREF =3D "#runProcess"
>runProcess</A
> :: FilePath -> [String] -> Maybe [(String, String)] -> =
Maybe FilePath -> Maybe Handle -> Maybe Handle -> Maybe Handle =
-> IO ()</TD
></TR
><TR
><TD CLASS =3D "s8"
></TD
></TR
><TR
><TD CLASS =3D "decl"
><A HREF =3D "#runProcessEx"
>runProcessEx</A
> :: Bool -> FilePath -> [String] -> Maybe [(String, String)] =
-> Maybe FilePath -> Maybe Handle -> Maybe Handle -> Maybe =
Handle -> IO Int</TD
></TR
><TR
><TD CLASS =3D "s8"
></TD
></TR
><TR
><TD CLASS =3D "decl"
><A HREF =3D "#createPipe"
>createPipe</A
> :: IO (Handle, Handle)</TD
></TR
><TR
><TD CLASS =3D "s8"
></TD
></TR
><TR
><TD CLASS =3D "decl"
><A HREF =3D "#createPipeEx"
>createPipeEx</A
> :: IOModeEx -> IO (Handle, Handle)</TD
></TR
></TABLE
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "section1"
><A NAME =3D "1"
> Process control</A
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "decl"
><A NAME =3D "runProcess"
></A
><B
>runProcess</B
></TD
></TR
><TR
><TD CLASS =3D "body"
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"
><TR
><TD CLASS =3D "decl"
>:: FilePath</TD
><TD CLASS =3D "rdoc"
> Command</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> [String]</TD
><TD CLASS =3D "rdoc"
> Arguments</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> Maybe [(String, String)]</TD
><TD CLASS =3D "rdoc"
> Environment (Nothing -> Inherited)</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> Maybe FilePath</TD
><TD CLASS =3D "rdoc"
> Working directory (Nothing -> inherited)</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> Maybe Handle</TD
><TD CLASS =3D "rdoc"
> stdin (Nothing -> inherited)</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> Maybe Handle</TD
><TD CLASS =3D "rdoc"
> stdout (Nothing -> inherited)</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> Maybe Handle</TD
><TD CLASS =3D "rdoc"
> stderr (Nothing -> inherited)</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> IO ()</TD
><TD CLASS =3D "rdoc"
></TD
></TR
><TR
><TD CLASS =3D "ndoc" COLSPAN =3D "2"
><P
>(<TT
>runProcess cmd args env workdir in out err</TT
>) runs a command <TT
>cmd</TT
>. It searches
the application along the current directory, the windows system =
directories and=20
finally the current PATH. The command is run with the arguments <TT
>args</TT
>. The
child process runs concurrently with the parent process and a call to =
<TT
>runProcess</TT
>
returns immediately.</P
><P
>If the environment <TT
>env</TT
> is (<TT
>Just pairs</TT
>),=20
the command is executed with the environment specified by pairs of =
variables and values; otherwise,=20
the command is executed with the current environment. </P
><P
>If <TT
>workdir</TT
> is (<TT
>Just dir</TT
>), the command is executed=20
with working directory <TT
>dir</TT
> and otherwise, the command is executed in the current working =
directory. </P
><P
>If {<TT
>in</TT
>,<TT
>out</TT
>,<TT
>err</TT
>} is (<TT
>Just handle</TT
>), the command is executed with=20
<TT
>std</TT
>{<TT
>in</TT
>,<TT
>out</TT
>,<TT
>err</TT
>} attached to the specified handle;=20
otherwise, <TT
>std</TT
>{<TT
>in</TT
>,<TT
>out</TT
>,<TT
>err</TT
>} is left unchanged.</P
><PRE
> runProcess =3D runProcessEx False
</PRE
></TD
></TR
></TABLE
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "decl"
><A NAME =3D "runProcessEx"
></A
><B
>runProcessEx</B
></TD
></TR
><TR
><TD CLASS =3D "body"
><TABLE CLASS =3D "vanilla" CELLSPACING =3D "0" CELLPADDING =3D "0"
><TR
><TD CLASS =3D "decl"
>:: Bool</TD
><TD CLASS =3D "rdoc"
> Wait for termination? </TD
></TR
><TR
><TD CLASS =3D "decl"
>-> FilePath</TD
><TD CLASS =3D "rdoc"
> Command</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> [String]</TD
><TD CLASS =3D "rdoc"
> Arguments</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> Maybe [(String, String)]</TD
><TD CLASS =3D "rdoc"
> Environment (Nothing -> Inherited)</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> Maybe FilePath</TD
><TD CLASS =3D "rdoc"
> Working directory (Nothing -> inherited)</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> Maybe Handle</TD
><TD CLASS =3D "rdoc"
> stdin (Nothing -> inherited)</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> Maybe Handle</TD
><TD CLASS =3D "rdoc"
> stdout (Nothing -> inherited)</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> Maybe Handle</TD
><TD CLASS =3D "rdoc"
> stderr (Nothing -> inherited)</TD
></TR
><TR
><TD CLASS =3D "decl"
>-> IO Int</TD
><TD CLASS =3D "rdoc"
> The exit code (or 0 if wait is False)</TD
></TR
><TR
><TD CLASS =3D "ndoc" COLSPAN =3D "2"
><P
>(<TT
>runProcessEx wait cmd args env workdir in out err</TT
>) runs a command <TT
>cmd</TT
>.
It searches the application along the=20
current directory, the windows system directories and finally the =
current PATH.
The command is run with the arguments <TT
>args</TT
>. If <TT
>wait</TT
> is True, the current
process is suspended until the child terminates, otherwise they are run =
concurrently.</P
><P
>If the environment <TT
>env</TT
> is (<TT
>Just pairs</TT
>),=20
the command is executed with the environment specified by pairs of =
variables and values; otherwise,=20
the command is executed with the current environment. </P
><P
>If <TT
>workdir</TT
> is (<TT
>Just dir</TT
>), the command is executed=20
with working directory <TT
>dir</TT
> and otherwise, the command is executed in the current working =
directory. </P
><P
>If {<TT
>in</TT
>,<TT
>out</TT
>,<TT
>err</TT
>} is (<TT
>Just handle</TT
>), the command is executed with=20
<TT
>std</TT
>{<TT
>in</TT
>,<TT
>out</TT
>,<TT
>err</TT
>} attached to the specified handle;=20
otherwise, <TT
>std</TT
>{<TT
>in</TT
>,<TT
>out</TT
>,<TT
>err</TT
>} is left unchanged.</P
><P
>If <TT
>wait</TT
> is True, the call to <TT
><A HREF =3D "Win32RunProcess.html#runProcessEx"
>runProcessEx</A
></TT
> returns after the child process
has terminated with the exit code of the process. If <TT
>wait</TT
> is false, the
call to <TT
><A HREF =3D "Win32RunProcess.html#runProcessEx"
>runProcessEx</A
></TT
> returns immediately with an exit code of 0.</P
><P
>Here is a short example of running a command <TT
>cmd</TT
> that gets its input
from a file <TT
>foo</TT
>. The process is run synchronously.</P
><PRE
> do{ input <- openFile "foo" ReadMode
; exitcode <- runProcessEx True "cmd" [] Nothing =
Nothing (Just input) Nothing Nothing
; hClose input
; ...
</PRE
></TD
></TR
></TABLE
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "section1"
><A NAME =3D "2"
> Pipes</A
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "decl"
><A NAME =3D "createPipe"
></A
><B
>createPipe</B
> :: IO (Handle, Handle)</TD
></TR
><TR
><TD CLASS =3D "doc"
><P
>=20
(<TT
>createPipe</TT
>) creates an anonymous <EM
>pipe</EM
> and returns a pair of=20
handles, the first for reading and the second for writing. Both
pipe ends can be inherited by a child process.</P
><PRE
> createPipe =3D createPipeEx (BinaryMode AppendMode) =20
</PRE
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "decl"
><A NAME =3D "createPipeEx"
></A
><B
>createPipeEx</B
> :: IOModeEx -> IO (Handle, Handle)</TD
></TR
><TR
><TD CLASS =3D "doc"
><P
>=20
(<TT
>createPipeEx modeEx</TT
>) creates an anonymous <EM
>pipe</EM
> and returns a pair of=20
handles, the first for reading and the second for writing.=20
The pipe mode <TT
>modeEx</TT
> can be:</P
><UL
><LI
><P
> <TT
>TextMode mode</TT
> -- the pipe is opened in text mode.</P
></LI
><LI
><P
> <TT
>BinaryMode mode</TT
> -- the pipe is opened in binary mode.</P
></LI
></UL
><P
>The <TT
>mode</TT
> determines if child processes can inherit the pipe handles:</P
><UL
><LI
><P
> ReadMode -- The <EM
>read</EM
> handle of the pipe is private to this process. </P
></LI
><LI
><P
> WriteMode -- The <EM
>write</EM
> handle of the pipe is private to this process. </P
></LI
><LI
><P
> ReadWriteMode -- Both handles are private to this process.</P
></LI
><LI
><P
> AppendMode -- Both handles are available (inheritable) to child =
processes.
This mode can be used to <EM
>append</EM
> (|) two seperate child processes.</P
></LI
></UL
><P
>If a broken pipe is read, an end-of-file (<TT
><A HREF =3D "GHC.IOBase.html#EOF"
>EOF</A
></TT
>)=20
exception is raised. If a broken pipe is written to, an invalid argument =
exception
is raised (<TT
><A HREF =3D "GHC.IOBase.html#InvalidArgument"
>InvalidArgument</A
></TT
>).</P
><P
>Here is a short example that redirects stdin, stdout and stderr of a =
spawned=20
child process to private handles in the parent process.</P
><PRE
> spawn :: String -> IO (Handle,Handle,Handle)
spawn command=20
=3D do{ (stdinRead,stdinWrite) <- createPipeEx (TextMode =
WriteMode)
; (stdoutRead,stdoutWrite) <- createPipeEx (TextMode ReadMode)
; (stderrRead,stderrWrite) <- createPipeEx (TextMode ReadMode)
; runProcess command [] Nothing Nothing (Just stdinRead) (Just =
stdoutWrite) (Just stderrWrite)
; hClose stdinRead
; hClose stdoutWrite
; hClose stderrWrite
; return (stdinWrite,stdoutRead,stderrRead)
}
</PRE
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "section1"
><A NAME =3D "3"
> Data types (<TT
>IOModeEx</TT
>) </A
></TD
></TR
><TR
><TD CLASS =3D "s15"
></TD
></TR
><TR
><TD CLASS =3D "botbar"
>Produced by <A HREF =3D "http://www.haskell.org/haddock"
>Haddock</A
> version 0.4</TD
></TR
></TABLE
></BODY
></HTML
>
------=_NextPart_000_00B0_01C31629.C5998A30--