|
4 | 4 | use IO::Pty;
|
5 | 5 | use File::Copy;
|
6 | 6 |
|
7 |
| -# Run @$argv in the background with stdout redirected to $out. |
| 7 | +# Run @$argv in the background with stdio redirected to $out and $err. |
8 | 8 | sub start_child {
|
9 |
| - my ($argv, $out) = @_; |
| 9 | + my ($argv, $out, $err) = @_; |
10 | 10 | my $pid = fork;
|
11 | 11 | if (not defined $pid) {
|
12 | 12 | die "fork failed: $!"
|
13 | 13 | } elsif ($pid == 0) {
|
14 | 14 | open STDOUT, ">&", $out;
|
| 15 | + open STDERR, ">&", $err; |
15 | 16 | close $out;
|
16 | 17 | exec(@$argv) or die "cannot exec '$argv->[0]': $!"
|
17 | 18 | }
|
@@ -47,12 +48,28 @@ sub xsendfile {
|
47 | 48 | copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
|
48 | 49 | }
|
49 | 50 |
|
| 51 | +sub copy_stdio { |
| 52 | + my ($out, $err) = @_; |
| 53 | + my $pid = fork; |
| 54 | + defined $pid or die "fork failed: $!"; |
| 55 | + if (!$pid) { |
| 56 | + close($out); |
| 57 | + xsendfile(\*STDERR, $err); |
| 58 | + exit 0; |
| 59 | + } |
| 60 | + close($err); |
| 61 | + xsendfile(\*STDOUT, $out); |
| 62 | + finish_child($pid) == 0 |
| 63 | + or exit 1; |
| 64 | +} |
| 65 | + |
50 | 66 | if ($#ARGV < 1) {
|
51 | 67 | die "usage: test-terminal program args";
|
52 | 68 | }
|
53 |
| -my $master = new IO::Pty; |
54 |
| -my $slave = $master->slave; |
55 |
| -my $pid = start_child(\@ARGV, $slave); |
56 |
| -close $slave; |
57 |
| -xsendfile(\*STDOUT, $master); |
| 69 | +my $master_out = new IO::Pty; |
| 70 | +my $master_err = new IO::Pty; |
| 71 | +my $pid = start_child(\@ARGV, $master_out->slave, $master_err->slave); |
| 72 | +close $master_out->slave; |
| 73 | +close $master_err->slave; |
| 74 | +copy_stdio($master_out, $master_err); |
58 | 75 | exit(finish_child($pid));
|
0 commit comments