From jbowyer@cis.vutbr.cs Thu Apr  8 09:24:08 1993
X-VM-Attributes: [nil nil nil nil nil]
Status: RO
Return-Path: <jbowyer@cis.vutbr.cs>
Received: from cme.nist.gov (durer.cme.nist.gov) by muffin.cme.nist.gov (4.1/SMI-3.2-del.7)
	id AA01871; Thu, 8 Apr 93 09:24:06 EDT
Received: from rhino.cis.vutbr.cs by cme.nist.gov (4.1/SMI-3.2-del.8)
	id AA25063; Thu, 8 Apr 93 09:15:16 EDT
Received: by rhino.cis.vutbr.cs (5.67/1.05 VUT Brno)
	id AA28819; Thu, 8 Apr 93 15:14:04 +0200
Message-Id: <9304081314.AA28819@rhino.cis.vutbr.cs>
Reply-To: jbowyer@cis.vutbr.cs
X-Mailer: ELM [version 2.4 PL20]
Mime-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Length: 7160      
From: Bowyer Jeff <jbowyer@cis.vutbr.cs>
To: libes@cme.nist.gov (Don Libes)
Subject: expect Program #1
Date: Thu, 8 Apr 1993 15:14:03 +0200 (MET DST)

I store several Internet-related documents on our anonymous ftp server
for members of the university community to access.

I want these documents to always represent the most recent edition, but
I'm too lazy to regularly check their original sites.  Therefore, I wrote
the following expect program to check for me and get the document if a
new version exists.

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

/usr/bin/ksh
MDIR=/users/jbowyer/maint/anondocs

echo 'updatedocs is executing' | mail jbowyer

$MDIR/update.internet.library
$MDIR/update.mailing.lists
$MDIR/update.ftp.sites
$MDIR/update.whois.servers
$MDIR/update.rfc.index
$MDIR/update.inet.services
$MDIR/update.serials
$MDIR/update.active1
$MDIR/update.active2
$MDIR/update.alt1
$MDIR/update.alt2
$MDIR/update.moderator.list

at 3am sa $MDIR/updatedocs
exit

A SAMPLE DOCUMENT-SPECIFIC SHELL PROGRAM (update.internet.library)

MDIR=/users/jbowyer/maint/anondocs
NDIR=/users/jbowyer/newdocs
ADIR=/users/ftp/pub/doc/internet

expect $MDIR/ftpdoc ariel.unm.edu library internet.library $ADIR book.libraries
case $? in
0)	cd $NDIR
	mv internet.library $ADIR/book.libraries
	chgrp ftp $ADIR/book.libraries
	chmod 644 $ADIR/book.libraries
	echo 'New book.libraries' | mail jbowyer ;;
1)	if test 5 -ne `date +%w`
	then
		at 3am $MDIR/update.internet.library
	fi ;;
2)	echo 'internet.library not found' | mail jbowyer ;;
esac

THE EXPECT PROGRAM

match_max -d 100000		;# max size of a directory listing

set destdir "/users/jbowyer/newdocs"

set currmonth 0
set curryear 0

set rmonth 0
set rday 0
set ryear 0

set lmonth 0
set lday 0
set lyear 0

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 [string trimright [lindex $line [expr [llength $line]-1]]]
	} 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 getrdate {} {
	global argv rmonth rday ryear
	send "dir\r"
	expect {
                 "ftp>*"
               }

	set buf $expect_out(buffer)

	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!
					#
					# Unfortunately, it indicates
					# that the desired filename on
					# the remote host was not found
					#
					return -1 
				}
			ftp>	{
					# next prompt, failed!
					return 0
				}
			.	{
					# unreadable
				}
			default {
					# either file or directory
					set fname [getname $line]
					if 0==[string compare $fname [lindex $argv 3]] {
					  set rmonth [getmonth $line]
					  set rday [getday $line]
					  set ryear [getyear $line $rmonth]
					  return 1
					}
				}
				}
		}
	return 0 
}

proc getldate {} {
	global argv lmonth lday lyear
	send "!ll\r"
	expect {
                 "ftp>*"
               }

	set buf $expect_out(buffer)

	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	{
			!ll\r	{
					# original command
				}
			total	{
					# directory header
				}
			ftp>	{
					# next prompt, failed!
					return 0
				}
			.	{
					# unreadable
				}
			default {
					# either file or directory
					set fname [getname $line]
					if 0==[string compare $fname [lindex $argv 5]] {
					  set lmonth [getmonth $line]
					  set lday [getday $line]
					  set lyear [getyear $line $lmonth]
					  return 1
					}
				}
				}
		}
	return 0
}

proc getrfile {} {
	global destdir argv rmonth rday ryear
	send "lcd $destdir\r"
	expect {
                 "ftp>*"
	       }
	send "binary\r"
	expect {
                 "ftp>*"
               }
	send "hash\r"
	expect {
                 "ftp>*"
               }
	send "get [lindex $argv 3]\r"
	expect {
                 "ftp>*"
               }
	set touchstr [format "%02d%02d0000%s" $rmonth $rday [string range $ryear 2 end]]
	exec touch $touchstr $destdir/[lindex $argv 3]
	send "quit\r"
	return 1
}

log_file /users/jbowyer/maint/logs/[exec date +%y%m%d]
set currmonth [exec date +%m]
set curryear [exec date +%Y]
set timeout 900
spawn ftp [lindex $argv 1]
expect_before {
                -re "closed connection*" {
                                           exit 1
                                         }
                -re "Connection timed out*" {
					      send "quit\r"
                                              exit 1
                                            }
                timeout	{
			  send "quit\r"
			  exit 1 
                        }
                eof {
                      exit 1
                    }
              }
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 {
         -re "CWD*success*" {
                              continue -expect
                            }
         "ftp>*"
       }

case [expr [getrdate]] {
  -1	{
  	#
	# Desired filename not found on remote anonymous ftp server
	#
	exit 2
	}
   0    {
   	#
	# Error on remote anonymous ftp server
	#
	exit 1
	}
   default {
   	#
	# Desired filename found on remote anonymous ftp server
	#

	send "lcd [lindex $argv 4]\r"
	expect {
                 -re "Local directory now*" {
                                              continue -expect
                                            }	
                 "ftp>*"
               }
	if [getldate] {
		if $ryear>$lyear {
			if [getrfile] {
				exit 0
			}
		} else {
			if $ryear==$lyear {
				if $rmonth>$lmonth {
					if [getrfile] {
						exit 0
					}
				} else {
					if $rmonth==$lmonth {
						if $rday>$lday {
							if [getrfile] {
								exit 0
							}
						}
					}
				}
			}
		}
	}
  }
}
exit 4