From: Bowyer Jeff To: libes@cme.nist.gov (Don Libes) Subject: expect Program #2 Date: Thu, 8 Apr 1993 15:18:42 +0200 (MET DST) On our anonymous ftp server, we also decided to create a directory that mirrors all rfc files at nic.ddn.mil. Consequently, I wrote the following expect program to get new files and delete obsoleted files. Jeff *========================================================================* Jeff Bowyer EMail: Computing Center jbowyer@cis.vutbr.cs Technical University of Brno Udolni 19, 602 00 BRNO Czech Republic *========================================================================* THE MAIN SHELL PROGRAM ---------------------------------------------------------------------- MDIR=/users/jbowyer/maint RDIR=/users/ftp/pub/doc/rfc expect $MDIR/mirror nic.ddn.mil rfc $RDIR case $? in 1) currmin=`date +%M` currhour=`date +%H` nextmin=`expr $currmin + 15` nexthour=$currhour if test $nextmin -ge 60 then nexthour=`expr $nexthour + 1` nextmin=`expr $nextmin - 60` fi if test $nexthour -eq 24 then nexthour=0 fi at $nexthour:$nextmin $MDIR/rfcmirror ;; esac ---------------------------------------------------------------------- THE EXPECT PROGRAM ---------------------------------------------------------------------- match_max -d 100000 ;# max size of a directory listing set destdir "nodir" set fname "nofile" set currmonth 0 set curryear 0 set mday 0 set mmonth 0 set myear 0 set localrfcs "" set needrfcs "" proc initexpect {} { expect_before { -re "unreachable*" { exit 1 } -re "closed connection*" { exec rm -f $destdir/$fname exit 1 } -re "Connection timed out*" { exec rm -f $destdir/$fname send "quit\r" exit 1 } timeout { exec rm -f $destdir/$fname send "quit\r" exit 1 } eof { exec rm -f $destdir/$fname exit 1 } } } proc getname {line} { # if it's a symbolic link, return local name set i [lsearch line "->"] if {-1==$i} { # not a sym link # return last token of line as name, and strip off newline at end return [lindex $line 8] } else { # sym link, return "a" of "a -> b" return [lindex $line [expr $i-1]] } } proc getmonth {line} { set fmonth [lindex $line [expr [llength $line]-4]] return [expr [lsearch {Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec} $fmonth]+1] } proc getday {line} { return [lindex $line [expr [llength $line]-3]] } proc getyear {line fmonth} { global currmonth curryear set fyear [lindex $line [expr [llength $line]-2]] if [regexp ".*:.*" $fyear] { if {$fmonth>$currmonth} { return [expr $curryear-1] } else { return $curryear } } else { return $fyear } } proc buildllist {thedir} { global fname localrfcs send "anonymous\r" expect { -re "Password:*" } send "jbowyer@cis.vutbr.cs\r" expect { "ok*ftp>*" } send "cd $thedir\r" expect { "CWD*success*" { continue -expect } "ftp>*" } send "dir\r" expect { "ftp>*" } set buf $expect_out(buffer)\n close for {} 1 {} { set split_buf [split $buf ""] set i [string first "\n" $buf] set line [join [lrange $split_buf 0 $i] ""] set buf [join [lrange $split_buf [expr 1+$i] end] ""] set token [lindex $line 0] case $token in { dir\r { # original command } 200 { # command successful } 150 { # opening data connection } total { # directory header } 226 { # transfer complete, succeeded! } ftp> { return 1 } . { # unreadable } default { # either file or directory set fname [getname $line] if [regexp -nocase "^rfc0|^rfc1|^rfc2|^rfc3|^rfc4|^rfc5|^rfc6|^rfc7|^rfc8|^rfc9" $fname] { set lday [getday $line] set lmonth [getmonth $line] set lyear [getyear $line $lmonth] lappend localrfcs [list $fname $lday $lmonth $lyear] } } } } return 0 } proc buildrlist {thedir} { global fname masterrfcs send "anonymous\r" expect { -re "Password:*" } send "jbowyer@cis.vutbr.cs\r" expect { "ok*ftp>*" } send "cd $thedir\r" expect { "CWD*success*" { continue -expect } "ftp>*" } send "dir\r" expect { "ftp>*" } set buf $expect_out(buffer)\n close for {} 1 {} { set split_buf [split $buf ""] set i [string first "\n" $buf] set line [join [lrange $split_buf 0 $i] ""] set buf [join [lrange $split_buf [expr 1+$i] end] ""] set token [lindex $line 0] case $token in { dir\r { # original command } 200 { # command successful } 150 { # opening data connection } total { # directory header } 226 { # transfer complete, succeeded! } ftp> { return 1 } . { # unreadable } default { # either file or directory set fname [getname $line] if [regexp -nocase "^rfc0|^rfc1|^rfc2|^rfc3|^rfc4|^rfc5|^rfc6|^rfc7|^rfc8|^rfc9" $fname] { set lday [getday $line] set lmonth [getmonth $line] set lyear [getyear $line $lmonth] lappend masterrfcs [list $fname $lday $lmonth $lyear] } } } } return 0 } proc getmasterdates {} { global masterfile mday mmonth myear set mday [expr [lindex $masterfile 1]] set mmonth [expr [lindex $masterfile 2]] set myear [expr [lindex $masterfile 3]] } proc newmaster {} { global masterfile mday mmonth myear localfile getmasterdates set lday [expr [lindex $localfile 1]] set lmonth [expr [lindex $localfile 2]] set lyear [expr [lindex $localfile 3]] if $myear>$lyear { return 1 } else { if $myear==$lyear { if $mmonth>$lmonth { return 1 } else { if $mmonth==$lmonth { if $mday>$lday { return 1 } } } } } return 0 } proc getrfile {} { global destdir fname needfile mday mmonth myear set fname [lindex $needfile 0] send "get $fname\r" expect { "ftp>*" } exec chmod "666" $destdir/$fname set touchstr [format "%02d%02d0000%s" $mmonth $mday [string range $myear 2 end]] exec touch $touchstr $destdir/$fname exec chmod "444" $destdir/$fname } log_file /users/jbowyer/maint/logs/rfclog set destdir [lindex $argv 3] set currmonth [exec date +%m] set curryear [exec date +%Y] set timeout 900 spawn ftp rhino.cis.vutbr.cs initexpect expect { -re "unknown host" { exit 1 } -re "unreachable*" { exit 1 } -re "Name*" } if [buildllist "pub/doc/rfc"] { spawn ftp [lindex $argv 1] initexpect expect { -re "unknown host" { exit 1 } -re "unreachable*" { exit 1 } -re "Name*" } if [buildrlist [lindex $argv 2]] { foreach masterfile $masterrfcs { set foundrfc 0 foreach localfile $localrfcs { if 0==[string compare [lindex $masterfile 0] [lindex $localfile 0]] { if [newmaster] { lappend needrfcs $masterfile } set localindex [lsearch $localrfcs $localfile] set localrfcs [concat [lrange $localrfcs 0 [expr $localindex-1]] [lrange $localrfcs [expr $localindex+1] end]] set foundrfc 1 break } } if !$foundrfc { lappend needrfcs $masterfile } } if [llength $localrfcs]>0 { foreach killfile $localrfcs { exec rm -f $destdir/[lindex $killfile 0] } } if [llength $needrfcs]>0 { spawn ftp [lindex $argv 1] initexpect expect { -re "unknown host" { exit 1 } -re "unreachable*" { exit 1 } -re "Name*" } send "anonymous\r" expect { -re "Password:*" } send "jbowyer@cis.vutbr.cs\r" expect { "ok*ftp>*" } send "cd [lindex $argv 2]\r" expect { "CWD*success*" { continue -expect } "ftp>*" } send "binary\r" expect { "ftp>*" } send "hash\r" expect { "ftp>*" } send "lcd $destdir\r" expect { "ftp>*" } foreach needfile $needrfcs { getmasterdates getrfile } } } } exit 0