http://www.perlmonks.org?node_id=903564


in reply to Re^2: Bidirectional IPC with Expect and Passthrough
in thread Bidirectional IPC with Expect and Passthrough

Perhaps this would also require a fork so one child could always read/write from/to the program, and the other would always read/write from/to the user?

T'is easier using threads.

I don't have top or anything I can easily substitute for it in an example, but what you are asking for should be relatively trivial using threads.

You have two distinct, and extremely simple loops you need to perform:

  1. Read whatever comes doen the pipe from the child process and print it to the terminal.
    print while <$fromKid>;
  2. Read anything that the user types and forward it to the child process via the pipe:
    print $toKid while <STDIN>;

But, as you say, the problem is you need to do both at the same time.

There are two traditional ways of approaching this problem.

Now consider a threaded solution:

#! perl -sw use strict; use threads; use IPC::Open2; my( $toKid, $fromKid ); my $pid = open2( $fromKid, $toKid, 'not-top' ); async{ print while <$fromKid>; }->detach; print $toKid while <STDIN>; kill 9, $pid

And that is pretty much it. Some extra stuff to handle closing things down and possible errors. But essentially, exactly what you'd like to use. Two loops that run concurrently. Simplicity incarnate.

Note: That almost certainly won't work with top as is. The reason is that top uses non-blocking, delimiter-less input for its commands, and that doesn;t work via a pipe. Basically, pipes buffer their input and only pass it on to the other end once they've accumulated a buffer full. With a (typically) 4096 character buffer, you'd have to send 4096 single character commands before top would see the first one, and then it would see all 4096 in quick succession and the result would be very confused.

So, if the program you actually want to control is top, or any program that does delimiter-less input for commands, then you are probably out of luck--using open2 or expect or anything else. But, if you want to control a program that takes normal line-oriented input for commands, then threading is far simpler than other approaches.


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.