�ɲɾ�����ӯ�����һ��ˣ��������С���˴��ͣ�������P���ҹ��ñ˽��ά�Բ��������˸߸ԣ�������ơ��ҹ��ñ�����ά�Բ���ˡ���˳^�ӣ������ӡ� ���ͯj�ӣ��ƺ���ӣ� ? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!PKQ1]R\\examples/kibitz/kibitznu[#!/usr/bin/perl # Original author: Author: Don Libes, NIST (tcl/expect) # Date written: December 5, 1991 # Date last editted: October 19, 1994 # Version: 2.11 # # Ported to Perl Expect module by: Lee Eakin, # Date first ported: January 28, 2001 # require 5.004; my ($pgm)=$0=~m|([^/]*)$|; $DEBUG=0; use strict; use Expect; use Getopt::Long; use vars qw($opt_noproc $opt_catu $opt_tty $opt_noescape $opt_escape $opt_silent $opt_proxy $opt_r); $|=1; my $prompt= $ENV{EXPECT_PROMPT} || '(?:%|#|\$)\s'; Getopt::Long::Configure('auto_abbrev','pass_through'); &GetOptions(qw(noproc catu tty=s noescape escape=s silent proxy=s r)) or &usage; &usage unless @ARGV or $opt_noproc; $opt_escape="\035" unless $opt_escape or $opt_noescape; my @flags; push @flags,'-tty',$opt_tty if $opt_tty; push @flags,'-silent' if $opt_silent; $Expect::Log_Stdout=0; my $stdin=Expect->exp_init(\*STDIN); my $stdout=Expect->exp_init(\*STDOUT); my $pid; my $user=shift; my $usernum; if ($opt_r) { print "KRUN"; $usernum=3; } else { $usernum=$user=~/^-\d+/ ? 2 : 1 } # User who originated kibitz session has $usernum == 1 on local machine. # User who is responding to kibitz has $usernum == 2. # User who originated kibitz session has $usernum == 3 on remote machine. # user 1 invokes kibitz as "kibitz user[@host]" # user 2 invokes kibitz as "kibitz -####" (some pid). # user 3 invokes kibitz as "kibitz -r user". my $sh; my $rhost; my $remsh; if ($usernum == 1) { unless ($opt_noproc) { if (@ARGV) { $sh=Expect->spawn("@ARGV") or die "$pgm: \"@ARGV\" spawn failed"; } else { $sh=Expect->spawn($ENV{SHELL} || '/bin/sh') or die "$pgm: shell spawn failed"; } } if ($user=~/([^@]+)@(.+)/) { $user=$1; $rhost=$2; } if ($rhost) { print "connecting to $rhost\n" unless $opt_silent; $opt_proxy||=$ENV{USER} || $ENV{LOGNAME} || `whoami` || `logname`; my $rcmd="rlogin $rhost -l $opt_proxy -8"; $remsh=Expect->spawn($rcmd); while (1) { $remsh->expect(60, -re => 'word:\s*$', -re => '\s+incorrect.*', -re => $prompt) or die "$pgm: connection to $rhost timed out\n"; if ($remsh->exp_match_number == 1) { print "password (for $opt_proxy) on $rhost: "; $stdin->exp_stty('-echo'); my $pswd=; $stdin->exp_stty('echo'); print "\n"; chomp $pswd; print $remsh "$pswd\r"; } elsif ($remsh->exp_match_number == 2) { die "$pgm: invalid password or account\n"; } elsif ($remsh->exp_match_number == 3) { last; } } print "starting $pgm on $rhost\n" unless $opt_silent; print $remsh "$pgm @flags -r $user;kill -9 $$\r"; $remsh->expect(120, -re => "$pgm @flags -r $user.*KRUN", -re => "$pgm @flags -r $user.*$pgm"."[^\r\n]*\r") or die "$pgm: unable to run $pgm on $rhost: timed out\n"; if ($remsh->exp_match_number == 2) { die "$pgm: unable to run $pgm on $rhost\n". "try rlogin by hand followed by \"$pgm $user\"\n"; } while (1) { $remsh->expect(120, -re => ".*\n",'KABORT','KDATA'); print $remsh->exp_match if $remsh->exp_match_number == 1; exit if $remsh->exp_match_number == 2; last if $remsh->exp_match_number == 3; } } } elsif ($usernum == 2) { ($pid)=$user=~/^-(\d+)/; } my $localio=(($usernum == 3) or not $rhost); my $inf; my $outf; my $exin; my $exout; if ($localio) { $pid||=$$; if ($usernum == 2) { $inf="/tmp/exp1.$pid"; $outf="/tmp/exp0.$pid"; } else { $inf="/tmp/exp0.$pid"; $outf="/tmp/exp1.$pid"; } } else { $exin=$remsh; $exout=$remsh; } if ($usernum == 2) { die "$pgm: Huh? No one is asking you to $pgm.\n" unless -r $inf; open OUT,">$outf" or die "$pgm: write pipe open failed: $!\n"; select((select(OUT),$|=1)[0]); open IN,$inf or die "$pgm: read pipe open failed: $!\n"; select((select(IN),$|=1)[0]); $stdin->exp_stty('-echo raw'); $exin=Expect->exp_init(\*IN); $exout=Expect->exp_init(\*OUT); if ($opt_escape) { &vprint("Escape sequence is $opt_escape"); print "\r\n"; $stdin->set_seq($opt_escape,\&local_esc); } unlink $inf; $exin->set_group($stdout); $stdin->set_group($exout); Expect::interconnect($exin,$stdin); exit; } if ($localio) { $SIG{'INT'}=$SIG{'QUIT'}=$SIG{'TERM'}=eval "sub {unlink '$inf','$outf';exit}"; my $fifocmd; foreach (qw(/usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /bin /sbin)) { $fifocmd="$_/mkfifo %s",last if -x "$_/mkfifo"; } unless ($fifocmd) { foreach (qw(/usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /bin /sbin /usr/etc /etc)) { $fifocmd="$_/mknod %s p",last if -x "$_/mknod"; } } die "$pgm: could not determine how to make a fifo - where is mknod?\n" unless $fifocmd; system(sprintf $fifocmd,$inf) == 0 or die "$pgm: could not make fifo \"$inf\": $?\n"; system(sprintf $fifocmd,$outf) == 0 or unlink($inf), die "$pgm: could not make fifo \"$outf\": $?\n"; chmod 0666,$inf,$outf; print "asking $user to type: $pgm -$pid\n" unless $opt_silent; open WQ,"|/usr/bin/write $user $opt_tty" or unlink($inf,$outf), die "$pgm: write command failed: $!\n"; print WQ "Can we talk? Run: $pgm -$pid\n"; close WQ; open IN,$inf or die "$pgm: read pipe open failed: $!\n"; select((select(IN),$|=1)[0]); open OUT,">$outf" or die "$pgm: write pipe open failed: $!\n"; select((select(OUT),$|=1)[0]); $stdin->exp_stty('-echo raw'); $exin=Expect->exp_init(\*IN); $exout=Expect->exp_init(\*OUT); unlink $inf; } if ($usernum==3) { print "KDATA"; $exin->set_group($stdout); $stdin->set_group($exout); Expect::interconnect($exin,$stdin); } else { if ($opt_escape) { &vprint("Escape sequence is $opt_escape"); print "\r\n"; $stdin->set_seq($opt_escape,\&local_esc); } if ($opt_noproc) { $exin->set_group($stdout); $stdin->set_group($exout); Expect::interconnect($exin,$stdin); } else { $exin->set_group($sh); $stdin->set_group($sh); $sh->set_group($stdout,$exout); Expect::interconnect($exin,$stdin,$sh); } $sh->hard_close; } unlink $inf,$outf; exit; sub local_esc { print "\r\n$pgm:\r\n E) Exit program\r\n any other key to return to program\r\n"; my $ans=getc; print "\r\n"; exit if $ans eq 'E'; print "returning to $pgm\r\n"; } sub vprint { my @keys=@_; foreach (@keys) { s/([\200-\277])/'M-'.chr(ord($1)^128)/eg; s/([\000-\011\013-\037\177])/"^".chr(ord($1)^ord('@'))/eg; } print @keys; } sub usage { print STDERR "Usage: $pgm [options] user [program ...]\n"; print STDERR " or: $pgm [options] user\@host [program ...]\n"; exit 1; } PKQ1]]examples/kibitz/kibitz.mannu[.TH KIBITZ 1 "28 January 2001" .SH NAME kibitz \- allow two people to interact with one shell .SH SYNOPSIS .B kibitz [ .I kibitz-args ] .I user [ .I program program-args... ] .br .B kibitz [ .I kibitz-args ] .I user@host [ .I program program-args... ] .SH INTRODUCTION .B kibitz allows two (or more) people to interact with one shell (or any arbitrary program). Uses include: .RS .TP 4 \(bu A novice user can ask an expert user for help. Using .BR kibitz , the expert can see what the user is doing, and offer advice or show how to do it right. .TP \(bu By running .B kibitz and then starting a full-screen editor, people may carry out a conversation, retaining the ability to scroll backwards, save the entire conversation, or even edit it while in progress. .TP \(bu People can team up on games, document editing, or other cooperative tasks where each person has strengths and weaknesses that complement one another. .SH USAGE To start .BR kibitz , user1 runs kibitz with the argument of the user to kibitz. For example: kibitz user2 .B kibitz starts a new shell (or another program, if given on the command line), while prompting user2 to run .BR kibitz . If user2 runs .B kibitz as directed, the keystrokes of both users become the input of the shell. Similarly, both users receive the output from the shell. To terminate .B kibitz it suffices to terminate the shell itself. For example, if either user types ^D (and the shell accepts this to be EOF), the shell terminates followed by .BR kibitz . Normally, all characters are passed uninterpreted. However, if the escape character (described when .B kibitz starts) is issued, the user may talk directly to the .B kibitz interpreter. Currently the only option is to exit the program. Also, job control may be used while in the interpreter, to, for example, suspend or restart .BR kibitz . Various processes can provide various effects. For example, you can emulate a two-way write(1) session with the command: kibitz user2 sleep 1000000 .SH ARGUMENTS .B kibitz takes arguments, these should also be separated by whitespace. The .B \-noproc flag runs .B kibitz with no process underneath. Characters are passed to the other .BR kibitz . This is particularly useful for connecting multiple interactive processes together. In this mode, characters are not echoed back to the typist. .B \-noescape disables the escape character. .BI \-escape " char" sets the escape character. The default escape character is ^]. .B \-silent turns off informational messages describing what kibitz is doing to initiate a connection. .BI \-tty " ttyname" defines the tty to which the invitation should be sent. If you start .B kibitz to user2 on a remote computer, .B kibitz performs a .B rlogin to the remote computer with your current username. The flag .BI \-proxy " username" causes .B rlogin to use .I username for the remote login (e.g. if your account on the remote computer has a different username). If the .B -proxy flag is not given, .B kibitz tries to determine your current username by (in that order) inspecting the environment variables USER and LOGNAME, then by using the commands .B whoami and .BR logname . The arguments .B -noescape and .B -escape can also be given by user2 when prompted to run .BR kibitz . .SH MORE THAN TWO USERS The current implementation of kibitz explicitly understands only two users, however, it is nonetheless possible to have a three (or more) -way kibitz, by kibitzing another .BR kibitz . For example, the following command runs .B kibitz with the current user, user2, and user3: % kibitz user2 kibitz user3 Additional users may be added by simply appending more "kibitz user" commands. .SH CAVEATS .B kibitz assumes the 2nd user has the same terminal type and size as the 1st user. If this assumption is incorrect, graphical programs may display oddly. .B kibitz handles character graphics, but cannot handle bitmapped graphics. Thus, .nf % xterm -e kibitz will work % kibitz xterm will not work .fi .B kibitz uses the same permissions as used by rlogin, rsh, etc. Thus, you can only .B kibitz to users at hosts for which you can rlogin. Similarly, .B kibitz will prompt for a password on the remote host if rlogin would. If you .B kibitz to users at remote hosts, .B kibitz needs to distinguish your prompt from other things that may precede it during login. (Ideally, the end of it is preferred but any part should suffice.) If you have an unusual prompt, set the environment variable EXPECT_PROMPT to an egrep(1)-style regular expression. Brackets should be preceded with one backslash in ranges, and three backslashes for literal brackets. The default prompt r.e. is "(%|#|\\$)\\s". .B kibitz requires the .B kibitz program on both hosts. .B kibitz requires .BR expect (1). This version "should be" but is not compatible with the original program (yet). .SH BUGS An early version of Sun's tmpfs had a bug in it that causes .B kibitz to blow up. If .B kibitz reports "error flushing ...: Is a directory" ask Sun for patch #100174. If your Expect is not compiled with multiple-process support (i.e., you do not have a working select or poll), you will not be able to run kibitz. .SH ENVIRONMENT The environment variable SHELL is used to determine the shell to start, if no other program is given on the command line. If the environment variable EXPECT_PROMPT exists, it is taken as a regular expression which matches the end of your login prompt (but does not otherwise occur while logging in). See also CAVEATS above. If the environment variables USER or LOGNAME are defined, they are used to determine the current user name for a .B kibitz to a remote computer. See description of the .B -proxy option in ARGUMENTS above. .SH SEE ALSO .BR Perl (1), .BR Expect (3), .BR Tcl (3), .BR libexpect (3), .br .I "Exploring Expect: A Tcl-Based Toolkit for Automating Interactive Programs" \fRby Don Libes, O'Reilly and Associates, January 1995. .br .I "Kibitz \- Connecting Multiple Interactive Programs Together", \fRby Don Libes, Software \- Practice & Experience, John Wiley & Sons, West Sussex, England, Vol. 23, No. 5, May, 1993. .SH AUTHOR Don Libes, National Institute of Standards and Technology .B kibitz is in the public domain. NIST and I would appreciate credit if this program or parts of it are used. Ported to .B Perl .B Expect module by Lee Eakin, Texas Instruments Inc. PKQ1]U$BBexamples/kibitz/Changelognu[Fri Feb 9 11:02:44 CST 2001 Lee Eakin removed double quotes from write message (easier to cut-n-paste) fixed non-functional escape char changed pipe names to match those used in the original kibitz added man page (hacked from original tcl-kibitz man page) added README file PKQ1]G){examples/kibitz/READMEnu[This is a port of the tcl/expect script 'kibitz' to the perl Expect module. I have always found it useful to debug user problems and in training new admins. Since the wonderful Expect module has come into existance I've had no need to install tcl/expect except to get the kibitz program on my system. I finally got around to converting it for my own use and thought the rest of the world might find a similar use for it. It "should be", but is not quite compatible with the original. I'm working on that. I also plan to port xkibitz unless someone beats me to it. The man page is hacked from the original kibitz man page. This version also takes a shortcut when deciding if the connection should use rlogin. If user@host is specified it assumes remote. If only user is given it assumes local. All options valid for the original program are accepted, but some are ignored (-catu). -Lee PKQ1]8examples/expect_calc.plnu[use strict; use warnings; use Expect; my $e = Expect->new; $e->spawn($^X, "examples/calc.pl") or die; $e->log_stdout(0); $e->raw_pty(1); $e->send("19+23\n"); $e->expect(1, "19+23"); print 'Match: <', $e->match, ">\n"; print 'Before: <', $e->before, ">\n"; print 'After: <', $e->after, ">\n"; $e->clear_accum; $e->expect(1, '-re' => qr/'\d+'/); print 'Match: <', $e->match, ">\n"; print 'Before: <', $e->before, ">\n"; print 'After: <', $e->after, ">\n"; $e->close; PKQ1]Vexamples/calc.plnu[use strict; use warnings; while (my $row = <>) { chomp $row; print "Input: '$row' = "; my $res = eval $row; print "'$res' :Output\n"; } PKQ1]"qexamples/ssh.plnu[#!/usr/bin/perl # # A Simple Terminal Resizing Example # (C) 2006 Jeff Carr # This script can be used under the same terms as Perl. # # This script is a simple example of how handle terminal # window resize events (transmitted via the WINCH signal) # -- Jeff Carr # # NOTE: I (the Expect maintainer) strongly object against using Expect # to automate ssh login. There are better methods, see ssh-keygen. # If you use this example as a stub to control a remote application, # please remove the password-part and use public-key authentication # instead. # -- Roland Giersig # if( ! defined $ARGV[0] ) { print "Usage: ssh.pl [ [ ] ]\n"; exit; } my ($host, $username, $password) = @ARGV; $username = $ENV{USER} if $username eq ""; use Expect; use IO::Pty; my $spawn = new Expect; $spawn->raw_pty(1); # This gets the size of your terminal window $spawn->slave->clone_winsize_from(\*STDIN); my $PROMPT; # This function traps WINCH signals and passes them on sub winch { my $signame = shift; my $pid = $spawn->pid; $shucks++; print "count $shucks,pid $pid, SIG$signame\n"; $spawn->slave->clone_winsize_from(\*STDIN); kill WINCH => $spawn->pid if $spawn->pid; } $SIG{WINCH} = \&winch; # best strategy $spawn=Expect->spawn("ssh $username\@$host"); # log everything if you want # $spawn->log_file("/tmp/autossh.log.$$"); my $PROMPT = '[\]\$\>\#]\s$'; my $ret = $spawn->expect(10, [ qr/\(yes\/no\)\?\s*$/ => sub { $spawn->send("yes\n"); exp_continue; } ], [ qr/assword:\s*$/ => sub { $spawn->send("$password\n") if defined $password; } ], [ qr/ogin:\s*$/ => sub { $spawn->send("$username\n"); exp_continue; } ], [ qr/REMOTE HOST IDEN/ => sub { print "FIX: .ssh/known_hosts\n"; exp_continue; } ], [ qr/$PROMPT/ => sub { $spawn->send("echo Now try window resizing\n"); } ], ); # Hand over control $spawn->interact(); exit; PKQ1]H sstutorial/5.A.topnu[#!/usr/bin/perl # Here we are doing this again only this time we'll do it #without Echoing the password. $RSH='/usr/bin/ssh'; $host_to_login_to=shift(@ARGV); use Expect; print "Enter password: "; # First we have to initialize STDIN in to an expect object. $stdin=Expect->exp_init(\*STDIN); # Now turn off echoing $stdin->exp_stty('-echo'); # The easy way to do this is: #$password=; #chop $password; # The somewhat harder way is to use $stdin->expect. This would look like: # ($match_num,$error,$match,$before,$after)=$stdin->expect(undef,"\r"); $password = $before; # Turn echo back on $stdin->exp_stty('echo'); # print that newline that wasn't echoed print "\n"; $rsh=Expect->spawn($RSH,$host_to_login_to); # Look for a password prompt. $rsh->expect(30,'-re','word:\s$')||(die"Never got password prompt\n"); print $rsh "$password\r"; # Look for a prompt. Prompt can be # $ > or ] followed by a whitespace. $prompt = '[\]\$\>\#]\s$'; # Note the use of -re $rsh->expect(30,'-re',$prompt)||(die "Never got prompt on host\n"); # Start top print $rsh "exec top\r"; # OK, now return control to user. $rsh->interact(); PKQ1]j))tutorial/6.B.modem-initnu[#!/usr/bin/perl # This is a very brief script that demonstrates send_slow(). This #command is chiefly for talking to modems and the like where if you send #it stuff too fast it can get mad at you. # Also demonstrated is how to talk to a bidirectional device #handle. # # This example has been changed in 1.05 so that it actually works. :-) use Expect; $device="/dev/modem" unless $device = shift(@ARGV); # open the device open(DEVICE,"+>$device") || die "Couldn't open $device, $!\n"; # Expectize it. note the \* which we do because we didn't use the OO # method of opening the device. $modem=Expect->exp_init(\*DEVICE); # Let's watch the output. Once again, output isn't automatically # watched since it was an initialized handlde and not a process. $modem->log_stdout(1); # Put it in raw mode w/ no echoing so it will operate as expected. $modem->exp_stty('raw','-echo'); # Send it an ATZH0\r to reset its state. print "Initializing modem\n"; $modem->send_slow(.5,"ATZH0\r"); # How about we look for an OK? $modem->expect(30,'-re','^OK\r?$')|| warn "Never got OK from modem\n"; print "Modem initialized.\n"; # Now let's interact with it so the user can talk to it, dial it out, # whatever. This is basically a poor man's term program. # When you interact() with a handle it puts STDIN in raw mode so # you are assured of interacting cleanly, no escape chars, etc. # This is usually what you want. Here however it's nice to be able to # escape from the session without doing any extra work. So let's make # an escape character of ^W. print "Beginning interaction, escape character is ^W.\n"; $modem->interact(\*STDIN,"\027"); # Done? Reset the modem, close the handle. print $modem "+++"; sleep 3; print $modem "ATZH0\r"; sleep 1; # Grab any output ready on the handle, toss it. $modem->expect(0); $modem->hard_close(); PKQ1]O] tutorial/5.B.topnu[#!/usr/bin/perl # Here we set manual_stty on the process so we can do things like #hit ^Z to stop it instead of the ^Z going to the process on the other machine. # This is to say, normally when you interact with a process STDIN is #put in raw mode so everything you type talks to the process at the other end. # Picture this. When you telnet somewhere and start a process (top #for example) you are talking to telnet in raw mode. If you press ^Z it #goes through telnet to the shell on the remote machine and the process #at the other end is stopped. Here we're going to make it so raw mode is #never set and when you press ^Z or ^C it will stop/interrupt Expect. # Also briefly demonstrated is the use of Expect::interconnect(), #a more general/versatile alternative to interact. use Expect; # Debugging anyone? # $Expect::Log_Stdout=1; # $Expect::Exp_Internal=1; # $Expect::Debug=1; $RSH='/usr/bin/ssh'; $host_to_login_to=shift(@ARGV); print "Enter password: "; $|=1; # First we have to initialize STDIN in to an expect object. $stdin=Expect->exp_init(\*STDIN); # Now turn off echoing $stdin->exp_stty('-echo'); # The easy way to do this is: #$password=; #chop $password; # The somewhat harder way is to use $stdin->expect. This would look like: # ($match_num,$error,$match,$before,$after)=$stdin->expect(undef,"\n"); $password = $before; # Turn echo back on $stdin->exp_stty('echo'); # print that newline that wasn't echoed print "\n"; #$Expect::Exp_Internal=1; $rsh=Expect->spawn($RSH,$host_to_login_to); # Look for a password prompt. $rsh->expect(30,'-re','word:\s$')||(die"Never got password prompt\n"); print $rsh "$password\r"; # Look for a prompt. Prompt can be # $ > or ] followed by a whitespace. $prompt = '[\]\$\>\#]\s$'; # Note the use of -re $rsh->expect(30,'-re',$prompt)||(die "Never got prompt on host\n"); # Start top print $rsh "exec top\r"; # We already have an inited handle for STDIN above which we can use. # We don't just do $rsh->interact because it will go monkeying # with tty settings by default (set it raw). $stdin->manual_stty(1); # Instead we use interconnect directly. # The trick here is to make sure: # 1. Everything listening to a handle is added to its # listen group. # 2. Only what you want is jabbering at STDOUT. # # In this case only $rsh will talk to STDOUT so we don't have to # change any log_stdout() settings. $stdin->set_group($rsh); Expect::interconnect($stdin,$rsh); PKQ1]??o tutorial/2.A.ftpnu[#!/usr/bin/perl # This example demonstrates how to spawn an ftp process, have it #log in to a host, and grab a file off the host. This should give you a #general idea of how to spawn processes and talk to them. # The first thing I do when attempting to automate a process is do it #by hand, so you know what interaction with the process should look like. # I highly recommend you read the information on debugging in chapter #3 before actually trying this yourself. # # Usage: script ftphost file1 [file2 file3.. ] use Expect; # Optional debugging, explained later. # $Expect::Debug=1 # $Expect::Exp_Internal=1; # $Expect::Log_Stdout=0; # On by default. $host = shift @ARGV; # Let the host be the first argument we are given. @files = @ARGV; # Let the names of the files be the remaining arguments. # Make sure we're trying to get something. unless ($host ne '' && @files > 0) { print STDERR <spawn("ftp $hostname")) || die "Couldn't spawn ftp, $!"; # Look for a username prompt. On my box this looks like: # "Name (ftp.cdrom.com:tex): " # So, let's see what our username is. $username = $ENV{'USER'}; # Time out if we don't get it within 30 seconds. unless ($ftp->expect(30,"Name ($hostname:$username): ")) { die "Never got username prompt on $hostname, ".$ftp->exp_error()."\n"; } # Ok, so we have the username prompt. Let's send it "anonymous". # Note how I follow with a \r. print $ftp "anonymous\r"; # And we want a password prompt now. # On my box this looks like: # 331 Guest login ok, send your complete e-mail address as password. # Password: # Where there are no spaces after the password. This is important to note # since, if there were a space, we might try sending a password before # the ftp server finished giving us a prompt or if we were looking for a space # and there wasn't one we might end up not matching. # To save time I cut and pasted most of the line above where we grabbed the # username prompt. unless ($ftp->expect(30,"Password:")) { die "Never got password prompt on $hostname, ".$ftp->exp_error()."\n"; } # Grabbing our actual domain would be the better thing to do here but is # outside the scope of this example. print $ftp "$username\@mycompany.com\r"; # Now we look for a prompt, having (we hope) successfully logged in. unless ($ftp->expect(30,"ftp> ")) { die "Never got ftp prompt after sending username, ".$ftp->exp_error()."\n"; } # Ok. We have a prompt on the foreign machine, so let's get the files. # Notice that at the end of each loop we are at an ftp> prompt. foreach $file (@files) { print $ftp "get $file\r"; unless ($ftp->expect(30,"ftp> ")) { die "Never got ftp prompt after attempting to get $file, ".$ftp->exp_error()."\n"; } } # We should have all the files. If this is the end of the script we can # quit without bothering to close the process. Perl will take care of it # for us. Later examples will demonstrate the differences between # close(), soft_close(), and hard_close(). PKQ1]c tutorial/2.B.rloginnu[#!/usr/bin/perl # There are three new things in this example. First is the concept #of closing the process, second is the concept of using regular #expressions in match patterns, and third is the concept of grabbing #stuff that is in the process's buffer. This last part is like when you #telnet to a host, do ls, and want to know the name of the files returned: # # #somehost$ ls #thing #thing.gz #core #Mail #mail #somehost$ # # When you use the expect() function it is possible to grab the #data before the next patter looked for. in this case if you were #looking for "somehost$ " you could get the names of the files returned #in the ls. In the example below the output of the 'id' command is grabbed #for use by the program. # # What this example tries to do is log in to foreign hosts and #grab the user id on each host. # use Expect; # Optional debugging, explained later. # $Expect::Debug=1 # $Expect::Exp_Internal=1; # $Expect::Log_Stdout=0; # On by default. die "Usage: $0 host1 host2... hostn\n" unless defined $ARGV[0]; @hosts = @ARGV; # Ssh would be better, rlogin is used here because it is more familiar. foreach $host (@hosts) { $rlogin=Expect->spawn("rlogin $host"); $rlogin->expect(30,"ssword: ") || die "Never got password prompt on $host, ".$rlogin->exp_error()."\n"; # We got the prompt, so send a password. print $rlogin "H4yB3vis\r"; # Now we look for a shell prompt. Notice the use of the regular expression. # To use a regexp make the previous argument '-re'. # expect will match on the hostname followed by a %, >, or $ followed by # whitespace. Notice that the regular expression part is in single quotes. # This is so that perl won't interpret control characters such as # whitespace (\s) for us until it gets in to the pattern matching engine. # my prompt is "darkwing$ ". Yours is probably different. # The below expect() call will return 1 if it matches the closed by foreign # host string or 2 if it matches the regular expression. # undef is returned if nothing matches. $match=$rlogin->expect(30,"closed by foreign host","-re",$host.'[%>$]\s'); die "Dumped by server\n" if $match == 1; die "Never got shell prompt on $host, ".$rlogin->exp_error()."\n" unless $match; # Ok, so we have a shell prompt. let's give it the 'id' command. print $rlogin "id\r"; # Now, we know that because ther terminal will echo "id\r" back to us # we should grab it so it won't muck with our final output. # Also, on most terminals if you send a carriage return it will respond # with a carriage return-newline combination. So we do: $rlogin->expect(30,"id\r\n"); # which clears id out of the buffer. Note that I used \r\n in double # quotes instead of single quotes because I want perl to look for # a carriage return instead of the literal \r\n. If I had instead done # $rlogin->expect(30,'-re','id\r\n'); it would work because it gets # tossed in to a regular expression where \r and \n get evaluated. # Now when we use expect() to find the next prompt the output of the last # command will be in the buffer that holds output between expect() calls. # this output should be 'before' we match. # I'm going to define what prompt we're looking for ahead of time to # make the call to expect more readable. $prompt = $host.'[%>$]\s'; $rlogin->expect(30,'-re',$prompt); # Yet another way to find out if we had a successful match is to test for # an error. die "Never got prompt after sending 'id' command\n" if $rlogin->exp_error(); # And the output of id: print "id on $host: $rlogin->exp_before()"; # Now, we do a hard close here. We are positively done with rlogin and we # know that it won't be ending by itself. This would be unlike, say, # a command like "tail /etc/passwd" which will exit as soon as it is finished # sending us its output. For that sort of a command soft_close() would # suffice. # It is important that you close rlogin so that processes don't # pile up eating your system resources during further loops through # hosts. $rlogin->hard_close(); # next host } PKQ1]\tutorial/READMEnu[ NOTE: This tutorial is completely outdated and needs a major overhaul. I still leave it in because it provides some additional info, but don't expect to be able to learn anything from it... The tutorial is in order of how I would want to learn to use this tool. very briefly, here's an index: 1. Introduction, how/why one would want to use this tool. 2. Spawn, expect- how to talk to a process. 3. Debugging. 4. Interacting with a spawned process. 5. Monkeying with tty settings. Good for grabbing passwords, among other things. 6. Miscellaneous extra functions. Let me know if there's something you'd like to see that isn't here. PKQ1] | | tutorial/1.A.Intronu[ Why is this tool useful? Chances are if you are reading this you probably have already used the fine Expect for tcl, and possibly even read Exploring Expect. You are interested in learning how to accomplish the same things you've done in tcl using perl, or perhaps are just totally irritated at tcl. Expect is a generic tool for talking to processes that normally require user interaction. This might be running an ftp client to grab a file, telnetting to a router to grab statistics or reset an interface. Or, as in the case of a place I recently administered, to start up a secure webserver without having to be physically at the machine to enter the super secret password. Expect talks to processes through ptys. To it, a process is mostly just a bidirectional file handle, much the same as a socket. In fact, it is possible to take a filehandle you've already used and pass it off to expect to interact with. Now, something you might say at this point is "well, but there are tools that I can use to do that with for more common protocols like telnet and ftp already, such as Net::Ftp and Net::Telnet. Why would I want to use your tool?". This is true. You might never want to use it. However, there are a few advantages Expect has over similar modules: 1. A consistent interface. You don't have to remember the syntax for the other tools. 2. It is more intuitive (my opinion, of course) because you already know how to use the clients you are familiar with. Once you learn how to talk to a process using Expect you will have an easy time automating your other tasks. 3. It is more versatile. With Expect you can connect multiple processes together, write to log files, talk to sockets, etc. 4. Consistent debugging. Debugging, IMHO, is much easier in Expect than in other tools because you have the ability to watch the interaction take place, and it's really pretty easy to use. One serious disadvantage of Expect is that scripts generated using it are generally non-portable. The way a client 'looks' is important to building a script to talk to it. Interacting with a client on DG-UX may be very different than the equivalent client on SunOS. Or, and ncftp would be a good example of this, a client may be different between versions. Similarly, if an administrator changes versions of a server it might send back different prompts than what you are looking for. These are things you should be aware of. PKQ1]9tutorial/3.A.debuggingnu[#!/usr/bin/perl # This example demonstrates how to use the debugging features in #expect. They're reasonably straghtforward. # # There are 3 basic ways you can debug a script: # # 1. Log_Stdout # # By setting $Expect::Log_Stdout you control whether or not processes #will echo to the screen or not. Having it turned on can be helpful so you #can watch what a process is doing. Alternately, for a process that is already #running you can do $process->log_stdout(1); which will turn on process #output for the process from that instant on. $process->log_stdout(0) will #turn it off. # By default $Expect::Log_Stdout == 1. Initialized handles (discussed #later) may also echo to STDOUT, but they don't do so by default. You have #to manually tell them to echo. You wouldn't want your log file jabbering at #you would you? Anyway, that will make sense later. # # 2. Exp_Internal # # Setting $Exp_Internal=1 (or $process->exp_internal(1)) will output #pattern matching information for expect() calls to STDERR. You can trap #this by doing "perl expect_script.pl 2>debug.out" if you are using any of #the bourne-ish shells. For people who use csh, don't. "exec bash" will take #care of that straightaway. This is handy so program output and debugging output #don't go to the same place. # # 3. Debug # # Setting $Expect::Debug = debug level(or $process->debug(debug level)) #will show other stuff, such as pids, output during interaction, and other #miscellaneous output not covered by the above two items. In combination with #Exp_Internal you can capture a lot of good information about what your script #is doing. Debugging info also goes to STDERR. # # # This example will show (lots) of debugging info. use Expect; $Expect::Log_Stdout=1; $Expect::Debug=3; $Expect::Exp_Internal=1; # lpc is a bsd printer control program. It's included in every Unix I # deal with. $lpc = Expect->spawn("lpc"); $lpc->expect(30,"lpc> ") && print $lpc "stat\r"; $lpc->hard_close(); PKQ1]ϟQ tutorial/6.A.smtp-verifynu[#!/usr/bin/perl -w # Here's something that is of actual use, and should be relatively #portable. # Given an email address and a mail server name check to see if #the address is deliverable on that box. This can be used for address #verification or spam relay checking. # # The point of this is to show how you can take a generic handle #and interact with it. In this example a socket is used. use Expect; use IO::Socket; # $Expect::Debug=1 # $Expect::Exp_Internal=1; # $Expect::Log_Stdout=0; # On by default. This does not affect Expect # objects created with Expect->exp_init() however. By default the output of # those handles will not be output to the screen. use $handle->log_stdout(1) # to turn that on after you initialize the handle. # Arg. 0 hostname of mail server $mail_server=shift(@ARGV); # Remaining args will be email addresses. @addresses=@ARGV; die "Usage: $0 mail_server address1 [address2 address3.. addressN]\n" unless @addresses; # Connect to mail server. This is right out of perldoc IO::Socket. $smtp_sock = IO::Socket::INET->new(PeerAddr => "$mail_server:smtp(25)"); die "Couldn't connect to $mail_server, $!" unless defined $smtp_sock; # Turn the socket in to an expect object. $smtp_session=Expect->exp_init($smtp_sock); # By default Expect doesn't print out the output of an exp_inited item. # Generally you don't want handles jabbering at you. In this case # we might turn it on so we can watch what happens. #$smtp_session->log_stdout(1); # Watch debugging? #$smtp_session->exp_internal(1); # Ok, now let's see if the mail server wants to talk to us: $smtp_session->expect(30,'-re','^220.*\n')||die "Bad response from server\n"; # Cool. Now let's introduce ourselves to the server. # There are many other ways to gain the FQDN of this box. This is mine, # and it's easy. This of course assumes you have uname and that -n returns # your hostname. $my_hostname = `uname -n`; chomp $my_hostname; print $smtp_session "HELO $my_hostname\n"; # My server responds with a 250 + stuff. Presumably that's RFC compliant. # Feel free to go look :-) $smtp_session->expect(30,'-re','^250.*\n')||die "Bad response after HELO\n"; # Try sending mail.. I should probably use my username rather than user@ # but I'm too lazy. print $smtp_session "MAIL FROM:\n"; $smtp_session->expect(30,'-re','^250.*\n')||die "Bad response after FROM\n"; # Now to check each address... foreach $address (@addresses) { print $smtp_session "RCPT TO:<$address>\n"; # Now check the status... ($match_num,$error,$match)=$smtp_session->expect(30,'-re','^\d\d\d'); die "Never got response back after trying RCPT to $address\n" if $error; $status = $match; # Read to the newline so the server will be ready for the next address. # If the server spit back something other than 250 we'll display the # Whole error. ($match_num,$error,$match)=$smtp_session->expect(30,'-re','.*\n'); die "Server seems to have hung after trying address $address\n" if $error; if ($status == 250) { $status = "ok\n"; } else { $status.=$match; } print "Status of address $address: $status"; } # Be good citizens, send a quit. print $smtp_session "QUIT\n"; # At which point it should die nicely. $smtp_session->soft_close(); PKQ1]`tutorial/4.A.topnu[#!/usr/bin/perl # This example is a replay of sorts of the rlogin example #before except in this example we turn control of the process back #to the user through use of interact(). use Expect; # $Expect::Debug=2; $Expect::Exp_Internal=1; $RSH='/usr/local/bin/ssh'; $host_to_login_to=shift(@ARGV); # Get the password. We will show how to do this without printing the # password to the screen later. print "Enter password: "; $password=; chomp $password; $rsh=Expect->spawn($RSH,$host_to_login_to); # Look for a password prompt. $rsh->expect(30,'-re','word:\s$')||(die"Never got password prompt\n"); print $rsh "$password\r"; # Look for a prompt. Prompt can be # $ > or ] followed by a whitespace. $prompt = '[\]\$\>\#]\s$'; # Note the use of -re $rsh->expect(30,'-re',$prompt)||(die "Never got prompt on host\n"); # Start top print $rsh "exec top\r"; # OK, now return control to user. $rsh->interact(); PKQ1]/ README.mdnu[###Status [![Build Status](https://travis-ci.org/jacoby/expect.pm.png)](https://travis-ci.org/jacoby/expect.pm) Expect.pm ========= Expect requires the latest version of IO::Tty, also available from CPAN. IO::Stty has become optional but I'd suggest you also install it. If you use the highly recommended CPAN module, there is a Bundle::Expect available that installs everything for you. If you prefer manual installation, the usual perl Makefile.PL make make test make install should work. Note that IO::Tty is very system-dependend. It has been extensively reworked and tested, but there still may be systems that have problems. Please be sure to read the FAQ section in the Expect pod manpage, especially the section about using Expect to control telnet/ssh etc. There are other ways to work around password entry, you definitely don't need Expect for ssh automatisation! The Perl Expect module was inspired more by the functionality of Tcl/Expect than any previous Expect-like tool such as Comm.pl or chat2.pl. The Tcl version of Expect is a creation of Don Libes (libes@nist.gov) and can be found at http://expect.nist.gov/. Don has written an excellent in-depth tutorial of Tcl/Expect, which is _Exploring Expect_. It is the O'Reilly book with the monkey on the front. Don has several references to other articles on the Expect web page. I try to stay as close to Tcl/Expect in interface and semantics as possible (so I can refer questions to the Tcl/Expect docu). Suggestions for improvement are always welcome. There are two mailing lists available, expectperl-announce and expectperl-discuss, at http://lists.sourceforge.net/lists/listinfo/expectperl-announce and http://lists.sourceforge.net/lists/listinfo/expectperl-discuss Thanks to everybody who wrote to me, either with bug reports, enhancement suggestions or especially fixes! Dave Jacoby (maintaner of Expect.pm) jacoby@cpan.org 2015-10-31 PKQ1]Ҭqy2y2Changesnu[Revision history for CPAN module Expect 1.35 2017-05-18 - Added AUTHOR key, listing all maintainers 1.34 2017-05-18 Official maintainer JACOBY (Dave Jacoby) - Added a MANIFEST so that "make dist" will work 1.33 2016-06-08 Remove dependency on Test::Exception 1.32 2014-10-26 Skip bc tests. https://rt.cpan.org/Ticket/Display.html?id=98495 1.31 2014-09-02 Eliminate the requirement for ExtUtils::MakeMaker 1.70. Now any ExtUtils::MakeMaker should work on the client side. In the tests, add special treatment for $^O=midnightbsd and dragonfly. and for $^O=linux as well. Test t/11-calc.t also got some special treatment. 1.30 2014-08-22 RT #47834 After a failed call to ->expect the ->match, and ->after will return undef and ->before will return the content of the accumulator. Earlier they retained the values obtained during the last successful match. ->before will return undef at the first time but later, if we call ->clear_accum, it will start returning the empty string. CONFIGURE_REQUIRES ExtUtils::MakeMaker 6.70 Some test updates. 1.29 2014-08-14 Official co-maintainer SZABGAB (Gabor Szabo) Update documentation according to RT #60722 1.28 2014-08-14 Croak if undef passed to _trim_length Fix double planning on skipped test 1.27 2014-08-13 Remove $& and $` fixing the rest of RT #61395 Add more test cases. Various code refactoring declaring loop variables; parameter passing; return undef; etc. 1.26 2014-08-12 Skip the bc test on OS-es where it has been failing. Stop inheriting from Exporter. Eliminate $` and $' from the code. part of (RT #61395) This fix might break some existing code n some extreme cases when the regex being matched has a lookbehind or a lookahead at the edges. 1.25 2014-08-05 Fix test count. 1.24 2014-08-04 More test diagnostics. Tests added for RT #62359 1.23 2014-07-29 Refactoring test script. Eliminate indirect calls in the code and in the docs. Use Perl::Tidy to unify layout. Add use warnings; IO::Tty prerequisite version 1.03 => 1.11 1.22 2014-07-27 New unofficial mainainer (Gabor Szabo) Merge .pod and .pm and move them to lib/ Move the test and the code to standard location /t in the distribution. Eliminate indirect calls in tests. Use Test::More instead of home-brew testing. Typos fixed in pod RT #86852. Changes file re-ordered and standardized. 1.21 2007-08-13 1.20 2006-07-21 + added early return to send and send_slow if filehandle was closed + added test for send_slow ! fixed bug in expect() param handling (exact pattern "0" was ignored) ! fixed bug in _make_readable() + now included example ssh.pl in MANIFEST so it gets packaged :-( 1.19 2006-07-17 ! fixed non-localized usage of $_ + added new example ssh.pl 1.18 2006-07-11 ! added another pipe to synchronize spawning. Closing the slave in the parent can lead to a hang if the child already wrote something into it... ! fixed REs in test to deal with shell prompts 1.17 2006-05-31 ! fixed param check for expect() to allow expect(undef) et al 1.16 2006-05-05 ! fixed hangup with pipe sync upon spawn by adding close-on-exec to pipe handle ! fixed log_file(undef) when logging to CODE ref ! fixed $? mangling in DESTROY by saving & restoring status ! fixed hangup in send_slow ! fixed ugly solaris hack by disabling it for raw ptys + added param check for expect() 1.15 2002-03-19 ! fixed bug in _multi_expect, pattern weren't tried against accum due to exp_New_Data not set. 1.14 2002-03-13 same as 1.13_10 ! fixed select in interconnect, may return -1 if interrupted by signal. 1.13_08 2002-02-28 ! fixed bug in log_file, parameter now gets set to undef. 1.13_07 2002-02-28 + added and corrected test for exit status; got rid of Test.pm ! use 'set_raw' instead of stty("raw"); IO::Stty now optional + updated docs & FAQs; explained how terminal sizes and SIGWINCH should be propagated 1.13_06 2002-01-31 ! spawn is back again + rearranged and changed tests to better suit the various systems + added rudimentary 'notransfer' option; global only, not on per-pattern-basis; workaround available in FAQ + timeout handlers now also can exp_continue + added 'raw_pty' option, also setting master to raw if isatty() 1.13_04 2002-01-18 1.13_02 2001-11-30 1.13_01 2001-11-26 1.13 ! changed tests to check out pty behaviour (max. string length) + added various FAQ entries + added autoflush(1) to log_file + split 'new' and 'spawn' to be able to set slave pty params via stty before actually spawning the program + added slave_pty() + added print_log_file(), send() now no longer prints to log file or stdout. + added alarm to test.pl to avoid blocking on cygwin. ! spawn() now uses IO::Pty spawn, thus exec errors are reported and ssh should work too! 1.12 2001-09-06 ! exp_Max_Accum didn't work for interact. - removed soft_close() from DESTROY. Being overly nice to a doomed process doesn't pay off. Old behaviour is available via $Expect::Do_Soft_Close = 1; ! cleanup of log and exp_internal output + added various aliases for functions starting with 'exp_' ! moved FAQ and intro into the main pod as I got the impression that many users didn't bother to read all the documentation or didn't know that it was there. + added a hook for log_file: can be set to a code ref. 1.11 2001-02-20 Bugs fixed: ! max_accum (match_max) finally really restricts the match-buffer-size. ! expect() didn't return the correct error state upon EOF ! soft_close() was re-reading the filehandle even when an EOF had already been detected, resulting in a very long delay. ! exp_continue() returned a value that got truncated with certain perl versions (5.6 :-( ) on certain systems. Features added: + Lee Eakin contributed a perl version of the kibitz script which might be of common interest. See the examples/kibitz subdir. Thanks Lee! + Expect got it's own print() so we can show what's getting sent to the spawned program when exp_internal is set. (suggested by horos@earth.he.net) + a session can now be logged to a file by setting log_file(). Thanks to Marcel Widjaja for suggesting this. + I added some aliases for certain methods to help Tcl/Expect users to a WLIE experience (Work Like I Expect). 'exp_pid', 'match_max', 'log_file', 'log_user', even 'send' (which is an alias for 'print') are all there now. But I won't make 'send_user' an alias for 'print STDOUT', you have to draw a line somewhere. + some diagnosis messages now use cluck to print a stacktrace (suggested by horos@earth.he.net) + there is a new option 'restart_timeout_upon_receive', that, when set to 1, will restart the timeout within the expect call. This is useful when supervising an application that produces periodic, but not well-defined output and you still want to react to certain patterns. Just say $exp->restart_timeout_upon_receive(1); $exp->expect($timeout, [ timeout => \&report_timeout ], [ qr/pattern/ => \&handle_pattern ]); (suggested by horos@earth.he.net) 1.10 2000-11-22 I cannot believe it: a syntax error in Expect.pm slipped through (probably when I changed the version number after testing the patches), forcing me to do anouther release. >:-( 1.09 2000-11-21 Various small bugfixes: exp_before didn't get set on timeout, the expect call didn't return on matching EOF, spawn didn't die when exec failed, Expect crashed in certain cases. 1.08 2000-09-20 Added multi-match functionality (see docu) --Roland 1.07 1998-07-12 Changed the ver by .01 so I could get it up on CPAN :P 1.06 Added exp_before(), exp_after(), exp_match(), exp_match_number(), exp_error(). 1.05 Added debug level '3'. Fixed/added to tutorial, fixed a couple of minor bugs. 1.04 1998-03-12 Made all handles exp_inited autoflush. IO::Pty does the spawned processes for us. All regexp patterns passed to expect() are now multiline matched-- this makes matching ^ work for the beginning of lines. Unfortunately due to limitations in perl matching $ as the end of a line doesn't work if you are being returned \r\n instead of just \n. In this case you can use \r?$ to match the end of a line. exp_stty now checks to make sure the FH is a tty. 1.03 Reworked expect() to make the code more fluid. Removed ~50 lines of cruft. Added soft_close() and hard_close() (see Expect.pod for details). 1.02 Killed the $Expect::Use_Regexps stuff. Changed expect to look for '-re' strings indicating the subsequent pattern is to be matched as a regular expression. 1.01 1997-12-15 Dropped process still alive during expect. Sometimes the process dies before the handle finishes getting read. Fixed a typo that caused a response of 'child process died' if a successfull pattern had a null value. Added the ability to do expect() literals instead of regular expressions. see $process->use_regexps and the package global $Expect::Use_Regexps. Fixed internals to work with the documented fashion for using file ojects. everything is internally represented as ${*$process}{exp_variable} instead of ${*$process}{variable}. Pids should be checked with $process->pid() now, since $process->{Pid} no longer exists. exp_kill() is obsolete. Use kill($signal,$process->pid()). 1.00 exp_close no longer sends an exp_kill() to the process. This was kind of a dumb thing to do in the first place. Processes should go away after they are close()d. In fact, there really isn't any point in using exp_close. Just use $process->close();. -This isn't true as of 1.03, where soft and hard close were added to help deal with buffering issues. 0.99 Changed expect() to return the index of the matched pattern + 1. This enables the 'quick and dirty' $process->expect($timeout,'patern') || die; sort of behavior. 0.98 Changed everything. Now requires IO::Tty and uses IO::Stty. This should make it work on any posix-supporting platform that includes a method of obtaining a pty. Got rid of the 'detach' stuff, as it cluttered stuff up too much. Do your own forking. Default settings are now done by directly setting Expect::Values, such as $Expect::Debug and $Expect::Log_Stdout. Things now use 'spawn ids' and 'handle ids' instead of handle numbers. This makes debugging a little more sensible. Though there may be more bugs in the ver. I'm hopeful it should prove to be much more stable, reliable, intuitive and portable than previously. 0.972 Fixed setpgrp to be setsid. Oops. Processes opening /dev/tty should be much happier now. 0.97 Forced baud rate to get set at startup to make sure it wasn't set to 0 and sending EOFs. Linux now hangs consistently. It will probably not work until I get to the stty module. Sigh. Time to stop being lazy :) Also forced complete handle flushing after handles are opened. Probably a bit anal but I'd rather err on the side of safety. After the stty problem gets fixed I'll probably change over eveything to use the IO::Pty module. 0.96 Fixed a couple of idiot mistakes concerning DEBUG mode and printing debug info to STDERR. Changed some debugging spots so debugging info will always be printed in readable escaped format rather than raw input. 0.95 Linux had this bizarre problem of stty occasionally not returning when setting raw -echo. My solution was to run it twice, once for raw and once for echo. The real solution is of course to write an stty function using the POSIX module.. any volunteers? :-) 0.94 Think I fixed the problem of opening /dev/tty. Should work now. Also fixed a typo which caused the initial value of Log_Stdout to be set wrong. 0.92 Finally figured out how to generate an EOF on a terminal (stty 0 but you knew that already ;). Whole module needs a spring cleaning but seems to be pretty functional. After the (later) introduction of a POSIX stty function the code involving stty should get a little cleaner. Interact, interconnect and expect should all benefit from the EOF fix. interconnect also looks for FH exceptions, which it treats as EOFs. PKn1]QBlccLICENSEnu[(c) 1997 Austin Schutz EFE (retired) expect() interface & functionality enhancements (c) 1999-2006 Roland Giersig. This module is now maintained by Dave Jacoby EFE LICENSE This module can be used under the same terms as Perl. DISCLAIMER THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. In other words: Use at your own risk. Provided as is. Your mileage may vary. Read the source, Luke! And finally, just to be sure: Any Use of This Product, in Any Manner Whatsoever, Will Increase the Amount of Disorder in the Universe. Although No Liability Is Implied Herein, the Consumer Is Warned That This Process Will Ultimately Lead to the Heat Death of the Universe. PKQ1]R\\examples/kibitz/kibitznu[PKQ1]]examples/kibitz/kibitz.mannu[PKQ1]U$BB5examples/kibitz/Changelognu[PKQ1]G){6examples/kibitz/READMEnu[PKQ1]8S:examples/expect_calc.plnu[PKQ1]Vp<examples/calc.plnu[PKQ1]"q==examples/ssh.plnu[PKQ1]H ssEtutorial/5.A.topnu[PKQ1]j))Itutorial/6.B.modem-initnu[PKQ1]O] +Qtutorial/5.B.topnu[PKQ1]??o Ztutorial/2.A.ftpnu[PKQ1]c Jgtutorial/2.B.rloginnu[PKQ1]\Xwtutorial/READMEnu[PKQ1] | | ztutorial/1.A.Intronu[PKQ1]9كtutorial/3.A.debuggingnu[PKQ1]ϟQ ԋtutorial/6.A.smtp-verifynu[PKQ1]`ؘtutorial/4.A.topnu[PKQ1]/ README.mdnu[PKQ1]Ҭqy2y2Changesnu[PKn1]QBlccCLICENSEnu[PKe