[Haskell-cafe] Intercept stdin in Haskell
andrew.gibiansky at gmail.com
Mon Jan 6 00:45:32 UTC 2014
You are a saviour!
We'd actually already tried going down this path with takeMVars and
putMVars, but somehow it didn't quite work. Let's see if this works in
practice in IHaskell!
Working program below:
main = do
-- Create a pipe using System.Posix and turn it into handles.
(readEnd, writeEnd) <- createPipe
newStdin <- fdToHandle readEnd
stdinInput <- fdToHandle writeEnd
-- Store old stdin and swap in new stdin.
oldStdin <- hDuplicate stdin
hDuplicateTo newStdin stdin
-- In a separate thread, wait for the read.
forkIO $ forever $ do
let FileHandle _ mvar = stdin
threadDelay $ 200 * 1000
empty <- isEmptyMVar mvar
when empty $ do
hPutStrLn stdinInput "foo"
threadDelay $ 3 * 1000 * 1000
getChar >>= print
On Sun, Jan 5, 2014 at 7:11 PM, John Lato <jwlato at gmail.com> wrote:
> Here's a stupid idea:
> A Handle contains an MVar Handle__, and when a thread calls hGetLine
> stdin, it will take that MVar, attempt to read from the buffered device,
> and then block until there's data available to be read from the device.
> You could check if the MVar is empty, and if so, assume that something is
> trying to read from stdin and write your input into the device.
> Horrible, unsound hack, I'm sure, but it's all I've got...
> On Sun, Jan 5, 2014 at 3:14 PM, Andrew Gibiansky <
> andrew.gibiansky at gmail.com> wrote:
>> Looks like the excitement was a bit premature. The types work, and in
>> Haskell that often means the program works... but looks like hDupTo relies
>> on the `dup2` of the IODevice class, and attempts to cast one IODevice to
>> another IODevice. Since I'm trying to replace stdin (with IODevice type Fd)
>> with my own IODevice, the cast fails and raises an exception. Practically
>> ClassCastException.... yeesh.
>> On Sun, Jan 5, 2014 at 5:19 PM, Andrew Gibiansky <
>> andrew.gibiansky at gmail.com> wrote:
>>> I think we found a way! (With a *ton* of help from @aavogt - might
>>> actually be more correct to say he found the way :) )
>>> You can use `hDupTo` to change what a Handle points to. You can use
>>> `mkFileHandle` in GHC.IO.Internal to create a new file handle. You can
>>> implement your own IODevice and BufferedIO datatype to give to
>>> `mkFileHandle` instead of using `Fd`. Then, when your "device" is being
>>> read from, you just implement `newBuffer` and `readBuffer` to do whatever
>>> you need them to.
>>> Results pending.
>>> -- Andrew
>>> On Sun, Jan 5, 2014 at 4:14 PM, Donn Cave <donn at avvanta.com> wrote:
>>>> I bet a quarter you can't do it. You'd need access to the process
>>>> state -
>>>> whether it's blocking for I/O and whether one of the units in the input
>>>> is 0 ("stdin".) Even if you could get that? you'd have to poll for it,
>>>> would be hideous.
>>>> That's the UNIX I/O model. I've always found it a little annoying,
>>>> I could do this with the VMS `mailbox' device, analogous to UNIX pipes -
>>>> in various ways a more sophisticated interprocess communication system
>>>> Haskell-Cafe mailing list
>>>> Haskell-Cafe at haskell.org
>> Haskell-Cafe mailing list
>> Haskell-Cafe at haskell.org
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Haskell-Cafe