8 # Run @$argv in the background with stdio redirected to $in, $out and $err.
 
  10         my ($argv, $in, $out, $err) = @_;
 
  12         if (not defined $pid) {
 
  15                 open STDIN, "<&", $in;
 
  16                 open STDOUT, ">&", $out;
 
  17                 open STDERR, ">&", $err;
 
  20                 exec(@$argv) or die "cannot exec '$argv->[0]': $!"
 
  25 # Wait for $pid to finish.
 
  27         # Simplified from wait_or_whine() in run-command.c.
 
  30         my $waiting = waitpid($pid, 0);
 
  32                 die "waitpid failed: $!";
 
  35                 warn "died of signal $code";
 
  45         # Note: the real sendfile() cannot read from a terminal.
 
  47         # It is unspecified by POSIX whether reads
 
  48         # from a disconnected terminal will return
 
  49         # EIO (as in AIX 4.x, IRIX, and Linux) or
 
  50         # end-of-file.  Either is fine.
 
  51         copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
 
  58                 xsendfile($in, \*STDIN);
 
  68         defined $pid or die "fork failed: $!";
 
  71                 xsendfile(\*STDERR, $err);
 
  75         xsendfile(\*STDOUT, $out);
 
  76         finish_child($pid) == 0
 
  81         die "usage: test-terminal program args";
 
  84 my $master_in = new IO::Pty;
 
  85 my $master_out = new IO::Pty;
 
  86 my $master_err = new IO::Pty;
 
  87 $master_in->set_raw();
 
  88 $master_out->set_raw();
 
  89 $master_err->set_raw();
 
  90 $master_in->slave->set_raw();
 
  91 $master_out->slave->set_raw();
 
  92 $master_err->slave->set_raw();
 
  93 my $pid = start_child(\@ARGV, $master_in->slave, $master_out->slave, $master_err->slave);
 
  94 close $master_in->slave;
 
  95 close $master_out->slave;
 
  96 close $master_err->slave;
 
  97 my $in_pid = copy_stdin($master_in);
 
  98 copy_stdio($master_out, $master_err);
 
  99 my $ret = finish_child($pid);
 
 100 # If the child process terminates before our copy_stdin() process is able to
 
 101 # write all of its data to $master_in, the copy_stdin() process could stall.
 
 102 # Send SIGTERM to it to ensure it terminates.
 
 103 kill 'TERM', $in_pid;
 
 104 finish_child($in_pid);