Chris
Chris

Reputation: 572

multiline contents of a IO handle in haskell display nothing

I have been experimenting with Haskell. I am trying to write a web crawler and I need to use external curl binary (due to some proxy settings, curl needs to have some special arguments which seem to be impossible/hard to set inside the haskell code, so i rather just pass it as a command line option. but that is another story...)

In the code at the bottom, if I change the marked line with curl instead of curl --help the output renders properly and gives:

"curl: try 'curl --help' or 'curl --manual' for more information
" 

otherwise the string is empty - as the `curl --help' response is multiline. I suspect that in haskell the buffer is cleared with every new line. (same goes for other simple shell commands like ls versus ls -l etc.)

How do I fix it?

The code:

import System.Process
import System.IO
main = do
    let sp = (proc "curl --help"[]){std_out=CreatePipe} -- *** THIS LINE ***
    (_,Just out_h,_,_)<- createProcess sp
    out <-hGetContents out_h
    print out

Upvotes: 0

Views: 71

Answers (2)

chi
chi

Reputation: 116139

proc takes as a first argument the name of the executable, not a shell command. That, is when you use proc "foo bar" you are not referring to a foo executable, but to an executable named exactly foo bar, with the space in its file name.

This is a useful feature in practice, because sometimes you do have spaces in there (e.g. on Windows you might have c:\Program Files\Foo\Foo.exe). Using a shell command you would have to escape spaces in your command string. Worse, a few other characters need to be escaped as well, and it's cumbersome to check what exactly those are. proc sidesteps the issue by not using the shell at all but passing the string as it is to the OS.

For the executable arguments, proc takes a separate argument list. E.g.

proc "c:\\Program Files\\Foo\\Foo.exe" ["hello world!%$"]

Note that the arguments need no escaping as well.

Upvotes: 5

Sibi
Sibi

Reputation: 48664

If you want to pass arguments to curl you have to pass that it in the list:

sp = (proc "/usr/bin/curl" ["--help"]) {std_out=CreatePipe}

Then you will get the complete output in the entire string.

Upvotes: 4

Related Questions