1#!/usr/bin/perl
2use strict;
3use warnings;
4use IO::Pty;
5use File::Copy;
67
# Run @$argv in the background with stdout redirected to $out.
8sub start_child {
9my ($argv, $out) = @_;
10my $pid = fork;
11if (not defined $pid) {
12die "fork failed: $!"
13} elsif ($pid == 0) {
14open STDOUT, ">&", $out;
15close $out;
16exec(@$argv) or die "cannot exec '$argv->[0]': $!"
17}
18return $pid;
19}
2021
# Wait for $pid to finish.
22sub finish_child {
23# Simplified from wait_or_whine() in run-command.c.
24my ($pid) = @_;
2526
my $waiting = waitpid($pid, 0);
27if ($waiting < 0) {
28die "waitpid failed: $!";
29} elsif ($? & 127) {
30my $code = $? & 127;
31warn "died of signal $code";
32return $code - 128;
33} else {
34return $? >> 8;
35}
36}
3738
sub xsendfile {
39my ($out, $in) = @_;
4041
# Note: the real sendfile() cannot read from a terminal.
4243
# It is unspecified by POSIX whether reads
44# from a disconnected terminal will return
45# EIO (as in AIX 4.x, IRIX, and Linux) or
46# end-of-file. Either is fine.
47copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
48}
4950
if ($#ARGV < 1) {
51die "usage: test-terminal program args";
52}
53my $master = new IO::Pty;
54my $slave = $master->slave;
55my $pid = start_child(\@ARGV, $slave);
56close $slave;
57xsendfile(\*STDOUT, $master);
58exit(finish_child($pid));