exec expect
-- "$0" ${1+"$@"}
# Name: autoexpect - generate an Expect script from watching a session
# Given a program name, autoexpect will run that program. Otherwise
# autoexpect will start a shell. Interact as desired. When done, exit
# the program or shell. Autoexpect will create a script that reproduces
# your interactions. By default, the script is named script.exp.
# See the man page for more info.
# Author: Don Libes, NIST
set filename
"script.exp"
proc check_for_following
{type} {
if {![llength
[uplevel
set argv
]]} {
puts
"autoexpect: [uplevel set flag] requires following $type"
while {[llength
$argv]>0} {
set flag
[lindex
$argv 0]
if {0==[regexp
"^-" $flag]} break
set argv
[lrange
$argv 1 end
]
check_for_following character
lappend option_keys
[lindex
$argv 0] ctoggle
set argv
[lrange
$argv 1 end
]
check_for_following character
lappend option_keys
[lindex
$argv 0] ptoggle
set argv
[lrange
$argv 1 end
]
check_for_following character
lappend option_keys
[lindex
$argv 0] quote
set argv
[lrange
$argv 1 end
]
check_for_following filename
set filename
[lindex
$argv 0]
set argv
[lrange
$argv 1 end
]
#############################################################
#############################################################
# userbuf buffered characters from user
# procbuf buffered characters from process
# lastkey last key pressed by user
# if undefined, last key came from process
# echoing if the process is echoing
#############################################################
# Handle a character that came from user input (i.e., the keyboard)
# Handle a null character from the keyboard
global lastkey userbuf procbuf echoing
# Handle a character that came from the process
global lastkey procbuf userbuf echoing
regexp
(.
)(.
*) $s dummy c
tail
if {[string length
$tail]} {
sendcmd
"$userbuf$lastkey"
sendcmd
"$userbuf$lastkey"
# rewrite raw strings so that can appear as source code but still reproduce
regsub
-all "\\\\" $s "\\\\\\\\" s
regsub
-all "\r" $s "\\r" s
regsub
-all "\"" $s "\\\"" s
regsub
-all "\\\[" $s "\\\[" s
regsub
-all "\\\]" $s "\\\]" s
regsub
-all "\\\$" $s "\\\$" s
# generate an expect command
regexp
".*\[\r\n]+(.*)" $s dummy s
cmd
"expect -exact \"[expand $s]\""
# generate a send command
global send_style conservative
cmd
"send$send_style -- \"[expand $s]\""
proc verbose_send_user
{s
} {
global conservative send_style
cmd
"# conservative mode off - adding no delays"
verbose_send_user
"conservative mode off\n"
cmd
"# prompt mode on - adding delays"
verbose_send_user
"conservative mode on\n"
cmd
"# prompt mode off - now looking for complete output"
verbose_send_user
"prompt mode off\n"
cmd
"# prompt mode on - now looking only for prompts"
verbose_send_user
"prompt mode on\n"
# quote the next character from the user
send
-- $expect_out(buffer
)
if {[catch
{set fd
[open
$filename w
]} msg
]} {
verbose_send_user
"autoexpect started, file is $filename\n"
# calculate a reasonable #! line
set expectpath
/usr
/local
/bin
;# prepare default
foreach dir
[split $env(PATH
) :] { ;# now look for real location
if {[file executable
$dir/expect
] && ![file isdirectory
$dir/expect
]} {
cmd
"#![set expectpath]/expect -f
# This Expect script was generated by autoexpect on [timestamp -format %c]
# Expect and autoexpect were both written by Don Libes, NIST."
# Note that autoexpect does not guarantee a working script. It
# necessarily has to guess about certain things. Two reasons a script
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts. If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character. This
# pacifies every program I know of. The -c flag makes the script do
# this in the first place. The -C flag allows you to define a
# character to toggle this mode off and on.
set force_conservative
0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
# 2) differing output - Some programs produce different output each time
# they run. The "date" command is an obvious example. Another is
# ftp, if it produces throughput statistics at the end of a file
# transfer. If this causes a problem, delete these patterns or replace
# them with wildcards. An alternative is to use the -p flag (for
# "prompt") which makes Expect only look for the last line of output
# (i.e., the prompt). The -P flag allows you to define a character to
# toggle this mode off and on.
# Read the man page for more info.
cmd
"set send_slow {1 .1}"
spawn
-noecho $env(SHELL
)
eval interact
$option_keys {
input
$interact_out(0,string
)
output
$interact_out(0,string
)
verbose_send_user
"autoexpect done, file is $filename\n"