open(PROG_FOR_READING_AND_WRITING, "| some program |")
and if you forget to use the -w flag, then you'll miss out entirely on the diagnostic message:
Can't do bidirectional pipe at -e line 1.
If you really want to, you can use the standard open2
library function to catch both ends. There's also an open3
for tri-directional
I/O so you can also catch your child's
STDERR, but doing so would then require an awkward select
loop and wouldn't allow you to use normal Perl input operations.
If you look at its source, you'll see that open2
uses low-level primitives like Unix pipe
and exec
to create all the connections. While it might have been slightly more efficient by using socketpair,
it would have then been even less portable than it already is. The open2
and open3
functions are unlikely to work anywhere except on a Unix system or some other one purporting to be
POSIX compliant.
Here's an example of using open2:
use FileHandle; use IPC::Open2; $pid = open2( \*Reader, \*Writer, "cat -u -n" ); Writer->autoflush(); # default here, actually print Writer "stuff\n"; $got = <Reader>;
The problem with this is that Unix buffering is really going to ruin your
day. Even though your Writer
filehandle is auto-flushed, and the process on the other end will get your
data in a timely manner, you can't usually do anything to force it to give
it back to you in a similarly quick fashion. In this case, we could,
because we gave cat a -u flag to make it unbuffered. But very few Unix commands are designed to
operate over pipes, so this seldom works unless you yourself wrote the
program on the other end of the double-ended pipe.
A solution to this is the non-standard Comm.pl library. It uses pseudo-ttys to make your program behave more reasonably:
require 'Comm.pl'; $ph = open_proc('cat -n'); for (1..10) { print $ph "a line\n"; print "got back ", scalar <$ph>; }
This way you don't have to have control over the source code of the program
you're using. The Comm library also has expect
and interact
functions.
Find the library (and we hope its successor IPC::Chat) at your nearest
CPAN archive as detailed in the
SEE
ALSO section below.