1N/Apackage IPC::Open2;
1N/A
1N/Ause strict;
1N/Aour ($VERSION, @ISA, @EXPORT);
1N/A
1N/Arequire 5.000;
1N/Arequire Exporter;
1N/A
1N/A$VERSION = 1.01;
1N/A@ISA = qw(Exporter);
1N/A@EXPORT = qw(open2);
1N/A
1N/A=head1 NAME
1N/A
1N/AIPC::Open2, open2 - open a process for both reading and writing
1N/A
1N/A=head1 SYNOPSIS
1N/A
1N/A use IPC::Open2;
1N/A
1N/A $pid = open2(\*RDRFH, \*WTRFH, 'some cmd and args');
1N/A # or without using the shell
1N/A $pid = open2(\*RDRFH, \*WTRFH, 'some', 'cmd', 'and', 'args');
1N/A
1N/A # or with handle autovivification
1N/A my($rdrfh, $wtrfh);
1N/A $pid = open2($rdrfh, $wtrfh, 'some cmd and args');
1N/A # or without using the shell
1N/A $pid = open2($rdrfh, $wtrfh, 'some', 'cmd', 'and', 'args');
1N/A
1N/A=head1 DESCRIPTION
1N/A
1N/AThe open2() function runs the given $cmd and connects $rdrfh for
1N/Areading and $wtrfh for writing. It's what you think should work
1N/Awhen you try
1N/A
1N/A $pid = open(HANDLE, "|cmd args|");
1N/A
1N/AThe write filehandle will have autoflush turned on.
1N/A
1N/AIf $rdrfh is a string (that is, a bareword filehandle rather than a glob
1N/Aor a reference) and it begins with C<< >& >>, then the child will send output
1N/Adirectly to that file handle. If $wtrfh is a string that begins with
1N/AC<< <& >>, then $wtrfh will be closed in the parent, and the child will read
1N/Afrom it directly. In both cases, there will be a dup(2) instead of a
1N/Apipe(2) made.
1N/A
1N/AIf either reader or writer is the null string, this will be replaced
1N/Aby an autogenerated filehandle. If so, you must pass a valid lvalue
1N/Ain the parameter slot so it can be overwritten in the caller, or
1N/Aan exception will be raised.
1N/A
1N/Aopen2() returns the process ID of the child process. It doesn't return on
1N/Afailure: it just raises an exception matching C</^open2:/>. However,
1N/AC<exec> failures in the child are not detected. You'll have to
1N/Atrap SIGPIPE yourself.
1N/A
1N/Aopen2() does not wait for and reap the child process after it exits.
1N/AExcept for short programs where it's acceptable to let the operating system
1N/Atake care of this, you need to do this yourself. This is normally as
1N/Asimple as calling C<waitpid $pid, 0> when you're done with the process.
1N/AFailing to do this can result in an accumulation of defunct or "zombie"
1N/Aprocesses. See L<perlfunc/waitpid> for more information.
1N/A
1N/AThis whole affair is quite dangerous, as you may block forever. It
1N/Aassumes it's going to talk to something like B<bc>, both writing
1N/Ato it and reading from it. This is presumably safe because you
1N/A"know" that commands like B<bc> will read a line at a time and
1N/Aoutput a line at a time. Programs like B<sort> that read their
1N/Aentire input stream first, however, are quite apt to cause deadlock.
1N/A
1N/AThe big problem with this approach is that if you don't have control
1N/Aover source code being run in the child process, you can't control
1N/Awhat it does with pipe buffering. Thus you can't just open a pipe to
1N/AC<cat -v> and continually read and write a line from it.
1N/A
1N/AThe IO::Pty and Expect modules from CPAN can help with this, as they
1N/Aprovide a real tty (well, a pseudo-tty, actually), which gets you
1N/Aback to line buffering in the invoked command again.
1N/A
1N/A=head1 WARNING
1N/A
1N/AThe order of arguments differs from that of open3().
1N/A
1N/A=head1 SEE ALSO
1N/A
1N/ASee L<IPC::Open3> for an alternative that handles STDERR as well. This
1N/Afunction is really just a wrapper around open3().
1N/A
1N/A=cut
1N/A
1N/A# &open2: tom christiansen, <tchrist@convex.com>
1N/A#
1N/A# usage: $pid = open2('rdr', 'wtr', 'some cmd and args');
1N/A# or $pid = open2('rdr', 'wtr', 'some', 'cmd', 'and', 'args');
1N/A#
1N/A# spawn the given $cmd and connect $rdr for
1N/A# reading and $wtr for writing. return pid
1N/A# of child, or 0 on failure.
1N/A#
1N/A# WARNING: this is dangerous, as you may block forever
1N/A# unless you are very careful.
1N/A#
1N/A# $wtr is left unbuffered.
1N/A#
1N/A# abort program if
1N/A# rdr or wtr are null
1N/A# a system call fails
1N/A
1N/Arequire IPC::Open3;
1N/A
1N/Asub open2 {
1N/A local $Carp::CarpLevel = $Carp::CarpLevel + 1;
1N/A return IPC::Open3::_open3('open2', scalar caller,
1N/A $_[1], $_[0], '>&STDERR', @_[2 .. $#_]);
1N/A}
1N/A
1N/A1