[Haskell-cafe] Using external programs with Haskell in windows.
Christian Lean
christian.lean2 at bigpond.com
Sun Mar 18 21:54:14 EDT 2007
Donald Bruce Stewart wrote:
> christian.lean2:
>
>> Donald Bruce Stewart wrote:
>>
>>> christian.lean2:
>>>
>>>
>>>> I'm looking for a way to run an external program and get the results in
>>>> haskell. Something similar to HSH but that will work in windows. I don't
>>>> need anything too complex, just to provide the command to be run as a
>>>> string and get the result as a string. Is this possible?
>>>> One of the HSH examples is all I need:
>>>>
>>>> runS $ "echo /etc/pass*"
>>>> -> "/etc/passwd /etc/passwd-"
>>>>
>>>>
>>> System.Process is your friend. E.g.
>>>
>>>
>>> import System.Process
>>> import Control.Exception
>>> import System.IO
>>> import System.Exit
>>>
>>> --
>>> -- Run a normal shell command
>>> --
>>> run :: String -> IO String
>>> run s = handle (fail . show) $ do
>>> (ih,oh,eh,pid) <- runInteractiveCommand s
>>> so <- hGetContents oh
>>> se <- hGetContents eh
>>> hClose ih
>>> ex <- waitForProcess pid
>>> case ex of
>>> ExitFailure e -> fail $ "Failed with status: " ++ show e
>>> _ | not (null se) -> fail se
>>> | otherwise -> return so
>>>
>>>
>>> *Process> run $ "echo *.hs"
>>> "Main.hs Process.hs Shell.hs\n"
>>>
>>> -- Don
>>>
>>>
>>>
>> Thank you for the speedy reply, I am trying to follow what the code is
>> trying to do, is this correct?
>> runInteractiveCommand:
>> This gives you handles for stdin, stdout, stderr, and the process
>> running the command.
>> You can then use functions like hPutStrLn with stdin or hGetContents
>> with stdout and stderr.
>>
>
> Right.
>
>
>> waitForProcess just stops that part of the code until the command has
>> finished.
>>
>
> Yep.
>
>
>> Is nClose ih necessary, none of the others are closed so I'm guessing
>> this is needed else waitForProcess will never finish.
>>
>
> They should be closed too I suspect.
>
>
>> Does this have to do with run_Interactive_Command, could I keep passing
>> commands and getting responses until I close the input.
>>
>
> Not with that code, but you could modify it to do so.
>
>
>> The two parts i'm having trouble following are:
>>
>> run s = handle (fail . show) $ do
>>
>
> That's an exception handler that just shows the exception in the current
> monad.
>
>
>> handle has type:
>>
>> handle :: (Exception -> IO a) -> IO a -> IO a
>>
>> Is (fail . show) composing a fuction of type
>>
>> Exception -> IO a)
>>
>> and what part is the middle IO a, is that the whole block that
>> follows(ie the do block)
>>
>
> Yes.
>
>
>> Also
>>
>> case ex of
>> ExitFailure e -> fail $ "Failed with status: " ++ show e
>> _ | not (null se) -> fail se
>> | otherwise -> return so
>>
>> I dont quite get this part. I understand that you are checking for
>> errors(not (null se)) otherwise returning everything gotten from stdout
>> but I don't get
>> the ExitFailure line.
>>
>
> That checks the exit status of the program, as reported by
> waitForProcess, the other cases check for stderr.
>
>
>> I have one final question, how should you go about finding functions
>> like runInteractiveCommand?
>>
>
> hoogle!
>
> http://www.haskell.org/hoogle/?q=Command
>
>
>> If I had that to begin with I might have had a chance to try some of the
>> above on my own but I find that it is difficult to know where to start.
>>
>
> Hoogle, and the library docs, are helpful here.
>
> -- Don
>
>
Just a quick thankyou, the response has been very helpful.
More information about the Haskell-Cafe
mailing list