#
# Copyright (C) 2002, 2003, 2004, 2005 Yokogawa Electric Corporation,
# INTAP(Interoperability Technology Association for Information
# Processing, Japan), IPA (Information-technology Promotion Agency, Japan).
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms, with
# or without modification, are permitted provided that the following
# conditions and disclaimer are agreed and accepted by the user:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the names of the copyrighters, the name of the project which
# is related to this software (hereinafter referred to as "project") nor
# the names of the contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# 4. No merchantable use may be permitted without prior written
# notification to the copyrighters. However, using this software for the
# purpose of testing or evaluating any products including merchantable
# products may be permitted without any notification to the copyrighters.
#
#
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING
# BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHTERS, THE PROJECT OR CONTRIBUTORS 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.
#
# $TAHI: v6eval/script/pmod/V6evalRemote/V6evalRemote.pm,v 1.142 2005/05/25 05:11:45 akisada Exp $
#
########################################################################
package V6evalRemote;
use Exporter;
@ISA = qw(Exporter);
use 5;
use Getopt::Std;
use Expect;
$debug=0;
$retry=2;
$exit_error=1;
$init_timeout=0.2;
$dummy_prompt='DUMMY_PROMPT';
@EXPORT = qw(
rType
rDevice
rUser
rUserPrompt
rPasswordPrompt
rCommandPrompt
rDebug
rExpInternal
rLogStdout
rSendSpeed
rCmdOutput
rEnableLogout
rOpen
rLogin
rLogout
rClose
rCommandAsync
rCommand
rRebootAsync
rReboot
rPutfile
rInit
rShutdown
rArg
);
########################################################################
# The following status values must be same as V6evalTool.pm's ones.
$exitPass=0; # PASS
$exitNS=2; # Not yet supported
$exitFail=32; # FAIL
$exitFatal=64; # FATAL
########################################################################
BEGIN
{
$SIG{CHLD}=\&_sigchld_handler;
$SIG{INT}=\&_sig_handler;
$SIG{TERM}=\&_sig_handler;
$Bye="~.";
$Type="tahi-v6eval";
$CU="cu";
$Device="cuaa0";
$User="root";
$Password="v6eval";
undef $Remote;
$Expect::Log_Stdout=0;
$SendSpeed=0;
$EnableLogout=0;
$CmdOutput="";
# login prompt
%prompt_user = (
);
# %prompt_user = (
# 'kame-freebsd', 'login: ',
# 'freebsd43-i386', 'login: ',
# 'hitachi-nr60', 'login:',
# 'hitachi-nr60-v2', 'login:',
# 'hitachi-gr2k', 'login:',
# 'hitachi-gr2k-beta', 'login:',
# 'nec-libra', 'login: ',
# 'nec-libra-utcpip', 'login: ',
# 'nec-mip6', 'login: ',
# 'nec-ix1k', 'login: ',
# 'sfc-mip6', 'login: ',
# 'yamaha-ws-one', '(starts|Yamaha Corporation)',
# 'linux-v6', 'login: ',
# 'sun-solaris', 'login: ',
# 'ms-win2k', 'Login: ',
# 'cisco-ios', 'get started',
# 'iij-seil', 'login: ',
# 'telebit-tbc2k', 'Username:',
# 'mgcs-sj6', 'login: ',
# 'netbsd-i386', 'login: ',
# 'kame-netbsd-i386', 'login: ',
# 'freebsd-i386', 'login: ',
# 'openbsd-i386', 'login: ',
# 'aix', 'login: ',
# 'hpux', 'login: ',
# 'usagi-i386', 'login: ',
# 'usagi24-i386', 'login: ',
# 'mipl', 'login: ',
# 'lcna', 'login: ',
# 'ttb3010', 'login: ',
# 'unitedlinux', 'login: ',
# );
# password prompt
%prompt_password = (
);
# %prompt_password = (
# 'kame-freebsd', 'Password:',
# 'freebsd43-i386', 'Password:',
# 'hitachi-nr60', 'Password:',
# 'hitachi-nr60-v2', 'Password:',
# 'hitachi-gr2k', 'Password:',
# 'hitachi-gr2k-beta', 'Password:',
# 'nec-libra', 'Password:',
# 'nec-libra-utcpip', 'Password:',
# 'nec-mip6', 'Password:',
# 'nec-ix1k', 'Password:',
# 'sfc-mip6', 'Password:',
# 'yamaha-ws-one', 'Password:',
# 'linux-v6', 'Password: ',
# 'sun-solaris', 'Password:',
# 'ms-win2k', 'Password:',
# 'cisco-ios', 'Password:',
# 'iij-seil', 'DUMMY_PROMPT', # dummy
# 'telebit-tbc2k', 'Password:',
# 'mgcs-sj6', 'Password:',
# 'netbsd-i386', 'Password:',
# 'kame-netbsd-i386', 'Password:',
# 'freebsd-i386', 'Password:',
# 'openbsd-i386', 'Password:',
# 'aix', 'Password:',
# 'hpux', 'Password:',
# 'usagi-i386', 'Password: ',
# 'usagi24-i386', 'Password: ',
# 'mipl', 'Password: ',
# 'lcna', 'Password:',
# 'ttb3010', 'Password:',
# 'unitedlinux', 'Password: ',
# );
# command prompt
%prompt_command = (
);
# %prompt_command = (
# 'kame-freebsd', '(\$|#) ',
# 'freebsd43-i386', '(\$|#) ',
# 'hitachi-nr60', '% ',
# 'hitachi-nr60-v2', '% ',
# 'hitachi-gr2k', '(command|admin)(:|>) ',
# 'hitachi-gr2k-beta', '(command|admin): ',
# 'nec-libra', '(\$|#) ',
# 'nec-libra-utcpip', '(\$|#) ',
# 'nec-mip6', '(\$|#) ',
# 'nec-ix1k', '(\$|#) ',
# 'sfc-mip6', '(\$|#) ',
# 'yamaha-ws-one', '(>|#) ',
# 'linux-v6', '# ',
# 'sun-solaris', '# ',
# 'ms-win2k', '.:.>',
# 'cisco-ios', '(>|#)',
# 'iij-seil', '\r(>|#) ',
# 'telebit-tbc2k', '(> |% |accepted)',
# 'mgcs-sj6', '(\$|#) ',
# 'netbsd-i386', '(\$|#) ',
# 'kame-netbsd-i386', '(\$|#) ',
# 'freebsd-i386', '(\$|#) ',
# 'openbsd-i386', '(\$|#) ',
# 'aix', '(\$|#) ',
# 'hpux', '(\$|#) ',
# 'usagi-i386', '# ',
# 'usagi24-i386', '# ',
# 'mipl', '# ',
# 'lcna', '(\$|#) ',
# 'ttb3010', '(>|#) ',
# 'unitedlinux', '# ',
# );
# command of the admin mode if any
%cmd_admin = (
);
# %cmd_admin = (
# 'hitachi-gr2k', 'admin',
# 'hitachi-gr2k-beta', 'admin',
# 'yamaha-ws-one', 'administrator',
# 'cisco-ios', 'enable',
# 'iij-seil', '!sh',
# 'telebit-tbc2k', "\esystem",
# 'ttb3010', 'config',
# );
# another command of the admin mode if any
%cmd_admin2 = (
);
# %cmd_admin2 = (
# 'telebit-tbc2k', "\epaxtcl0\r",
# );
# logout command
%cmd_exit = (
);
# %cmd_exit = (
# 'kame-freebsd', 'exit',
# 'freebsd43-i386', 'exit',
# 'hitachi-nr60', 'exit',
# 'hitachi-nr60-v2', 'exit',
# 'hitachi-gr2k', 'exit',
# 'hitachi-gr2k-beta', 'exit',
# 'nec-libra', 'exit',
# 'nec-libra-utcpip', 'exit',
# 'nec-mip6', 'exit',
# 'nec-ix1k', 'exit',
# 'sfc-mip6', 'exit',
# 'yamaha-ws-one', 'exit',
# 'linux-v6', 'exit',
# 'sun-solaris', 'exit',
# 'ms-win2k', 'exit',
# 'cisco-ios', 'exit',
# 'iij-seil', 'exit',
# 'telebit-tbc2k', "\elogout\r",
# 'mgcs-sj6', 'exit',
# 'netbsd-i386', 'exit',
# 'kame-netbsd-i386', 'exit',
# 'freebsd-i386', 'exit',
# 'openbsd-i386', 'exit',
# 'aix', 'exit',
# 'hpux', 'exit',
# 'usagi-i386', 'exit',
# 'usagi24-i386', 'exit',
# 'mipl', 'exit',
# 'lcna', 'exit',
# 'ttb3010', 'logout',
# 'unitedlinux', 'exit',
# );
# confirmation for logout
%prompt_exit_confirm = (
);
# %prompt_exit_confirm = (
# 'ms-win2k', 'ENTER',
# );
# reply of the confirmation for logout
%reply_exit_confirm = (
);
# %reply_exit_confirm = (
# 'ms-win2k', "\r",
# );
# command for initialize
%cmd_init = (
);
# %cmd_init = (
# 'ttb3010', 'init all',
# );
# confirmation for Initialize
%prompt_init_confirm = (
);
# %prompt_init_confirm = (
# 'ttb3010', "y/n",
# );
# reply of the confirmation for Initialize
%reply_init_confirm = (
);
# %reply_init_confirm = (
# 'ttb3010', "y",
# );
# command for shutdown
%cmd_shutdown = (
);
# %cmd_shutdown = (
# 'ttb3010', "shutdown",
# );
# confirmation for Initialize
%prompt_shutdown_confirm = (
);
# %prompt_shutdown_confirm = (
# # TTB asks [y/n]
# 'ttb3010', "y/n",
# );
# reply of the confirmation for Initialize
%reply_shutdown_confirm = (
);
# %reply_shutdown_confirm = (
# 'ttb3010', "y",
# );
# reboot command
%cmd_reboot = (
);
# %cmd_reboot = (
# 'kame-freebsd', 'reboot',
# 'freebsd43-i386', 'reboot',
# 'hitachi-nr60', 'reboot',
# 'hitachi-nr60-v2', 'reboot',
# 'hitachi-gr2k', 'boot -nf',
# 'hitachi-gr2k-beta', 'boot -nf',
# 'nec-libra', 'reboot',
# 'nec-libra-utcpip', 'reboot',
# 'nec-mip6', 'reboot',
# 'nec-ix1k', 'reload y',
# 'sfc-mip6', 'reboot',
# 'yamaha-ws-one', 'restart',
# 'linux-v6', 'reboot',
# 'sun-solaris', 'reboot',
# # ms-win2k
# 'cisco-ios', 'reload',
# 'iij-seil', 'reboot',
# 'telebit-tbc2k', 'restart',
# 'mgcs-sj6', 'reboot',
# 'netbsd-i386', 'reboot',
# 'kame-netbsd-i386', 'reboot',
# 'freebsd-i386', 'reboot',
# 'openbsd-i386', 'reboot',
# 'aix', 'reboot',
# 'hpux', 'reboot',
# 'usagi-i386', 'reboot',
# 'usagi24-i386', 'reboot',
# 'mipl', 'reboot',
# 'lcna', 'reboot',
# 'ttb3010', 'reboot',
# 'unitedlinux', 'reboot',
# );
# final confirmation for reboot if any
%prompt_reboot_confirm = (
);
# %prompt_reboot_confirm = (
# 'ms-win2k', 'ENTER',
# # Proceed with reload? [confirm]
# 'cisco-ios', 'confirm',
# # Proceed with init? [y/n]
# 'ttb3010', 'y/n',
# );
# reply of the final confirmation for reboot
%reply_reboot_confirm = (
);
# %reply_reboot_confirm = (
# 'ms-win2k', "\r",
# 'cisco-ios', 'y',
# 'ttb3010', 'y',
# );
# pre-final confirmation for reboot if any
%prompt_reboot_confirm2 = (
);
# %prompt_reboot_confirm2 = (
# # System configuration has been modified.
# # Save? [yes/no]:
# 'cisco-ios', 'yes/no',
# );
# reply of the pre-final confirmation for reboot
%reply_reboot_confirm2 = (
);
# %reply_reboot_confirm2 = (
# 'cisco-ios', "no\r",
# );
# final confirmation for shutdown if any
%prompt_shutdown_confirm = (
);
# %prompt_shutdown_confirm = (
# # Proceed with init? [y/n]
# 'ttb3010', 'y/n',
# );
# reply of the final confirmation for reboot
%reply_shutdown_confirm = (
);
# %reply_shutdown_confirm = (
# 'ttb3010', 'y',
# );
# command for reading command status
%cmd_status = (
);
# %cmd_status = (
# 'kame-freebsd', 'echo $status',
# 'freebsd43-i386', 'echo $status',
# 'hitachi-nr60', 'echo $status',
# 'hitachi-nr60-v2', 'echo $status',
# 'hitachi-gr2k', 'echo $status',
# 'hitachi-gr2k-beta', 'echo $status',
# 'nec-libra', 'echo $status',
# 'nec-libra-utcpip', 'echo $status',
# 'nec-mip6', 'echo $status',
# 'sfc-mip6', 'echo $status',
# 'linux-v6', 'echo $?',
# 'sun-solaris', 'echo $?',
# # ms-win2k
# # cisco-ios
# # iij-seil
# # ttb3010
# 'mgcs-sj6', 'echo $status',
# 'netbsd-i386', 'echo $status',
# 'kame-netbsd-i386', 'echo $status',
# 'freebsd-i386', 'echo $status',
# 'openbsd-i386', 'echo $status',
# 'aix', 'echo $?',
# 'hpux', 'echo $?',
# 'usagi-i386', 'echo $?',
# 'usagi24-i386', 'echo $?',
# 'mipl', 'echo $?',
# 'lcna', 'echo $status',
# 'unitedlinux', 'echo $?',
# );
}
########################################################################
END
{
rClose();
}
########################################################################
sub _sig_handler
{
exit $exitFatal;
# call END for rClose()
}
########################################################################
sub _sigchld_handler
{
$! = 0;
$? = ($exit_error << 8);
print STDERR "``$CU -l $Device'' was killed with SIGCHLD.\n";
exit $exitFatal;
}
########################################################################
sub rType(;$)
{
my($x)=$Type;
$Type=shift(@_) if @_ != ();
$x;
}
########################################################################
sub rDevice(;$)
{
my($x)=$Device;
$Device=shift(@_) if @_ != ();
$x;
}
########################################################################
sub rUser(;$)
{
my($x)=$User;
$User=shift(@_) if @_ != ();
$x;
}
########################################################################
sub rUserPrompt(;$)
{
my($x)=$prompt_user{$Type};
$prompt_user{$Type}=shift(@_) if @_ != ();
$x;
}
########################################################################
sub rPasswordPrompt(;$)
{
my($x)=$prompt_password{$Type};
$prompt_password{$Type}=shift(@_) if @_ != ();
$x;
}
########################################################################
sub rCommandPrompt(;$)
{
my($x)=$prompt_command{$Type};
$prompt_command{$Type}=shift(@_) if @_ != ();
$x;
}
########################################################################
sub rDebug(;$)
{
# return undef if $Remote == undef;
return undef if (!defined $Remote);
my($x)=$Remote->debug();
$Remote->debug(shift(@_)) if @_ != ();
$x;
}
########################################################################
sub rExpInternal(;$)
{
# return undef if $Remote == undef;
return undef if (!defined $Remote);
my($x)=$Remote->exp_internal();
$Remote->exp_internal(shift(@_)) if @_ != ();
$x;
}
########################################################################
sub rLogStdout(;$)
{
# return undef if $Remote == undef;
return undef if (!defind $Remote);
my($x)=$Remote->log_stdout();
$Remote->log_stdout(shift(@_)) if @_ != ();
$x
}
########################################################################
sub rSendSpeed(;$)
{
my($x)=$SendSpeed;
$SendSpeed=shift(@_) if @_ != ();
$x;
}
########################################################################
sub rCmdOutput()
{
my(@x);
@x=split(/\n/, $CmdOutput);
}
########################################################################
sub rEnableLogout(;$)
{
my($x)=$EnableLogout;
# $EnableLogout=shift(@_) if @_ != ();
$EnableLogout=shift(@_) if (@_ > 0);
$x;
}
########################################################################
sub rOpen()
{
# return undef if $Remote != undef;
return undef if (defined $Remote);
autoflush STDOUT 1;
getopts('t:T:d:u:p:v:i:o:U:P:C:Vs:l:h');
if($opt_h) {
usage();
exit 0;
}
$Type=$opt_t if defined($opt_t); # target type
$CU=$opt_T if defined($opt_T); # cu command path
$Device=$opt_d if defined($opt_d); # serial device name
$User=$opt_u if defined($opt_u); # user name
$Password=$opt_p if defined($opt_p); # password
$prompt_user{$Type}=$opt_U if defined($opt_U); # login prompt
$prompt_password{$Type}=$opt_P if defined($opt_P); # password prompt
$prompt_command{$Type}=$opt_C if defined($opt_C); # command prompt
$debug = 1 if defined($opt_V); # debug flag
$SendSpeed=$opt_s if defined($opt_s); # send speed
$EnableLogout=$opt_l if defined($opt_l); # enable logout
my $TermCmd = "$CU -l $Device";
$Remote = Expect->spawn("$TermCmd");
# if($Remote == undef) {
if(!defined $Remote) {
print STDERR "$TermCmd exec failed\n";
return undef;
}
$Remote->debug($opt_v) if defined($opt_v); # debug level
$Remote->exp_internal($opt_i) if defined($opt_i); # internal debug level
$Remote->log_stdout($opt_o) if defined($opt_o); # stdout
my($v, $lval, $rval);
while($v = shift(@ARGV)) {
($lval, $rval) = split(/=/, $v, 2);
$rval=1 if $rval =~ /^\s*$/;
$v='$main::rOpt_'."$lval".'=\''."$rval".'\'';
eval($v); # eval ``$main::rOpt<LVAL>=<RVAL>''
print STDERR "eval $v\n" if $debug;
}
# if($Remote->expect(4, "onnect") == undef) {
if(!defined $Remote->expect(4, "onnect")) {
print STDERR "Unable to sync with cu\n";
return undef;
}
$Remote;
}
sub usage()
{
print "V6evalRemote.pm system options:\n".
" -h\n".
" -t<target_type>\n".
" -T<cu command path>\n".
" -d<serial_device_name>\n".
" -u<user_name>\n".
" -p<password>\n".
" -U<login_prompt>\n".
" -P<password_prompt>\n".
" -C<command_prompt>\n".
" -v<debug level>\n".
" -i<internal debug level>\n".
" -o<stdout>\n".
" -V\n".
" -s<interval>\n".
" -l<enable_logout>\n";
}
########################################################################
#
#
# START
# |
# | <----- A
# |
# Retry out? ---> ERROR
# |
# |
# wait prompt ---------------------------+----+----> timeout
# | | | OR
# | login prompt | | command prompt &&
# | | | logout
# put user_name | | THEN
# | | | goto A
# | | |
# wait prompt ----> timeout THEN goto A | |
# | | |
# | password prompt | |
# | | |
# | <----------------------------------+ |
# | password prompt && !logout |
# | |
# put password |
# | |
# | |
# wait prompt ----> timeout THEN goto A |
# | |
# | command prompt |
# | |
# | <---------------------------------------+
# | command prompt
# |
# END
#
sub rLogin($)
{
my($timeout)=@_;
my($retry)=8;
my($i)=0;
my($t)=$init_timeout;
my($is_admin)=0;
my($is_admin2)=0;
### $timeout=50; # special patch for long login timeout (such as netbsd-i386)
# if($Remote == undef) {
if(!defined $Remote) {
print STDERR "rOpen() should be called first.\n";
return 0;
}
if($debug) {
print STDERR "prompt_user: ``$prompt_user{$Type}'', ".
"prompt_password: ``$prompt_password{$Type}'', ".
"prompt_command: ``$prompt_command{$Type}''\n";
}
while($i<$retry) {
#
# wait for login prompt
#
print STDERR "rLogin: Wait for login prompt ($t sec)\n" if $debug;
# next if $Remote->expect($t,
# '-re', "$prompt_user{$Type}",
# '-re', "$prompt_password{$Type}",
# '-re', "$prompt_command{$Type}"
# ) == undef;
next if (!defined $Remote->expect($t,
'-re', "$prompt_user{$Type}",
'-re', "$prompt_password{$Type}",
'-re', "$prompt_command{$Type}"
));
$t=$timeout;
my($num)=$Remote->exp_match_number();
if($num == 1) {
#
# got login prompt
#
print STDERR "rLogin: Got login prompt\n" if $debug;
sendMessages("$User\r"); # put user name
} elsif($num == 2) {
#
# got password prompt
#
print STDERR "rLogin: Got password prompt\n" if $debug;
goto password;
} elsif($num == 3) {
#
# got command prompt
#
print STDERR "rLogin: Got command prompt\n" if $debug;
if(!$EnableLogout || $is_admin || $is_admin2) {
goto command;
} else {
rLogout($timeout);
next;
}
}
#
# wait for password prompt
#
if($prompt_password{$Type} eq $dummy_prompt) {
print STDERR "rlogin: password prompt is not defined\n"
if $debug;
} else {
print STDERR "rLogin: Wait for password prompt ($timeout sec)\n"
if $debug;
# next if $Remote->expect($timeout,
# '-re', "$prompt_password{$Type}",
# ) == undef;
next if (!defined $Remote->expect($timeout,
'-re', "$prompt_password{$Type}",
));
}
password:
if($prompt_password{$Type} ne $dummy_prompt) {
print STDERR "rLogin: Got password prompt\n" if $debug;
sendMessages("$Password\r"); # put password
}
#
# wait for command prompt
#
print STDERR "rLogin: Wait for command prompt ($timeout sec)\n"
if $debug;
# next if $Remote->expect($timeout,
# '-re', "$prompt_command{$Type}"
# ) == undef;
next if (!defined $Remote->expect($timeout,
'-re', "$prompt_command{$Type}"
));
command:
print STDERR "rLogin: Got command prompt\n" if $debug;
#
#
#
if($is_admin == 0 && $cmd_admin{$Type}) {
$is_admin = 1;
print STDERR "rLogin: Need admin command: $cmd_admin{$Type}\n" if $debug;
sendMessages("$cmd_admin{$Type}\r");
redo;
}
#
#
#
if($is_admin2 == 0 && $cmd_admin2{$Type}) {
$is_admin2 = 1;
print STDERR "rLogin: Need admin command2\n" if $debug;
sendMessages("$cmd_admin2{$Type}\r");
redo;
}
last;
} continue {
#
# timeout: never got any prompt
#
print STDERR "rLogin: Never got prompt; try again\n" if $debug;
sendMessages("\r");
$t=$timeout;
$i++;
}
if($i >= $retry) {
#
# Retry out
#
print STDERR "rLogin: Retry error (> $retry)\n";
print STDERR getOutput();
return 0;
}
#
# login
#
return 1;
}
########################################################################
#
# START
# |
# | <------- A
# |
# Retry out ? -----> ERROR
# |
# wait for prompt ------------+----------------------+
# | | |
# | login prompt OR | command prompt | timeout
# | passowrd prompt | |
# | put exit command |
# END | |
# goto A goto A
#
sub rLogout($)
{
my($timeout)=@_;
my($retry)=6;
my($i)=0;
my($t)=$init_timeout;
if(!defined $Remote) {
print STDERR "rOpen() should be called first.\n";
return 0;
}
if($debug) {
print STDERR "prompt_user: ``$prompt_user{$Type}'', ".
"prompt_password: ``$prompt_password{$Type}'', ".
"prompt_command: ``$prompt_command{$Type}''\n";
}
#
# if $EnableLogout == 0 then keep login
#
if($EnableLogout == 0) {
print STDERR "rLogout: skip by not specifing ``-l'' $opt_l\n"
if $debug;
return 1;
}
my(@ptn)= (
'-re', "$prompt_user{$Type}",
'-re', "$prompt_password{$Type}",
'-re', "$prompt_command{$Type}"
);
push(@ptn, '-re', $prompt_exit_confirm{$Type})
if $prompt_exit_confirm{$Type};
while($i<$retry) {
#
# wait for login prompt
#
print STDERR "rLogout: Wait for prompt ($t sec)\n" if $debug;
# next if $Remote->expect($t, @ptn) == undef;
next if (!defined $Remote->expect($t, @ptn));
$t=$timeout;
my($num)=$Remote->exp_match_number();
if($num == 1) {
#
# got login prompt
#
print STDERR "rLogout: Got login prompt\n" if $debug;
last;
} elsif($num == 2) {
#
# got password prompt
#
print STDERR "rLogout: Got password prompt\n" if $debug;
last;
} elsif($num == 3) {
#
# got command prompt
#
print STDERR "rLogout: Got command prompt\n" if $debug;
sendMessagesSync("$cmd_exit{$Type}\r");
$i++;
redo;
} elsif ($num == 4) {
#
# got confirmation message
#
print STDERR "rLogout: Got confirmation prompt\n" if $debug;
sendMessages("$reply_exit_confirm{$Type}");
$i++;
redo;
}
} continue {
#
# timeout: never got any prompt
#
print STDERR "rLogout: Never got prompt; try again\n" if $debug;
sendMessages("\r");
$t=$timeout;
$i++;
}
if($i >= $retry) {
#
# Retry out
#
print STDERR "rLogout: Retry error (> $retry)\n";
print STDERR getOutput();
return 0;
}
#
# logout
#
return 1;
}
########################################################################
sub rClose()
{
# return 0 if $Remote == undef;
return 0 if (!defined $Remote);
$SIG{CHLD}='DEFAULT';
print $Remote "$Bye\r";
print $Remote "$Bye\r";
print $Remote "$Bye\r";
$Remote->soft_close();
undef $Remote;
1;
}
########################################################################
sub _rCommand($$$)
{
my($cmd, $timeout, $sync)=@_;
my($i);
if(!$prompt_command{$Type}) {
print STDERR "$Type: Not defining the patterns of the prompts\n";
return 0;
}
# return 0 if $Remote == undef;
return 0 if (!defined $Remote);
for($i=0, $t=$init_timeout; $i<$retry; $i++) {
print STDERR "_rCommand: Try to get command prompt ($t sec.)\n"
if $debug;
# last if $Remote->expect($t, '-re', "$prompt_command{$Type}") != undef;
last if (defined $Remote->expect($t, '-re', "$prompt_command{$Type}"));
#
# Try to get any prompt
#
sendMessages("\r");
$t = $timeout;
}
if($i >= $retry) {
#
# retry error
#
print STDERR "_rCommand: never got command prompt\n";
print STDERR getOutput();
return 0;
}
print STDERR "_rCommand: Do ``$cmd'' command\n" if $debug;
if($sync) {
sendMessagesSync("$cmd\r");
} else {
sendMessages("$cmd\r");
}
return 3;
}
########################################################################
sub rCommandAsync($$)
{
my($cmd, $timeout)=@_;
return _rCommand($cmd, $timeout, 0);
}
########################################################################
sub rCommand($$)
{
my($cmd, $timeout)=@_;
my($i, $s, $t);
return 0 if _rCommand($cmd, $timeout, 1) == 0;
for($i=0, $t=$init_timeout; $i<$retry; $i++) {
print STDERR "rCommand: Try to get command prompt ($t sec)\n"
if $debug;
# last if $Remote->expect($t, '-re', "$prompt_command{$Type}") != undef;
last if (defined $Remote->expect($t, '-re', "$prompt_command{$Type}"));
sendMessages("\r");
$t = $timeout;
}
if($i >= $retry) {
#
# retry error
#
print STDERR "rCommand: never got command exit status\n" if $debug;
return 3;
}
$CmdOutput=$Remote->exp_before();
print STDERR "rCommand: CmdOutput=``$CmdOutput''\n" if $debug;
if($cmd_status{$Type}) {
# Invoke for getting exit status
sendMessagesSync("$cmd_status{$Type}\r");
# Get exit status
# if($Remote->expect($timeout, '-re', '[0-9]+') != undef) {
if(defined $Remote->expect($timeout, '-re', '[0-9]+')) {
$s = $Remote->exp_match();
print STDERR "rCommand: exit status: $s\n" if $debug;
return (($s == 0) ? 1 : 2);
}
}
print STDERR "rCommand: never got command exit status\n" if $debug;
return 3;
}
########################################################################
sub rRebootAsync($)
{
my($timeout)=@_;
my($i);
if(0) {
if(!$prompt_command{$Type}) {
print STDERR "$Type: Not defining the patterns of the prompts\n";
return 0;
}
# return 0 if $Remote == undef;
return 0 if (!defined $Remote);
my($cmd)=$cmd_reboot{$Type};
for($i=0, $t=$init_timeout; $i<$retry; $i++) {
print STDERR "rRebootAsync: Try to get command prompt ($t sec.)\n"
if $debug;
# last if
# $Remote->expect($t, '-re', "$prompt_command{$Type}") != undef;
last if (defined $Remote->expect($t,
'-re',
"$prompt_command{$Type}"
));
#
# Try to get any prompt
#
sendMessages("\r");
$t = $timeout;
}
if($i >= $retry) {
#
# retry error
#
print STDERR "rRebootAsync: never got command prompt\n";
print STDERR getOutput();
return 0;
}
print STDERR "rRebootAsync: Do ``$cmd'' command\n" if $debug;
sendMessagesSync("$cmd\r");
}
my($cmd)=$cmd_reboot{$Type};
return 0 if rCommandAsync($cmd, $timeout) == 0;
my(@ptn)=();
push(@ptn, '-re', "$prompt_reboot_confirm{$Type}")
if $prompt_reboot_confirm{$Type};
push(@ptn, '-re', "$prompt_reboot_confirm2{$Type}")
if $prompt_reboot_confirm2{$Type};
if(@ptn > 0) {
while(1) {
# if($Remote->expect($timeout,
# @ptn
# ) == undef) {
if(!defined $Remote->expect($timeout,
@ptn
)) {
print STDERR
"Did not get any confirmation message in reboot\n";
return 0;
}
my($num)=$Remote->exp_match_number();
if($num == 1) {
print STDERR "rRebootAsync: Got reboot prompt #1\n" if $debug;
sendMessages("$reply_reboot_confirm{$Type}");
last;
} elsif($num == 2) {
print STDERR "rRebootAsync: Got reboot prompt #2\n" if $debug;
sendMessages("$reply_reboot_confirm2{$Type}");
# try again
} else {
print STDERR "rRebootAsync: Internal error\n";
return 0;
}
}
}
return 1;
}
########################################################################
sub rReboot($)
{
my($timeout) = @_;
my($i, $t);
if(!$prompt_user{$Type}) {
printf STDERR "$Type: Not defining the pattern of the prompts\n";
return 0
}
if($Type eq 'telebit-tbc2k') {
printf STDERR "rReboot: $Type: Does not support\n";
return 0
}
#
# Do reboot command
#
rRebootAsync(5) || return 0;
#
# The login again.
#
for($i=0, $t=$init_timeout; $i<$retry; $i++) {
print STDERR "rReboot: Try to get login prompt ($t sec)\n"
if $debug;
# return 1 if $Remote->expect($t,
# '-re', "$prompt_user{$Type}",
# ) != undef;
return 1 if (defined $Remote->expect($t,
'-re', "$prompt_user{$Type}",
));
sendMessages("\r");
$t = $timeout;
}
print STDERR "rReboot: never got login prompt\n";
print STDERR getOutput();
return 0;
}
########################################################################
sub rPutfile($$$)
{
my($from, $to, $timeout)=@_;
setTipVar($timeout, 'echocheck') || goto error;
print STDERR "rPutfile: Starting copying\n" if $debug;
unless(get_prompt($timeout)) {
goto error;
}
sendMessages("~p");
sendMessages("$from $to\r");
unless(get_prompt($timeout)) {
goto error;
}
#
#
#
sendMessages("\r"); # it's important if prompt pattern is ``^(>|#) ''
# if($Remote->expect($timeout, '-re', "$prompt_command{$Type}") == undef) {
if(!defined $Remote->expect($timeout, '-re', "$prompt_command{$Type}")) {
print STDERR "Never sync with copy\n";
goto error;
}
print STDERR "rPutfile: Copying completed\n" if $debug;
#
#
#
return(1);
error:
return(0);
}
########################################################################
sub getOutput()
{
my($s);
$s = sprintf("Before: ``%s''\nMatch: ``%s''\nAfter: ``%s''\n",
$Remote->exp_before(),
$Remote->exp_match(),
$Remote->exp_after()
);
}
########################################################################
sub sendMessages(@)
{
my(@strings)=@_;
foreach(@strings) {
if($SendSpeed == 0){
print $Remote $_;
} else {
$Remote-> send_slow($SendSpeed, $_);
}
}
}
########################################################################
sub sendMessagesSync(@)
{
my(@strings)=@_;
my($timeout)=5;
foreach(@strings) {
if($SendSpeed == 0){
print $Remote $_;
} else {
$Remote-> send_slow($SendSpeed, $_);
}
# Sync with command echo back
# It is important if a target is WIN2K
# if($Remote->expect($timeout, "$_") == undef) {
if(!defined $Remote->expect($timeout, "$_")) {
print STDERR "sendMessagesSync: never got $_\n";
} else {
print STDERR "sendMessagesSync: got echo back of $_\n"
if $debug;
}
}
}
########################################################################
sub setTipVar($@)
{
my($timeout, @var)=@_;
foreach(@var) {
my($v)=$_;
unless(get_prompt($timeout)) {
return(0);
}
sendMessages("~s");
sendMessages("$v\r");
unless(get_prompt($timeout)) {
return(0);
}
}
return 1;
}
########################################################################
sub rInit($)
{
my($timeout)=@_;
my($i);
my($cmd)=$cmd_init{$Type};
return 0 if rCommandAsync($cmd, $timeout) == 0;
my(@ptn)=();
push(@ptn, '-re', "$prompt_init_confirm{$Type}")
if $prompt_init_confirm{$Type};
push(@ptn, '-re', "$prompt_command{$Type}")
if $prompt_command{$Type};
if(@ptn > 0) {
while(1) {
# if($Remote->expect($timeout,
# @ptn
# ) == undef) {
if(!defined $Remote->expect($timeout,
@ptn
)) {
print STDERR
"Did not get any confirmation message in initialize\n";
return 0;
}
my($num)=$Remote->exp_match_number();
if($num == 1) {
print STDERR "rInit: Got confirm prompt #1\n" if $debug;
sendMessages("$reply_init_confirm{$Type}\r");
} elsif($num == 2) {
print STDERR "rInit: Got Command prompt #2\n" if $debug;
sendMessages("$cmd_exit{$Type}\r");
last;
} else {
print STDERR "rInit: Internal error\n";
return 0;
}
}
}
return 1;
}
########################################################################
sub rShutdown($)
{
my($timeout)=@_;
my($i);
my($cmd)=$cmd_shutdown{$Type};
return 0 if rCommandAsync($cmd, $timeout) == 0;
my(@ptn)=();
push(@ptn, '-re', "$prompt_shutdown_confirm{$Type}")
if $prompt_shutdown_confirm{$Type};
if(@ptn > 0) {
while(1) {
# if($Remote->expect($timeout,
# @ptn
# ) == undef) {
if(!defined $Remote->expect($timeout,
@ptn
)) {
print STDERR
"Did not get any confirmation message in shutdown\n";
return 0;
}
my($num)=$Remote->exp_match_number();
if($num == 1) {
print STDERR "rShutdown: Got confirm prompt #1\n" if $debug;
sendMessages("$reply_shutdown_confirm{$Type}\n");
last;
} else {
print STDERR "rShutdown: Internal error\n";
return 0;
}
}
}
return 1;
}
########################################################################
sub get_prompt($)
{
my ($timeout) = @_;
my $count = 0;
for(my $d = 0; $d < $timeout; $d ++) {
if(defined($Remote->expect(1,
'-re', "$prompt_command{$Type}"))) {
$count ++;
last;
}
sendMessages("\r");
}
return($count);
}
########################################################################
#rArg() for pass argments to *.rmt
# return: always 1
#######################################
sub rArg()
{
autoflush STDOUT 1;
my($v, $lval, $rval);
while($v = shift(@ARGV)) {
($lval, $rval) = split(/=/, $v, 2);
$rval=1 if $rval =~ /^\s*$/;
$v='$main::rOpt_'."$lval".'=\''."$rval".'\'';
eval($v); # eval ``$main::rOpt<LVAL>=<RVAL>''
print STDERR "eval $v\n" if $debug;
}
return 1;
}
########################################################################
1;
########################################################################
__END__
=head1 NAME
V6evalRemote - Perl interface to control NUT via serial line.
=head1 SYNOPSIS
=head1 DESCRIPTION
=head1 INTERFACE OF REMOTE CONTROL SCRIPT
<Default> <Descriptions>
----------- -----------------------
-t<target_type> kame-freebsd kame-freebsd
hitachi-nr60
nec-libra
nec-libra-utcpip
yamaha-ws-one
-T<cu_command_path> cu cu command path
-d<serial_device_name> cuaa0c see cu(1)
-u<user_name> root user name
-p<password> v6eval user password
-U<login_prompt> 'ogin: ' Regular-expression
-P<password_prompt> 'assword:' Reqular-expression
-C<command_prompt> '(#|\$|%|>) ' Reqular-expression
-v<debug level> 0 $Expect::Debug
-i<internal debug level> 0 $Expect::Exp_Internal
-o<stdout> 0 $Expect::Log_Stdout
-V N/A enable other debug messages
-s<interval> 0 send speed (sec.)
-l{0,1} 0 enable rLogout()
-h N/A show this message
=head1 SUPPORTED FUNCTION
=head1 rOpen
Open the remote control program.
sub rOpen()
=head2 RETURN VALUES
undef: error
Otherwise: Expect handle
=head1 rLogin
Log into the target machine.
sub rLogin($) { my (
$timeout # timeout sec.
)=@_;
=head2 RETURN VALUES
==0: error
!=0: success
=head1 rCommand
Execute a command.
sub rCommand($$) { my (
$command # command
$timeout # timeout sec.
)=@_;
=head2 RETURN VALUES
==0: error
==1: success: command exit status is 0
==2: warning: command exit status isn't 0
==3: warning: command exit status unknown
=head1 rReboot
Reboot the target machine.
The functin return when getting login prompt.
sub rReboot($) { my (
$timeout # timeout sec.
)=@_;
=head2 RETURN VALUES
==0: error
!=0: success
=head1 rRebootAsync
Reboot the target machine.
The function return immediately when executing reboot command.
sub rRebootAsync($) { my (
$timeout # timeout sec.
)=@_;
=head2 RETURN VALUES
==0: error
!=0: success
=head1 rPutfile
Copy a local file to a remote file.
sub rPutfile($$$) { my (
$from,
$to,
$timeout,
)=@_;
=head2 RETURN VALUES
==0: error
!=0: success
=head1 rLogout
Log out of the target machine.
sub rLogout($) { my (
$timeout # timeout sec.
)=@_;
=head2 RETURN VALUES
==0: error
!=0: success
=head1 rClose
Terminate the remote control program.
sub rClose($) { my (
$timeout # timeout sec.
)=@_;
=head2 RETURN VALUES
==0: error
!=0: success
=head1 rType
Set/get a target machine type.
sub rType(;$)
=head2 RETURN VALUES
Returns a target machine type.
=head1 rDevice
Set/get serial device name.
sub rDevice(;$)
=head2 RETURN VALUES
Returns serial device name.
=head1 rUser
Set/get user name.
sub rUser(;$)
=head2 RETURN VALUES
Returns user name.
=head1 rUserPrompt
Set/get user prompt.
sub rUserPrompt(;$)
=head2 RETURN VALUES
Returns user prompt.
=head1 rPasswordPrompt
Set/get password prompt.
sub rPasswordPrompt(;$)
=head2 RETURN VALUES
Returns password prompt.
=head1 rCommandPrompt
Set/get command prompt.
sub rCommandPrompt(;$)
=head2 RETURN VALUES
Returns command prompt.
=head1 rDebug
Set/get Expect.pm's debug()
sub rDebug(;$)
=head2 RETURN VALUES
Returns $Remote->debug().
=head1 rExpInternal
Set/get Expect.pm's exp_internal()
sub rExpInternal(;$)
=head2 RETURN VALUES
Returns $Remote->exp_internal()
=head1 rLogStdout
Set/get Expect.pm's log_stdout()
sub rLogStdout(;$)
=head2 RETURN VALUES
Returns $Remote->log_stdout()
=head1 rRemoteSpeed
Set/get interval that characters are sent at.
sub rRemoteSpeed(;$)
=head2 RETURN VALUES
Returns interval value.
=head1 rEnableLogout
Enable(!=0)/Desable(==0, default) rLogout()
sub rEnableLogout(;$)
=head2 RETURN VALUES
Returns previous value
=head1 EXAMPLE
#!/usr/bin/perl
use V6evalRemote;
print "Open remote\n";
rOpen() || exit $V6evalRemote::exitFail;
$type=rType();
$rOpt_timeout=5 if (!defined $rOpt_timeout);
if($type eq "kame-freebsd") {
print "Login\n";
rLogin($rOpt_timeout) || exit $V6evalRemote::exitFail;
print "List dir\n";
rCommand("ls -a", $rOpt_timeout) || exit $V6evalRemote::exitFail;
print "Logout\n";
rLogout($rOpt_timeout) || exit $V6evalRemote::exitFail;
} else {
print "List dir of NUT($type) manually, ".
"then press enter key.\n";
<STDIN>;
}
print "Close remote\n";
rClose();
exit $V6evalRemote::exitPass;
=head1 REQUIRED PACKAGES
Expect.pm
Stty.pm
Pty.pm
=cut
syntax highlighted by Code2HTML, v. 0.9.1