Sunday, February 1, 2015

Installing autoexpect on Linux / Cygwin

This script automates much of day to day tasks and records keystrokes and responses into a file.
This file can later be made into a executable script to be run over and over again  .
Reduces repeated chores and also number of errors .

There is no installer as such, however there is a online script that you would cut and paste and create an executable out of it.



To begin using it,after cut and paste into a file ( call it autoexpect ) , and giving it execute permissions  chmod 755 autoexpect .

autoexpect  ( and hit enter )
 A default script called script.exp gets created in the same folder where this is run.

From here on - start typing the commands
When done, quit out of this. ( ctrl-D)

A script called "script.exp"  that captured all your keystrokes is now in the file.

Use this script as the automated script - OR - Change / modify to fit your needs and you have successfully created an auto expect script.

==
Here is the link from where you can download the autoexpect code, and in case you cannot download, I have cut and pasted the code below.
I had to make a small change in the first line to get this to work. First I figured out where expect was installed by running the "whereis expect" and the response was "/usr/bin/expect". 
Changing the first  line to #!/usr/bin/expect -- and giving the file the execute permissions got this to work.

Wishing you good luck and success in your effort to make scripts automated.

http://www.opensource.apple.com/source/expect/expect-1/expect/example/autoexpect


autoexpect   [plain text]


#!../expect --
# Name: autoexpect - generate an Expect script from watching a session
#
# Description:
#
# 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
# Date: June 30 1995
# Version: 1.4b

set filename "script.exp"
set verbose 1
set conservative 0
set promptmode 0
set option_keys ""

proc check_for_following {type} {
 if {![llength [uplevel set argv]]} {
  puts "autoexpect: [uplevel set flag] requires following $type"
  exit 1
 }
} 

while {[llength $argv]>0} {
 set flag [lindex $argv 0]
 if {0==[regexp "^-" $flag]} break
 set argv [lrange $argv 1 end]
 switch -- $flag \
   "-c" {
  set conservative 1
 } "-C" {
  check_for_following character
  lappend option_keys [lindex $argv 0] ctoggle
  set argv [lrange $argv 1 end]
 } "-p" {
  set promptmode 1
 } "-P" {
  check_for_following character
  lappend option_keys [lindex $argv 0] ptoggle
  set argv [lrange $argv 1 end]
 } "-Q" {
  check_for_following character
  lappend option_keys [lindex $argv 0] quote
  set argv [lrange $argv 1 end]
 } "-f" {
  check_for_following filename
  set filename [lindex $argv 0]
  set argv [lrange $argv 1 end]
 } "-quiet" {
  set verbose 0
 } default {
  break
 }
}

#############################################################
# Variables Descriptions
#############################################################
# 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)
proc input {c} {
 global userbuf lastkey

 send -- $c
 append userbuf $lastkey
 set lastkey $c
}

# Handle a null character from the keyboard
proc input_null {} {
 global lastkey userbuf procbuf echoing

 send -null

 if {$lastkey == ""} {
  if {$echoing} {
   sendcmd "$userbuf"
  }
  if {$procbuf != ""} {
   expcmd "$procbuf"
  }
 } else {
  sendcmd "$userbuf"
  if {$echoing} {
   expcmd "$procbuf"
   sendcmd "$lastkey"
  }   
 }
 cmd "send -null"
 set userbuf ""
 set procbuf ""
 set lastkey ""
 set echoing 0
}

# Handle a character that came from the process
proc output {s} {
 global lastkey procbuf userbuf echoing

 send_user -raw -- $s

 if {$lastkey == ""} {
  if {!$echoing} {
   append procbuf $s
  } else {
   sendcmd "$userbuf"
   expcmd "$procbuf"
   set echoing 0
   set userbuf ""
   set procbuf $s
  }
  return
 }

 regexp (.)(.*) $s dummy c tail
 if {$c == $lastkey} {
  if {$echoing} {
   append userbuf $lastkey
   set lastkey ""
  } else {
   if {$procbuf != ""} {
    expcmd "$procbuf"
    set procbuf ""
   }
   set echoing 1
  }
  append procbuf $s

  if {[string length $tail]} {
   sendcmd "$userbuf$lastkey"
   set userbuf ""
   set lastkey ""
   set echoing 0
  }
 } else {
  if {!$echoing} {
   expcmd "$procbuf"
  }
  sendcmd "$userbuf$lastkey"
  set procbuf $s
  set userbuf ""
  set lastkey ""
  set echoing 0
 }
}

# rewrite raw strings so that can appear as source code but still reproduce
# themselves.
proc expand {s} {
 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

 return $s
}

# generate an expect command
proc expcmd {s} {
 global promptmode

 if {$promptmode} {
  regexp ".*\[\r\n]+(.*)" $s dummy s
 }

 cmd "expect -exact \"[expand $s]\""
}

# generate a send command
proc sendcmd {s} {
 global send_style conservative

 if {$conservative} {
  cmd "sleep .1"
 }

 cmd "send$send_style -- \"[expand $s]\""
}

# generate any command
proc cmd {s} {
 global fd
 puts $fd "$s"
}

proc verbose_send_user {s} {
 global verbose

 if {$verbose} {
  send_user -- $s
 }
}

proc ctoggle {} {
 global conservative send_style

 if {$conservative} {
  cmd "# conservative mode off - adding no delays"
  verbose_send_user "conservative mode off\n"
  set conservative 0
  set send_style ""
 } else {
  cmd "# prompt mode on - adding delays"
  verbose_send_user "conservative mode on\n"
  set conservative 1
  set send_style " -s"
 }
}

proc ptoggle {} {
 global promptmode

 if {$promptmode} {
  cmd "# prompt mode off - now looking for complete output"
  verbose_send_user "prompt mode off\n"
  set promptmode 0
 } else {
  cmd "# prompt mode on - now looking only for prompts"
  verbose_send_user "prompt mode on\n"
  set promptmode 1
 }
}

# quote the next character from the user
proc quote {} {
 expect_user -re .
 send -- $expect_out(buffer)
}
 

if {[catch {set fd [open $filename w]} msg]} {
 puts $msg
 exit
}
exec chmod +x $filename
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]} {
  set expectpath $dir
  break
 }
}

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."
cmd {#
# Note that autoexpect does not guarantee a working script.  It
# necessarily has to guess about certain things.  Two reasons a script
# might fail are:
#
# 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} {
 set send_slow {1 .1}
 proc send {ignore arg} {
  sleep .1
  exp_send -s -- $arg
 }
}

#
# 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.
#
# -Don

}

cmd "set timeout -1"
if {$conservative} {
 set send_style " -s"
 cmd "set send_slow {1 .1}"
} else {
 set send_style ""
}

if {[llength $argv]>0} {
 eval spawn -noecho $argv
 cmd "spawn $argv"
} else {
 spawn -noecho $env(SHELL)
 cmd "spawn \$env(SHELL)"
}

cmd "match_max 100000"

set lastkey ""
set procbuf ""
set userbuf ""
set echoing 0

remove_nulls 0

eval interact $option_keys {
    -re . {
 input $interact_out(0,string)
    } -o -re .+ {
 output $interact_out(0,string)
    } eof {
 cmd "expect eof"
 return
    }
}

close $fd
verbose_send_user "autoexpect done, file is $filename\n"