1#!../expect -f 2# ftp-inband - copy files over a telnet/rlogin/etc link 3# Author: Don Libes, NIST 4# Date: Jan 11, 1993 5 6# Program follows usual conventions and is otherwise self-documenting. 7# Assumes standard UNIX conventions on both sides. It uses "compress" 8# which can be replaced with gzip or removed totally - it's just there 9# for efficiency. 10# Assumes error-free transmission (i.e., MNP modems), telnet links, etc. 11# Assumes remote shell does not reset tty modes after each command. 12 13# Note, there is very little error checking. This script was written 14# primarily as an exercise - just to demonstrate Expect. 15 16set prompt "(%|#|\\\$) $" ;# default prompt 17catch {set prompt $env(EXPECT_PROMPT)} 18 19set timeout -1 20set verbose_flag 0 21 22proc send_verbose {msg} { 23 global verbose_flag 24 25 if {$verbose_flag} { 26 send_user $msg 27 } 28} 29 30proc get {infile outfile} { 31 global prompt verbose_flag 32 33 if {!$verbose_flag} { 34 log_user 0 35 } 36 37 send_verbose "disabling echo: " 38 send "stty -echo\r" 39 expect -re $prompt 40 41 send_verbose "remote pid is " 42 send "echo $$\r" 43 expect -re "(.*)\r\n.*$prompt" {set rpid $expect_out(1,string)} 44 45 set pid [pid] 46 # pid is local pid, rpid is remote pid 47 48 set infile_plain "/tmp/$rpid" 49 set infile_compressed "$infile_plain.Z" 50 set infile_encoded "$infile_compressed.uu" 51 52 set outfile_plain "/tmp/$pid" 53 set outfile_compressed "$outfile_plain.Z" 54 set outfile_encoded "$outfile_compressed.uu" 55 56 set out [open $outfile_encoded w] 57 58 send_verbose "compressing\n" 59 send "compress -fc $infile > $infile_compressed\r" 60 expect -re $prompt 61 62 # use label corresponding to temporary name on local system 63 send_verbose "uuencoding\n" 64 send "uuencode $infile_compressed $outfile_compressed > $infile_encoded\r" 65 expect -re $prompt 66 67 send_verbose "copying\n" 68 send "cat $infile_encoded\r" 69 70 log_user 0 71 72 expect { 73 -re "^end\r\n" { 74 puts $out "end" 75 close $out 76 } -re "^(\[^\r]*)\r\n" { 77 puts $out $expect_out(1,string) 78 send_verbose "." 79 exp_continue 80 } 81 } 82 83 if {$verbose_flag} { 84 send_user "\n" ;# after last "." 85 log_user 1 86 } 87 88 expect -re $prompt ;# wait for prompt from cat 89 90 send_verbose "deleting temporary files\n" 91 send "rm -f $infile_compressed $infile_encoded\r" 92 expect -re $prompt 93 94 send_verbose "switching attention to local system\nuudecoding\n" 95 exec uudecode $outfile_encoded 96 97 send_verbose "uncompressing\n" 98 exec uncompress -f $outfile_compressed 99 100 send_verbose "renaming\n" 101 if {[catch "exec cp $outfile_plain $outfile" msg]} { 102 send_user "could not move file in place, reason: $msg\n" 103 send_user "left as $outfile_plain\n" 104 exec rm -f $outfile_encoded 105 } else { 106 exec rm -f $outfile_plain $outfile_encoded 107 } 108 109 # restore echo and serendipitously reprompt 110 send "stty echo\r" 111 112 log_user 1 113} 114 115proc put {infile outfile} { 116 global prompt verbose_flag 117 118 if {!$verbose_flag} { 119 log_user 0 120 } 121 122 send_verbose "disabling echo: " 123 send "stty -echo\r" 124 expect -re $prompt 125 126 send_verbose "remote pid is " 127 send "echo $$\r" 128 expect -re "(.*)\r\n.*$prompt" {set rpid $expect_out(1,string)} 129 130 set pid [pid] 131 # pid is local pid, rpid is remote pid 132 133 set infile_plain "/tmp/$pid" 134 set infile_compressed "$infile_plain.Z" 135 set infile_encoded "$infile_compressed.uu" 136 137 set outfile_plain "/tmp/$rpid" 138 set outfile_compressed "$outfile_plain.Z" 139 set outfile_encoded "$outfile_compressed.uu" 140 141 set out [open $outfile_encoded w] 142 143 send_verbose "compressing\n" 144 exec compress -fc $infile > $infile_compressed 145 146 # use label corresponding to temporary name on local system 147 send_verbose "uuencoding\n" 148 exec uuencode $infile_compressed $outfile_compressed > $infile_encoded 149 150 send_verbose "copying\n" 151 send "cat > $outfile_encoded\r" 152 153 log_user 0 154 155 set fp [open $infile_encoded r] 156 while {1} { 157 if {-1 == [gets $fp buf]} break 158 send_verbose "." 159 send -- "$buf\r" 160 } 161 162 if {$verbose_flag} { 163 send_user "\n" ;# after last "." 164 log_user 1 165 } 166 167 send "\004" ;# eof 168 close $fp 169 170 send_verbose "deleting temporary files\n" 171 exec rm -f $infile_compressed $infile_encoded 172 173 send_verbose "switching attention to remote system\n" 174 175 expect -re $prompt ;# wait for prompt from cat 176 177 send_verbose "uudecoding\n" 178 send "uudecode $outfile_encoded\r" 179 expect -re $prompt 180 181 send_verbose "uncompressing\n" 182 send "uncompress -f $outfile_compressed\r" 183 expect -re $prompt 184 185 send_verbose "renaming\n" 186 send "cp $outfile_plain $outfile\r" 187 expect -re $prompt 188 189 send_verbose "deleting temporary files\n" 190 send "rm -f $outfile_plain $outfile_encoded\r" 191 expect -re $prompt 192 193 # restore echo and serendipitously reprompt 194 send "stty echo\r" 195 196 log_user 1 197} 198 199proc get_main {} { 200 stty -raw echo 201 send_user "g\nget remote file \[localfile]: " 202 expect_user { 203 -re "(\[^ ]+) +(\[^ ]+)\n" { 204 send_user "copying (remote) $expect_out(1,string) to (local) $expect_out(2,string)\n" 205 get $expect_out(1,string) $expect_out(2,string) 206 } -re "(\[^ ]+)\n" { 207 send_user "copying $expect_out(1,string)\n" 208 get $expect_out(1,string) $expect_out(1,string) 209 } -re "\n" { 210 send_user "eh?\n" 211 } 212 } 213 stty raw -echo 214} 215 216proc put_main {} { 217 stty -raw echo 218 send_user "p\nput localfile \[remotefile]: " 219 expect_user { 220 -re "(\[^ ]+) +(\[^ ]+)\n" { 221 send_user "copying (local) $expect_out(1,string) to (remote) $expect_out(2,string)\n" 222 put $expect_out(1,string) $expect_out(2,string) 223 } -re "(\[^ ]+)\n" { 224 send_user "copying $expect_out(1,string)\n" 225 put $expect_out(1,string) $expect_out(1,string) 226 } -re "\n" { 227 send_user "eh?\n" 228 } 229 } 230 stty raw -echo 231} 232 233proc chdir {} { 234 stty -raw echo 235 send_user "c\n" 236 send_user "current directory is [pwd], new directory: " 237 expect_user -re "(.*)\n" { 238 cd $expect_out(1,string) 239 } 240 stty raw -echo 241} 242 243proc verbose {} { 244 global verbose_flag 245 246 set verbose_flag [expr !$verbose_flag] 247 send_user "verbose [verbose_status]\r\n" 248} 249 250proc verbose_status {} { 251 global verbose_flag 252 253 if {$verbose_flag} { 254 return "on" 255 } else { 256 return "off" 257 } 258} 259 260proc cmd {} { 261 set CTRLZ \032 262 263 send_user "command (g,p,? for more): " 264 expect_user { 265 g get_main 266 p put_main 267 c chdir 268 v verbose 269 ~ {send "~"} 270 "\\?" { 271 send_user "?\n" 272 send_user "~~g get file from remote system\n" 273 send_user "~~p put file to remote system\n" 274 send_user "~~c change/show directory on local system\n" 275 send_user "~~~ send ~~ to remote system\n" 276 send_user "~~? this list\n" 277 send_user "~~v verbose mode toggle (currently [verbose_status])\n" 278 send_user "~~^Z suspend\n" 279 } 280 $CTRLZ { 281 stty -raw echo 282 exec kill -STOP [pid] 283 stty raw -echo 284 } 285 -re . {send_user "unknown command\n"} 286 } 287 send_user "resuming session...\n" 288} 289 290spawn -noecho $env(SHELL) 291 292send_user "Once logged in, cd to directory to transfer to/from and press: ~~\n" 293send_user "One moment...\n" 294interact ~~ cmd 295 296