
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 =================== shell-haskell 1.0.0 =================== 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

Simon Marlow writes:
What do people think?
I think it is a good idea to provide the POSIX functions 'popen' and 'system', simply because people _know_ them. When I tried to figure out how to start sub-processes in Haskell, I looked for these functions first of all, too. So far, 'launch' seems to be the most useful one, though, so I'd definitely like to see it (or something similar) in GHC's standard library. Plus: One could easily implement 'popen' and 'system' on top of it. Peter

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"
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
=================== shell-haskell 1.0.0 ===================
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

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 -----
From: Daan Leijen
To: Simon Marlow ; libraries@haskell.org
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"
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
=================== shell-haskell 1.0.0 ===================
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

On Fri, May 09, 2003 at 11:03:13AM +0100, Simon Marlow wrote:
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.
You need to have two rather than one handle if you want to know when the process is finishing outputting. Otherwise its output filehandle will never reach EOF. Generally you won't want to close the output and input Handles simultaneously. -- David Roundy http://www.abridgegame.org

On Fri, May 09, 2003 at 11:03:13AM +0100, Simon Marlow wrote:
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).
One thing I'd like to see would be a version that accepts a string as the standard input, and perhaps gives a lazy string as the standard output. At least in its current incarnation, I don't see how this can trivially be implemented on top of launch, since it would generally fail on input strings longer than 4k in length due to buffering issues, as the write of the string will block when the buffer is full. The handles are great, but if what you really want is just a simple (non-interactive) pipe, strings would be nice. -- David Roundy http://www.abridgegame.org

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

I was wondering what the state of the System.Process module described on http://haskell.org/hawiki/ExternalCommands is? I have tried to use the various POpen-like implementations out there, but _none_ of them works with the most current GHC. Is there any way to communicate with external programs at the moment? Posix-only would be suffice at the moment. Peter

Peter Simons wrote:
I have tried to use the various POpen-like implementations out there, but _none_ of them works with the most current GHC. Is there any way to communicate with external programs at the moment? Posix-only would be suffice at the moment.
There's the DIY solution, i.e. a direct translation of how popen() is implemented in C, e.g.:
module Main where
import IO import System import System.Posix
main = do (rfd, wfd) <- createPipe pid <- forkProcess (proc rfd wfd) closeFd wfd hRead <- fdToHandle rfd str <- hGetContents hRead putStr str stat <- getProcessStatus True False pid case stat of (Just (Exited code)) -> exitWith code _ -> exitWith (ExitFailure 127) where proc rfd wfd = do closeFd rfd dupTo wfd stdOutput executeFile "/bin/ls" False ["-l"] Nothing
The above has been (briefly) tested with ghc 6.2.1.
--
Glynn Clements

Glynn Clements wrote:
I have tried to use the various POpen-like implementations out there, but _none_ of them works with the most current GHC. Is there any way to communicate with external programs at the moment? Posix-only would be suffice at the moment.
There's the DIY solution, i.e. a direct translation of how popen() is implemented in C, e.g.:
module Main where
import IO import System import System.Posix
main = do (rfd, wfd) <- createPipe pid <- forkProcess (proc rfd wfd) closeFd wfd hRead <- fdToHandle rfd str <- hGetContents hRead putStr str stat <- getProcessStatus True False pid case stat of (Just (Exited code)) -> exitWith code _ -> exitWith (ExitFailure 127) where proc rfd wfd = do closeFd rfd dupTo wfd stdOutput executeFile "/bin/ls" False ["-l"] Nothing
The above has been (briefly) tested with ghc 6.2.1.
I had forgotten about Simon's System.Process module (at the time of the announcement, I was still on GHC 5.04.2, so I couldn't test it). Here's a version of the above code which uses runProcess:
module Main where
import IO ( hGetContents , hClose ) import System ( exitWith ) import System.Process ( runProcess , waitForProcess ) import System.Posix ( createPipe , fdToHandle )
main = do (rfd, wfd) <- createPipe hRead <- fdToHandle rfd hWrite <- fdToHandle wfd handle <- runProcess "/bin/ls" ["-l"] Nothing Nothing (Just hWrite) Nothing hClose hWrite str <- hGetContents hRead putStr str code <- waitForProcess handle exitWith code
And another version which uses runInteractiveProcess:
module Main where
import IO ( hGetContents ) import System ( exitWith ) import System.Process ( runInteractiveProcess , waitForProcess )
main = do (_, hOut, _, handle) <- runInteractiveProcess "/bin/ls" ["-l"] Nothing str <- hGetContents hOut putStr str code <- waitForProcess handle exitWith code
This last one isn't quite the same as popen(), as it automatically
associates each of the three standard descriptors with their own pipe,
whereas popen() only redirects one of stdin or stdout, while the other
one and stderr are inherited from the caller.
--
Glynn Clements
participants (5)
-
Daan Leijen
-
David Roundy
-
Glynn Clements
-
Peter Simons
-
Simon Marlow