Redirecting the end of a pipe

Following interesting problem:
1. I have created two pipe end points via IO.pipe:
stdin_read,stdin_write=IO.pipe

2. I have forked of a child, and redirected stdin of the child with:
$stdin.reopen(stdin_read)

3. In the parent process, I have used the other end of the pipe to write
to the stdin of the child:
stdin_write.puts "word1"

At that point, I am finished sending stuff through the pipe
automatically.
However, I am unsure whether my child may need any further input.
Because of that, I want to redirect the pipe end 'stdin_write' in the
parent to stdin, so that stuff coming in through stdin gets send on
through stdin_write (thus ending up in the stdin of the child).
Question: How do I do that?

The obvious first try of stdin_write.reopen($stdin) does not work, as it
destroys the pipe connection.
Of course I could just keep polling $stdin, and send anything I get on
to stdin_write, but really, ughh...

Does anybody have a nicer solution or idea?

···

--
Posted via http://www.ruby-forum.com/.

You cannot solve this by redirection because $stdin is opened in read
mode while stdin_write is opened in write mode. You need something in
between that sends over data. Any other solution works only if you
can control the child's code because then you can simply read from the
pipe and continue reading from the old stdin which is inherited. Even
for the temporary saving of the fd (what I did with "x" below) you
need to control the child's code.

#!/bin/env ruby19

rd, wr = IO.pipe

pid = fork do
  wr.close

  # x = $stdin.clone
  $stdin.reopen rd

  $stdin.each_line do |line|
    puts "child got: #{line}"
  end

  false and x.each_line do |line|
    puts "child got: #{line}"
  end
end

rd.close

5.times do |i|
  wr.puts "parent sends #{i}"
end

# line wise
false and $stdin.each_line do |line|
  wr.puts "from stdin #{line}"
end

# raw
while buffer = $stdin.read(100)
  wr.write(buffer)
end

wr.close

Kind regards

robert

···

2010/6/25 Thomas Secret <martin.gerdes@directbox.com>:

Following interesting problem:
1. I have created two pipe end points via IO.pipe:
stdin_read,stdin_write=IO.pipe

2. I have forked of a child, and redirected stdin of the child with:
$stdin.reopen(stdin_read)

3. In the parent process, I have used the other end of the pipe to write
to the stdin of the child:
stdin_write.puts "word1"

At that point, I am finished sending stuff through the pipe
automatically.
However, I am unsure whether my child may need any further input.
Because of that, I want to redirect the pipe end 'stdin_write' in the
parent to stdin, so that stuff coming in through stdin gets send on
through stdin_write (thus ending up in the stdin of the child).
Question: How do I do that?

The obvious first try of stdin_write.reopen($stdin) does not work, as it
destroys the pipe connection.
Of course I could just keep polling $stdin, and send anything I get on
to stdin_write, but really, ughh...

Does anybody have a nicer solution or idea?

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Thank you for your answer.

I've now done precisely what I had hoped to avoid: Keep polling for new
input, and pass on anything I get. As I don't control the child,
apparently the only thing I can do. At least it works...

···

--
Posted via http://www.ruby-forum.com/.

Thank you for your answer.

You're welcome.

I've now done precisely what I had hoped to avoid: Keep polling for new
input, and pass on anything I get. As I don't control the child,
apparently the only thing I can do. At least it works...

IMHO "polling" is not exactly the right term for this. Rather you
read and block until more data is available - unless you use non
blocking IO.

Kind regards

robert

···

2010/6/28 Thomas Secret <martin.gerdes@directbox.com>:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/