#!../expect -f # ftp-inband - copy files over a telnet/rlogin/etc link # Author: Don Libes, NIST # Date: Jan 11, 1993 # Program follows usual conventions and is otherwise self-documenting. # Assumes standard UNIX conventions on both sides. It uses "compress" # which can be replaced with gzip or removed totally - it's just there # for efficiency. # Assumes error-free transmission (i.e., MNP modems), telnet links, etc. # Assumes remote shell does not reset tty modes after each command. # Note, there is very little error checking. This script was written # primarily as an exercise - just to demonstrate Expect. set prompt "(%|#|\\\$) $" ;# default prompt catch {set prompt $env(EXPECT_PROMPT)} set timeout -1 set verbose_flag 0 proc send_verbose {msg} { global verbose_flag if $verbose_flag { send_user $msg } } proc get {infile outfile} { global prompt verbose_flag if (!$verbose_flag) { log_user 0 } send_verbose "disabling echo: " send "stty -echo\r" expect -re $prompt send_verbose "remote pid is " send "echo $$\r" expect -re "(.*)\r\n.*$prompt" {set rpid $expect_out(1,string)} set pid [pid] # pid is local pid, rpid is remote pid set infile_plain "/tmp/$rpid" set infile_compressed "$infile_plain.Z" set infile_encoded "$infile_compressed.uu" set outfile_plain "/tmp/$pid" set outfile_compressed "$outfile_plain.Z" set outfile_encoded "$outfile_compressed.uu" set out [open $outfile_encoded w] send_verbose "compressing\n" send "compress -fc $infile > $infile_compressed\r" expect -re $prompt # use label corresponding to temporary name on local system send_verbose "uuencoding\n" send "uuencode $infile_compressed $outfile_compressed > $infile_encoded\r" expect -re $prompt send_verbose "copying\n" send "cat $infile_encoded\r" log_user 0 expect { -re "^end\r\n" { puts $out "end" close $out } -re "^(\[^\r]*)\r\n" { puts $out $expect_out(1,string) send_verbose "." exp_continue } } if ($verbose_flag) { send_user "\n" ;# after last "." log_user 1 } expect -re $prompt ;# wait for prompt from cat send_verbose "deleting temporary files\n" send "rm -f $infile_compressed $infile_encoded\r" expect -re $prompt send_verbose "switching attention to local system\nuudecoding\n" exec uudecode $outfile_encoded send_verbose "uncompressing\n" exec uncompress -f $outfile_compressed send_verbose "renaming\n" if [catch "exec cp $outfile_plain $outfile" msg] { send_user "could not move file in place, reason: $msg\n" send_user "left as $outfile_plain\n" exec rm -f $outfile_encoded } else { exec rm -f $outfile_plain $outfile_encoded } # restore echo and serendipitously reprompt send "stty echo\r" log_user 1 } proc put {infile outfile} { global prompt verbose_flag if (!$verbose_flag) { log_user 0 } send_verbose "disabling echo: " send "stty -echo\r" expect -re $prompt send_verbose "remote pid is " send "echo $$\r" expect -re "(.*)\r\n.*$prompt" {set rpid $expect_out(1,string)} set pid [pid] # pid is local pid, rpid is remote pid set infile_plain "/tmp/$pid" set infile_compressed "$infile_plain.Z" set infile_encoded "$infile_compressed.uu" set outfile_plain "/tmp/$rpid" set outfile_compressed "$outfile_plain.Z" set outfile_encoded "$outfile_compressed.uu" set out [open $outfile_encoded w] send_verbose "compressing\n" exec compress -fc $infile > $infile_compressed # use label corresponding to temporary name on local system send_verbose "uuencoding\n" exec uuencode $infile_compressed $outfile_compressed > $infile_encoded send_verbose "copying\n" send "cat > $outfile_encoded\r" log_user 0 set fp [open $infile_encoded r] while 1 { if {-1 == [gets $fp buf]} break send_verbose "." send "$buf\r" } if ($verbose_flag) { send_user "\n" ;# after last "." log_user 1 } send "\004" ;# eof close $fp send_verbose "deleting temporary files\n" exec rm -f $infile_compressed $infile_encoded send_verbose "switching attention to remote system\n" expect -re $prompt ;# wait for prompt from cat send_verbose "uudecoding\n" send "uudecode $outfile_encoded\r" expect -re $prompt send_verbose "uncompressing\n" send "uncompress -f $outfile_compressed\r" expect -re $prompt send_verbose "renaming\n" send "cp $outfile_plain $outfile\r" expect -re $prompt send_verbose "deleting temporary files\n" send "rm -f $outfile_plain $outfile_encoded\r" expect -re $prompt # restore echo and serendipitously reprompt send "stty echo\r" log_user 1 } proc get_main {} { stty -raw echo send_user "g\nget remote file \[localfile]: " expect_user { -re "(\[^ ]+) +(\[^ ]+)\n" { send_user "copying (remote) $expect_out(1,string) to (local) $expect_out(2,string)\n" get $expect_out(1,string) $expect_out(2,string) } -re "(\[^ ]+)\n" { send_user "copying $expect_out(1,string)\n" get $expect_out(1,string) $expect_out(1,string) } -re "\n" { send_user "eh?\n" } } stty raw -echo } proc put_main {} { stty -raw echo send_user "p\nput localfile \[remotefile]: " expect_user { -re "(\[^ ]+) +(\[^ ]+)\n" { send_user "copying (local) $expect_out(1,string) to (remote) $expect_out(2,string)\n" put $expect_out(1,string) $expect_out(2,string) } -re "(\[^ ]+)\n" { send_user "copying $expect_out(1,string)\n" put $expect_out(1,string) $expect_out(1,string) } -re "\n" { send_user "eh?\n" } } stty raw -echo } proc chdir {} { stty -raw echo send_user "c\n" send_user "current directory is [pwd], new directory: " expect_user -re "(.*)\n" { cd $expect_out(1,string) } stty raw -echo } proc verbose {} { global verbose_flag set verbose_flag [expr !$verbose_flag] send_user "verbose [verbose_status]\r\n" } proc verbose_status {} { global verbose_flag if $verbose_flag { return "on" } else { return "off" } } proc cmd {} { set CTRLZ \032 send_user "command (g,p,? for more): " expect_user { g get_main p put_main c chdir v verbose ~ {send "~"} "\\?" { send_user "?\n" send_user "~~g get file from remote system\n" send_user "~~p put file to remote system\n" send_user "~~c change/show directory on local system\n" send_user "~~~ send ~~ to remote system\n" send_user "~~? this list\n" send_user "~~v verbose mode toggle (currently [verbose_status])\n" send_user "~~^Z suspend\n" } $CTRLZ { stty -raw echo exec kill -STOP [pid] stty raw -echo } -re . {send_user "unknown command\n"} } send_user "resuming session...\n" } spawn -noecho $env(SHELL) send_user "Once logged in, cd to directory to transfer to/from and press: ~~\n" send_user "One moment...\n" interact ~~ cmd