use IPC::Open3; use POSIX ":sys_wait_h"; package Query; sub new { my $self = shift; my %opt = @_; $self = \%opt; defined $self -> { SERVICE } or $self -> { SERVICE } = 'defaultqueryprog'; if ( defined $self -> { SEND } ) { my $pid = open3 my $wh, my $rh, my $eh, $self -> { SERVICE } or warn "$!: " . $self -> { SERVICE } . "\n" && exit $?; $self -> { WH } = $wh; $self -> { RH } = $rh; $self -> { EH } = $eh; $self -> { PID } = $pid; write $wh $self -> { SEND } . "\n"; } else { my $pid = open3 undef(), my $rh, my $eh, $self -> { SERVICE } or warn "$!: " . $self -> { SERVICE } . "\n" && exit $?; $self -> { RH } = $rh; $self -> { EH } = $eh; $self -> { PID } = $pid; } return bless $self; # note the pipe is not closed! } sub fetch { my $self = shift; my $rh = $self -> { RH }; my $eh = $self -> { EH }; my $oneliner = !wantarray; unless ( $oneliner &&= <$rh> ) { # cleanup if and only if flushing the pipe my @out = <$rh>; close $rh; my @err = <$eh>; close $eh; $self -> { STDERR } = \@err; waitpid $self -> { PID },0; delete $self -> { PID }; return @out; } return $oneliner; } sub fetcherror { # similar to fetch but on $self -> { EH }; ... } sub shut { my $self = shift; close $self -> { RH }, $self -> { EH }; $sts = $?; waitpid $self -> { PID }, 0; delete $self -> { PID }; return $sts; } 1;