GF shell: improved system_pipe (aka "?") command

1. No temporary files are created.

2. The output of a system command is read lazily, making it feasible to 
   process large or even infinite output, e.g. the following works as
   expected:

	? "yes" | ? "head -5" | ps -lextext
This commit is contained in:
hallgren
2013-11-19 15:18:58 +00:00
parent c58b6d8a60
commit c29326d074
2 changed files with 23 additions and 1 deletions

View File

@@ -46,6 +46,7 @@ import Data.List(intersperse,nub)
import Data.Maybe
import qualified Data.Map as Map
--import System.Cmd(system) -- use GF.Infra.UseIO.restricedSystem instead!
import GF.System.Process
import Text.PrettyPrint
import Data.List (sort)
--import Debug.Trace
@@ -866,12 +867,15 @@ allCommands = Map.fromList [
synopsis = "send argument to a system command",
syntax = "sp -command=\"SYSTEMCOMMAND\", alt. ? SYSTEMCOMMAND",
exec = \_ opts arg -> do
let syst = optComm opts -- ++ " " ++ tmpi
{-
let tmpi = "_tmpi" ---
let tmpo = "_tmpo"
restricted $ writeFile tmpi $ toString arg
let syst = optComm opts -- ++ " " ++ tmpi
restrictedSystem $ syst ++ " <" ++ tmpi ++ " >" ++ tmpo
fmap fromString $ restricted $ readFile tmpo,
-}
fmap fromString . restricted . readShellProcess syst $ toString arg,
flags = [
("command","the system command applied to the argument")
],

View File

@@ -0,0 +1,18 @@
module GF.System.Process where
import System.Process
import System.IO(hGetContents,hClose,hPutStr)
import Control.Concurrent(forkIO)
import GF.System.Catch(try)
-- | Feed some input to a shell process and read the output lazily
readShellProcess :: String -- ^ shell command
-> String -- ^ input to shell command
-> IO String -- ^ output from shell command
readShellProcess cmd input =
do (Just stdin,Just stdout,Nothing,ph) <-
createProcess (shell cmd){std_in=CreatePipe,std_out=CreatePipe}
forkIO $ do try $ hPutStr stdin input
try $ hClose stdin
waitForProcess ph
return ()
hGetContents stdout