
and there shouldn't be any problem with us just pulling it into the current Posix library for the time being.
Sounds fine to me. Do you mean dropping it into "libraries/base/GHC/Posix.hs"?
I would drop the file into the tree as hslibs/posix/POpen.hs for now, and export popen and popenEnvDir from Posix.
Btw is most of hslibs expected to go into libraries? How about all the posix stuff?
The plan is to migrate everything useful from hslibs into libraries eventually. Deprecated functionality and old interfaces are being left behind, and someday we'll ship GHC without hslibs at all. Hugs is also going to move to using the contents of fptools/libraries for its base libraries soon. As regards the Posix library, I think we need a redesigned library that supports more of IEEE 1003.1-2001 (the latest incarnation of POSIX including all the extra bits from the Single Unix Spec). It certainly needs to be completely re-implemented: the current Posix library uses all kinds of old GHC features and libraries that we'd like to remove.
Yes, that's ok. Should I send you a new version with the header updated, or?
That would be great, thanks. Cheers, Simon

"Simon Marlow"
I would drop the file into the tree as hslibs/posix/POpen.hs for now,
Ok, sure. (Btw is there is a LICENSE file for hslibs?)
and export popen and popenEnvDir from Posix.
I have been pondering a little over popenEnvDir. I'm starting to think it might be preferable to have some idioms like "withCurrentDirectory" and "withEnv" instead. withCurrentDirectory :: FilePath -> IO a -> IO a -- in DirectoryExts perhaps, or System.Directory? withEnv :: [(String, String)] -> IO a -> IO a -- in SystemExts perhaps, or System.Environment? Well, "executeFile" takes a Maybe Env argument, so maybe that it ok, but perhaps the Dir part could be dropped (it basically comes from runProcess) to make "popenEnv" instead? In that case perhaps just one function "popen" is enough, don't you think?
Btw is most of hslibs expected to go into libraries? How about all the posix stuff?
The plan is to migrate everything useful from hslibs into libraries eventually. Deprecated functionality and old interfaces are being left behind, and someday we'll ship GHC without hslibs at all. Hugs is also going to move to using the contents of fptools/libraries for its base libraries soon.
So libraries will be the new library base in the next release of ghc?
As regards the Posix library, I think we need a redesigned library that supports more of IEEE 1003.1-2001 (the latest incarnation of POSIX including all the extra bits from the Single Unix Spec). It certainly needs to be completely re-implemented: the current Posix library uses all kinds of old GHC features and libraries that we'd like to remove.
Ok. The Posix popen seems to allow only reading from or writing to the subprocess, but not both. I wonder if something like the following sugar wouldn't be useful too? withStdinString :: String -> IO a -> IO a withStdoutString :: IO a -> IO (a, String) withStdoutString_ :: IO () -> IO String withStderrString :: IO a -> IO (a, String) withStderrString_ :: IO () -> IO String withStdouterrString :: IO a -> IO (a, String) withStdouterrString_ :: IO () -> IO String
Yes, that's ok. Should I send you a new version with the header updated
That would be great, thanks.
Ok, basically it's ready, pending any changes from comments to the above. Jens

Jens Petersen
"Simon Marlow"
writes: I would drop the file into the tree as hslibs/posix/POpen.hs for now,
Ok, sure. (Btw is there is a LICENSE file for hslibs?)
and export popen and popenEnvDir from Posix.
I have been pondering a little over popenEnvDir. I'm starting to think it might be preferable to have some idioms like "withCurrentDirectory" and "withEnv" instead.
But these are perhaps less useful for forked processes.
As regards the Posix library, I think we need a redesigned library that supports more of IEEE 1003.1-2001 (the latest incarnation of POSIX including all the extra bits from the Single Unix Spec). It certainly needs to be completely re-implemented: the current Posix library uses all kinds of old GHC features and libraries that we'd like to remove.
Ok. The Posix popen seems to allow only reading from or writing to the subprocess, but not both.
Yes, that's ok. Should I send you a new version with the header updated
That would be great, thanks.
Ok, basically it's ready, pending any changes from comments to the above.
I added a little sgml documentation too. I think this should compile ok in posix. If you need changelog entries, please let me know. Is the header ok? Cheers, Jens --- /dev/null Fri Feb 1 12:24:56 2002 +++ POpen.hs Tue Mar 12 19:41:17 2002 @@ -0,0 +1,112 @@ +----------------------------------------------------------------------------- +-- +-- Module : POpen +-- Copyright : (c) The GRASP/AQUA Project, Glasgow University, 1995-1996 +-- (c) 2001-2002 Jens-Ulrik Holger Petersen +-- License : BSD-style +-- +-- Maintainer : petersen@haskell.org +-- Stability : experimental +-- Portability : Platform-specific +-- +-- $Id: POpen.hs,v 1.0 2002/02/25 10:44:01 petersen Exp $ +-- +-- Convenient string input to and output from a subprocess +-- +----------------------------------------------------------------------------- +-- +-- Description +-- +-- POpen provides a convenient way of sending string input to a +-- subprocess and reading output from it lazily. +-- +-- It provides two functions popen and popenEnvDir. +-- +-- * popen gives lazy output and error streams from a +-- subprocess command, and optionally can direct input from a +-- string to the process. +-- +-- * popenEnvDir in addition lets one specify the environment +-- and directory in which to run the subprocess command. +-- +-- This code is originally based on Posix.runProcess, but it +-- uses file descriptors and pipes internally instead of +-- handles and returns the output and error streams lazily as +-- strings and also the pid of forked process. + +module POpen (popen, popenEnvDir) +where + +import PosixFiles (stdInput, stdOutput, stdError) +import PosixIO (createPipe, dupTo, fdClose, fdToHandle) +import PosixProcPrim (executeFile, forkProcess) +import PosixUtil (Fd, ProcessID) + +import Directory +import IO (isEOFError, hGetContents, Handle, hPutStr, hClose) +import Maybe (fromJust, isJust) +import Monad (when) + +popen :: FilePath -- Command + -> [String] -- Arguments + -> Maybe String -- Input + -> IO (String, String, ProcessID) -- (stdout, stderr, pid) +popen path args inpt = + popenEnvDir path args inpt Nothing Nothing + +popenEnvDir :: FilePath -- Command + -> [String] -- Arguments + -> Maybe String -- Input + -> Maybe [(String, String)] -- Environment + -> Maybe FilePath -- Working directory + -> IO (String, String, ProcessID) -- (stdout, stderr, pid) +popenEnvDir path args inpt env dir = + do + inr <- if (isJust inpt) + then + do + (inr', inw) <- createPipe + hin <- fdToHandle inw + hPutStr hin $ fromJust inpt + hClose hin + return $ Just inr' + else + return Nothing + (outr, outw) <- createPipe + (errr, errw) <- createPipe + pid <- forkProcess + case pid of + Nothing -> doTheBusiness inr outw errw + Just p -> do + -- close other end of pipes in here + when (isJust inr) $ + fdClose $ fromJust inr + fdClose outw + fdClose errw + hout <- fdToHandle outr + outstrm <- hGetContents hout + herr <- fdToHandle errr + errstrm <- hGetContents herr + return (outstrm, errstrm , p) + where + doTheBusiness :: + Maybe Fd -- stdin + -> Fd -- stdout + -> Fd -- stderr + -> IO (String, String, ProcessID) -- (stdout, stderr) + doTheBusiness inr outw errw = + do + maybeChangeWorkingDirectory dir + when (isJust inr) $ + dupTo (fromJust inr) stdInput + dupTo outw stdOutput + dupTo errw stdError + executeFile path True args env + -- for typing, should never actually run + error "executeFile failed!" + +maybeChangeWorkingDirectory :: Maybe FilePath -> IO () +maybeChangeWorkingDirectory dir = + case dir of + Nothing -> return () + Just x -> setCurrentDirectory x Index: Posix.lhs =================================================================== RCS file: /cvs/fptools/hslibs/posix/Posix.lhs,v retrieving revision 1.5 diff -u -r1.5 Posix.lhs --- Posix.lhs 2002/02/12 15:17:33 1.5 +++ Posix.lhs 2002/03/12 12:57:29 @@ -14,6 +14,7 @@ module PosixProcEnv, module PosixProcPrim, module PosixTTY, + module POpen runProcess, @@ -44,6 +45,7 @@ import PosixProcPrim import PosixTTY import PosixUtil +import POpen -- [OLD COMMENT:] -- runProcess is our candidate for the high-level OS-independent primitive Index: doc/posix.sgml =================================================================== RCS file: /cvs/fptools/hslibs/posix/doc/posix.sgml,v retrieving revision 1.12 diff -u -r1.12 posix.sgml --- doc/posix.sgml 2001/10/22 10:08:45 1.12 +++ doc/posix.sgml 2002/03/12 12:57:30 @@ -2372,4 +2372,66 @@ </Sect1> +<Sect1 id="POpen"> +<Title>POpen +</Title> + +<Para> +<IndexTerm><Primary>POpen</Primary></IndexTerm> +POpen provides a convenient way of sending string input to a +subprocess and reading output from it lazily. +</Para> + +<Para> + +<ProgramListing> +popen :: FilePath -- Command + -> [String] -- Arguments + -> Maybe String -- Input + -> IO (String, String, ProcessID) -- (stdout, stderr, pid) +</ProgramListing> + +</Para> + +<Para> +<literal>popen cmd args inp</literal> executes +<literal>cmd</literal> with <literal>args</literal> in a +forked process. If <literal>inp</literal> is +<literal>Just str</literal> then str in sent in a pipe to +the standard input of the process. The output and error +streams from the process are returned, together with the +process id. +</Para> + +<Para> + +<ProgramListing> +popenEnvDir :: FilePath -- Command + -> [String] -- Arguments + -> Maybe String -- Input + -> Maybe [(String, String)] -- Environment + -> Maybe FilePath -- Working directory + -> IO (String, String, ProcessID) -- (stdout, stderr, pid) +</ProgramListing> + +</Para> + +<Para> +<literal>popenEnvDir cmd args inp env dir</literal> like +<literal>popen</literal> executes +<literal>cmd</literal> with <literal>args</literal> in a +forked process. If <literal>inp</literal> is +<literal>Just str</literal> then str in sent in a pipe to +the standard input of the process. If <literal>env</literal> +is <literal>Just pairs</literal>, the command in executed in +the environment specified by <literal>pairs</literal>, +instead of the current one. If <literal>dir</literal> is +<literal>Just d</literal> the command is executed in +directory <literal>d</literal> instead of the current +directory. The output and error streams from the process +are returned, together with the process id. +</Para> + +</Sect1> + </Chapter>

I guess you've just been busy with other things, but was the
patch I sent to add POpen to posix ok?
Jens
Jens Petersen
Jens Petersen
writes: "Simon Marlow"
writes: I would drop the file into the tree as hslibs/posix/POpen.hs for now,
Ok, sure.
Yes, that's ok. Should I send you a new version with the header updated
That would be great, thanks.
Ok, basically it's ready, pending any changes from comments to the above.
I added a little sgml documentation too. I think this should compile ok in posix. If you need changelog entries, please let me know. Is the header ok?
--- /dev/null Fri Feb 1 12:24:56 2002 +++ POpen.hs Tue Mar 12 19:41:17 2002
participants (3)
-
Jens Petersen
-
Jens Petersen
-
Simon Marlow