1#!/usr/bin/perl2use 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) = @_;2526my $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}3738sub xsendfile {39my ($out, $in) = @_;4041# Note: the real sendfile() cannot read from a terminal.4243# It is unspecified by POSIX whether reads44# from a disconnected terminal will return45# EIO (as in AIX 4.x, IRIX, and Linux) or46# end-of-file. Either is fine.47copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";48}4950if ($#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));