#!/usr/local/bin/expect -f # # brdob Name: eftp Version: 1.3 Changed: 93/10/25 18:09:06 # # Eftp, an interface for ftp. # # USAGE, type in: eftp -- -h # # One of the nice features is the "~r" command which # allows you to quickly reconnect to a machine after # the remote connection has been broken (time out). # You may also easily connect to another host with same # username, passwd, and current directory. A mirror # directory feature allows you to go to $HOME/path # where path is taken from your current working directory # on local machine. Example: if you are in $HOME/path # on local machine when you entered eftp, then mirror directory # will be ~/path for accessing remote host. # # Try ~h to get a list of eftp commands. # # Denis Ballant, Oct. 1993 # bad@ittc.wec.com # # Global Variables: username pass dir host # Check expect version exp_version -exit 5.0.3 # Usage if {$argc>0 && [lindex $argv 0]=="-h"} { send_user "Usage: eftp \[remote-host \[user-name \[dir\]\]\]\n" exit } # Exit after some condition proc sorry {msg} { send_user "\n*** eftp: $msg.\n" exit } # ask_user /* blind may be "show" or "hide" */ proc ask_user {msg default blind} { send_user $msg if {"$default" != ""} { if {"$blind" == "hide"} { send_user " \[...\]" } else { send_user " \[$default\]" } } send_user ": " set timeout 120 if {"$blind" == "hide"} { system stty -echo } expect_user timeout { sorry "Time out" } "*\n" if {"$blind" == "hide"} { send_user "\n"; system stty echo } set result $default scan $expect_out(buffer) "%s" result return $result } # Normalize directory names # (Remove any leading "/tmp_mnt/" string) proc norm_dirname {dirname} { set index [string first "/tmp_mnt/" $dirname] if {"$index" == "0"} { set dirname [string range $dirname 8 end] } return $dirname } # Get host if {$argc>0} { set host [lindex $argv 0] } else { set host [ask_user "Host" "" show] } # Get username if {$argc>1} { set username [lindex $argv 1] } else { set username [ask_user "Login" [exec printenv USER] show] } # Get password set pass [ask_user "Password" "" hide] # Get Directory if {$argc>2} { set indir [lindex $argv 2] } else { set indir [ask_user "Directory (. = mirror)" "." show] } proc handle_dir {dir} { if {"$dir"=="."} { set home [exec printenv HOME] set home [norm_dirname $home] set cwd [exec printenv PWD] set cwd [norm_dirname $cwd] set index [string first $home $cwd] if {"$index" == "0"} { set dir "~/[string range $cwd [expr 1 + [string length $home]] end]" } else { set dir $cwd } } return $dir } set dir [handle_dir $indir] #-------------------------------------------------------------------------------- set prompt ftp* proc get_host {$default} { global host send_user "\n" set host [ask_user "Host" "$default" show] } proc open_host {} { global username pass dir host set timeout 60 while (1) { send "open $host\n" expect timeout {sorry "Time out"} \ "*unreachable*ftp>*" {get_host ""; continue} \ "*unknown*ftp>*" {get_host ""; continue} \ *Name* {break} } open_login } #----------------------------- proc get_login {} { global username pass dir host send_user "\n" set username [ask_user "Login" "$username" show] set pass [ask_user "Password" "$pass" hide] send "user " } proc open_login {} { global username pass dir host set timeout 60 while (1) { send $username\n expect { timeout {sorry "Time out"} "*User*unknown*ftp>*" {get_login; continue} *Password:* } send $pass\n expect { timeout {sorry "Time out"} "*Login failed*ftp>*" {get_login; continue} "*ftp>*" {break} } } open_dir } proc get_dir {} { global dir indir send_user "\n" set indir [ask_user "Directory (. = mirror)" "$indir" show] set dir [handle_dir $indir] } proc open_dir {} { global dir while (1) { if {"$dir"!=""} { send "cd $dir\n" expect { timeout {sorry "Time out"} "*No such file*ftp>*" {get_dir; continue} "*ftp>*" {break} } } } } proc display_vars {} { global username pass dir host send_user "\nYou are currently connected to host \"$host\"\n" send_user "under username \"$username\".\n" send_user "Current directory is \"$dir\"\n" send_user "ftp> " } #-------------------------------------------------------------------------------- spawn ftp expect $prompt open_host send_user "\nType in ~h to get help on eftp\nftp> " proc display_help {} { global username pass dir host send_user "\n -------------------------------------------------------\n" send_user " ~q - quit\n" send_user " ~h - display this help\n" send_user " ~ls - local ls\n" send_user " ~r - automatic reconnection to remote host ($host)\n" send_user " ~c - connect to new host\n" send_user " ~u - enter new user name and password\n" send_user " ~d - enter new directory\n" send_user " user - same as ~u\n" send_user " ^D - display local date\n" send_user " ^Z - suspend eftp\n" send_user " ~s - display current status (hostname,etc.)\n" send_user " -------------------------------------------------------\n" send_user "ftp> " } set CTRLZ \032 while (1) { # I use the following variable for those actions # that require input from user. Which actions do # not work correctly without returning from interact # first. set action 0 interact { -reset $CTRLZ {exec kill -STOP 0} ~q {send quit\n} ~h {display_help} ~ls {send_user "\n[exec ls -FC]\nftp> "} ~r {set action 4 ; return } ~c {set action 2 ; return } ~u {set action 1 ; return} ~d {set action 3 ; return} ~s {display_vars} user\r {set action 1 ; return} \004 {send_user "\n[exec date]\nftp> "} } if {"$action" == "0"} { exit } if {"$action" == "4"} { send "close\n" expect "*ftp>*" open_host } if {"$action" == "1"} { get_login open_login } if {"$action" == "2"} { send "close\n" expect "*ftp>*" send_user "\n" set host [ask_user "Host" "$host" show] set username [ask_user "Login" "$username" show] set pass [ask_user "Password" "$pass" hide] open_host } if {"$action" == "3"} { get_dir open_dir } }