forked from GitHub/gf-core
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:
@@ -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")
|
||||
],
|
||||
|
||||
18
src/compiler/GF/System/Process.hs
Normal file
18
src/compiler/GF/System/Process.hs
Normal 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
|
||||
Reference in New Issue
Block a user