#! /usr/local/bin/perl -w # (c) Louis Granboulan 2000-2004 # tp6: expect, in perl if (scalar(@ARGV) == 1 and $ARGV[0] eq '-h') { print << 'EOT'; Usage: The first argument is a perl file containing a subroutine named "interact". The other arguments are used as a command that will interact with this subroutine. The subroutine can use CIN, COUT and CERR as the file descriptors for the I/O of the command. STDIN, STDOUT and STDERR are the I/O of this program. The subroutine can write in CIN, STDOUT and STDERR. The subroutine gets what is read from STDIN, COUT and CERR. Don't forget to close CIN if necessary. EOT exit 0; } unless (scalar(@ARGV) >= 2) { die "Syntax: $0 [interact] [command]\n" ." $0 -h\n"; } unless (-r $ARGV[0]) { die "Error: $ARGV[0] unreadable.\n"; } pipe (XIN,CIN); pipe (COUT,XOUT); pipe (CERR,XERR); unless (defined($pid = fork)) { die "Fork failed\n"; } if ($pid == 0) { close (CIN); close (COUT); close (CERR); open (STDIN , "<&XIN"); open (STDOUT, ">&XOUT"); open (STDERR, ">&XERR"); shift @ARGV; exec @ARGV; } else { $SIG{'CHLD'} = sub { wait }; $SIG{'HUP'} = $SIG{'TERM'} = sub { kill 'TERM', $pid; exit 0 }; # We connect childe I/O to father I/O close (XIN); close (XOUT); close (XERR); # We import "interact" subroutine require $ARGV[0]; # We wait some something from the user (STDIN) or from the program (COUT/CERR) # Infinite loop, until child (maple) dies or all inputs are closed. $rin = $win = $ein = ''; vec($rin,fileno(STDIN),1) = 1; vec($rin,fileno(COUT),1) = 1; vec($rin,fileno(CERR),1) = 1; use IO::Handle; CIN->autoflush(1); COUT->autoflush(1); interact(-1); # Initialisation while (0 <= select ($rout=$rin, $wout=$win, $eout=$ein, undef)) { if (vec($rout,fileno(STDIN),1)) { # Copy STDIN into CIN, closing CIN when STDIN is closed. if (eof STDIN) { vec($rin,fileno(STDIN),1) = 0; interact(-2); # End } else { $_ = ; interact(0,$_); # Something came from STDIN } } if (vec($rout,fileno(COUT),1)) { if (eof COUT) { vec($rin,fileno(COUT),1) = 0; } elsif(1) { sysread COUT, $_, 80; interact(1,$_); # Something came from COUT } } if (vec($rout,fileno(CERR),1)) { if (eof CERR) { vec($rin,fileno(CERR),1) = 0; } else { sysread CERR, $_, 80; interact(2,$_); # Something came from CERR } } } exit 0; }