#!/usr/local/bin/expect -- # # rabbit - copies an executable to many target machines and executes it there # # Created Fri Nov 25 17:28:59 EST 1994 - Steve Traugott # set user [exec logname] set timeout 300 set ftpserver ftp set usage "usage: rabbit \[ -l username \] \[ -v \] {executable} {host1 host2 host3 ...}\n" set maxpasswords 8 set passwordcount 0 set argskip 0 set verbose 0 set prompt "(%|#|\\$|\\]|\\>)( $|$)" ;# prompt pattern string if [info exists env(EXPECT_PROMPT)] {set prompt $env(EXPECT_PROMPT)} for {set argskip 0} {[string match -* [lindex $argv $argskip]]} {incr argskip} { set arg [lindex $argv $argskip] switch -regexp -- $arg { -v { set verbose 1 } -l { incr argskip ; set user [lindex $argv $argskip]} -.* { send_user "Cannot parse option $arg.\n$usage" exit } } } if $argc<=$argskip+1 { send_user $usage exit } proc getpasswd {} { global user passwords passwordcount maxpasswords # get passwords set passwords "" send_user "Enter $user's password(s) - end with blank entry: \n" stty -echo for {set passwordcount 1} {$passwordcount<=$maxpasswords} {incr passwordcount} { send_user "$user's Password: " expect_user { -re ".(.*)\n" { send_user "\n" set passwords "$passwords $expect_out(0,string)" } -re "\n" { set passwordcount [expr $passwordcount-1] send_user "\n" break } } } stty echo } proc putfile {ftpserver ftpscript script} { spawn ftp $ftpserver expect "Name*:" {send "ftp\r"} expect "*word:" {send "rabbit@\r"} expect "*ftp>" {send "bin\r"} expect "*ftp>" {send "cd rabbit/incoming\r"} expect "*ftp>" {send "put $script $ftpscript\r"} # if I get a file not found, bail out now. expect { "*o such file*" {send_user "\n\n$script not found.\n\n" ; exit} "*ftp>" {send "quit\r"} } } proc hop {ftpscript remotescript host} { global passwords user prompt ftpserver passwordcount verbose send_user "\n========== $host ==========\n" if $verbose==0 { log_user 0 } set timeout 15 expect_before { eof return timeout { send_user "TIMEOUT - $host\n" close send_user [exec banner $host] send_user [exec banner timeout] return } } spawn telnet $host set i 0 while {1} { if $verbose==0 { send_user "." } expect { "*ogin:*" {send "$user\r"} "*nknown host*" { log_user 1 send_user [exec banner $host] send_user [exec banner unknown] return } "*on system console*" { log_user 1 send_user [exec banner $host] send_user [exec banner disallowed] return } "*refused*" { log_user 1 send_user [exec banner $host] send_user [exec banner refused] return } "*illegal option*" { spawn telnet $host } "*Connection closed*" { spawn telnet $host } "*word:" { set password [lindex $passwords $i] send "$password\r" incr i } "*Last*" {send "\r"; break} "*TERM=" {send "\r"} -re $prompt {send "\r"; break} } if $i>$passwordcount {break} } if $verbose==0 { send_user "\n" } if $i<=$passwordcount { set timeout 300 # go get script expect -re $prompt {send "cd /tmp\r"} expect -re $prompt {send "ftp $ftpserver\r"} expect "Name*:" {send "ftp\r"} expect "*word:" {send "rabbit@\r"} expect "*ftp>" {send "bin\r"} expect "*ftp>" {send "cd rabbit/incoming\r"} expect "*ftp>" {send "get $ftpscript $remotescript\r"} expect "*ftp>" {send "quit\r"} expect -re $prompt {send "chmod 700 $remotescript\r"} # run it expect -re $prompt {send "$remotescript\r"} if $verbose==0 { log_user 1 } expect -re $prompt {send "\r"} set timeout 15 expect -re $prompt {send "\r"} expect -re $prompt {send "echo rabbit done\r"} if $verbose==0 { log_user 0 } expect "*rabbit done" {send "rm $remotescript\r"} expect -re $prompt {send "exit\r"} } else { send_user [exec banner $host] send_user [exec banner FAILED] } if $verbose==0 { log_user 1 } close send_user "\n" } # Main # ask user for some passwords to use getpasswd # get script name set script [lindex $argv $argskip] incr argskip # figure out various names for script set ftpscript [exec basename $script] # - where it gets executed on remote machine set remotescript "/tmp/[exec basename $script]" putfile $ftpserver $ftpscript $script # cycle throught hosts for {set i $argskip} {$i<$argc} {incr i} { set host [lindex $argv $i] hop $ftpscript $remotescript $host } send_user "\nCompleted:\n\trabbit $argv\n\n" send_user "\n"