#!/bin/sh
#

#From: Jeff Bowyer <jbowyer@muni.cz>
#To: libes@cme.nist.gov (Don Libes)
#Subject: Re: autoexpect
#Date: Wed, 26 Jul 1995 07:18:25 +0200 (MET DST)
#
#As promised, the "manymaint" multiple router maintenance program
#follows my signature.  The code needs *minor* tweeks to work on an
#installation besides my own.
#
#Jeff
#

#
# Set default savescript value
#
savescript="y"

#
# Set default perform maintenance value
#
perform_maint="y"

#
# Default script file
#
defscript="script.exp"

#
# Default router names file
#
defrouters="/network/routers/router.list"

#
# The famous "no default" string
#
nodef="no default"

#
# Checking out how to suppress new lines...
#
if [ "`echo -n a`" = "a" ]; then
  n='-n'
  c=''
else
  n=''
  c='\c'
fi

#
# Set up ~user expansion
cat >.tildexp <<EOF
#!/bin/sh
case "\$1" in
~/*|~)
  echo \$1 | $sed "s|~|\${HOME-\$LOGDIR}|"
  ;;
~*)
  if test -f /bin/csh; then
    /bin/csh -f -c "glob \$1"
    failed=$?
    echo ""
    exit \$failed
  else
    name=\`$expr x\$1 : '..\([^/]*\)'\`
    dir=\`$sed -n -e "/^\${name}:/{s/^[^:]*:[^:]*:[^:]*:[^:]*:[^:]*:\([^:]*\).*"'\$'"/\1/" -e p -e q -e '}' </etc/passwd\`
    if test ! -d "\$dir"; then
      me=\`basename \$0\`
      echo "\$me: can't locate home directory for: \$name" \>\&2
      exit 1
    fi
    case "\$1" in
    */*)
      echo \$dir/\`$expr x\$1 : '..[^/]*/\(.*\)'\`
      ;;
    *)
      echo \$dir
      ;;
    esac
  fi
  ;;
*)
  echo \$1
  ;;
esac
EOF
chmod a+x .tildexp

#
# Set up shell script to read input
#
myecho="case \"\$xxxm\" in
'') echo $n \"\$rp $c\" >&4;;
*)  case \"\$rp\" in
  '') echo $n \"[\$xxxm] $c\";;
  *)
    if test \`echo \"\$rp [\$xxxm]  \" | wc -c\` -ge ${COLUMNS-80}; then
      echo \"\$rp\" >&4
      echo $n \"[\$xxxm] $c\" >&4
    else
      echo $n \"\$rp [\$xxxm] $c\" >&4
    fi
    ;;
  esac;;
esac"
cat <<EOF > .myread
xxxm=\$dflt
$myecho
ans='!'
case "\$fastread" in
yes) case "\$dflt" in
  '') ;;
  *) ans='';
    case "\$silent-\$rp" in
    true-) ;;
    *) echo " " >&4;;
    esac;;
  esac;;
*) case "\$silent" in
  true) case "\$rp" in
    '') ans='';;
    esac;;
  esac;;
esac
while expr "X\$ans" : "X!" >/dev/null; do
  read answ
  set x \$xxxm
  shift
  aok=''; eval "ans=\"\$answ\"" && aok=y
  case  "\$answ" in
  "\$ans")
    case "\$ans" in
    "!")
      sh 1>&4
      echo " "
      $myecho
      ;;
    !*)
      set x \`expr "X\$ans" : "X!\(.*\)\$"\`
      shift
      sh 1>&4 -c "\$*"
      echo " "
      $myecho
      ;;
    esac;;
  *)
    case "\$aok" in
    y)
      echo "*** Substitution done -- please confirm."
      xxxm="\$ans"
      ans=\`echo $n "\$ans$c" | tr '\012' ' '\`
      xxxm="\$ans"
      ans=!
      ;;
    *)
      echo "*** Error -- try again."
      ans=!
      ;;
    esac
    $myecho
    ;;
  esac
  case "\$ans\$xxxm\$nostick" in
  '')
    ans=!
    $myecho
    ;;
  esac
done
case "\$ans" in
'') ans="\$xxxm";;
esac
EOF

trapdeletefiles=".myread .tildexp"

trap '{
  exitstat=$?
  rm -f $trapdeletefiles
  trap "" 0
  echo "Aborting... cleaning up." >&2
  exit $exitstat
}' 0 1 2 15

# Prepare redirection for "silent" mode (to be implemented :)
exec 4>&1

cat << EOF

Welcome to the multiple router maintenance program.

I will ask you a few questions. Most of the time, a default value will
be printed, and you'll just need to hit the 'Return' key to confirm.
If you get stuck on a question, you may use a ! shell escape to start
a subshell or execute a !command.

Some questions asking for file or directory names allow the use of the ~user
construct to specify the login directory belonging to "user", even if you
don't have a shell which knows about that. They'll be marked "(~user ok)".

The prompter used in this script allows you to use shell variables and
backticks in your answers.  You may use \$1, \$2, etc...  to refer to the words
in the default answer, as if the default line was a set of arguments given to a
script shell.  This means you may also use \$@ to repeat the whole default line,
so you do not have to re-type everything to add something to the default.

Everytime there is a substitution, you will have to confirm.  If there is an
error (e.g. an unmatched backtick), the default answer will remain unchanged
and you will be prompted again.

EOF
dflt="Press 'Return' to go on"
. ./.myread

cat << EOF

If you already have an autoexpect script file that contains the
maintenance actions you want to perform on the routers, you can
specify the name of this file and bypass the creation of a new
script file.

EOF

dflt="n"
rp="Do you want to bypass the creation of a new script file?"
. ./.myread
prescript=$ans

case "$prescript" in
y*|Y*)
  echo
  dflt=$nodef
  rp="Enter the name of the script file (~user ok)"
  . ./.myread
  ans=`./.tildexp "$ans"`
  defscript=$ans
  ;;
*)
cat << EOF

The multiple router maintenance program will record every action
that you perform on the "model" router.  This record is stored
in an autoexpect script file named "script.exp" by default, but
this file will be deleted at the end of the program.

EOF

dflt="n"
rp="Do you want to save the script file from this maintenance session?"
. ./.myread

savescript=$ans
case "$ans" in
y*|Y*)
  echo
  dflt=$defscript
  rp="Enter the name of the script file (~user ok)"
  . ./.myread
  ans=`./.tildexp "$ans"`
  defscript=$ans
  ;;
esac
;;
esac

cat << EOF

Before running the multiple router maintenance program, you must
have created a file that contains the symbolic IP address of
every router, one per line, that you want to update, or you can
use the default router names file, /network/routers/router.list

IMPORTANT: The router specified by the first symbolic IP address
           in the router names file will serve as the "model"
           router where you will perform your maintenance actions.

EOF

dflt=$defrouters
rp="Enter the name of the routers file (~user ok)"
. ./.myread
ans=`./.tildexp "$ans"`
defrouters=$ans

#
# If the user did not specify an existing autoexpect script file
# to use, then create a new one.
#
case "$prescript" in
n*|N*)
  #
  # Extract the IP address of the "model" router from the
  # router names file
  #
  modelrouter=`head -1 $defrouters`

  #
  # Create the autoexpect script file from the user's maintenance
  # actions that are performed on the "model" router
  #
  autoexpect -c -f $defscript -p telnet $modelrouter

cat << EOF

You may need to edit the script file that you created to
remove variable strings from the "expect -exact" commands.
For example, any strings that contain the current time
will not match when maintenance is performed on the other
routers.

However, the script is set to continue processing if an
"expect -exact" command does not match within 5 seconds.

EOF

dflt="n"
rp="Do you want to perform maintenance on the routers now?"
. ./.myread
perform_maint=$ans
;;
esac

case "$perform_maint" in
y*|Y*)
#
# If the user agrees, perform the maintenance actions from the
# script file on the various routers
#
awk -v defscript=$defscript '
  BEGIN {
    default_reply = "n"
    standard_input = "/dev/tty"
    defscript_file = defscript
    tempscript_file0 = "tempscript.exp0"
    tempscript_file = "tempscript.exp"
  }

  {
    if (NR == 1)
    {
      model = $0
      next
    }
    printf("Perform maintenance on %s [%s] ", $0, default_reply) 
    getline user_reply <standard_input
    if (length(user_reply) > 0)
    {
      user_reply = substr(user_reply,1,1)
    }
    else
    {
      user_reply = default_reply
    }
    user_reply = toupper(user_reply)
    if (user_reply == "Y")
    {
      temp = "sed \x27s/set timeout -1/set timeout 5/g\x27 " defscript_file " >" tempscript_file0 
      system(temp)
      temp = "sed \x27s/" model "/" $0 "/g\x27 " tempscript_file0 " >" tempscript_file 
      system(temp)
      temp = "chmod 755 " tempscript_file
      system(temp)
      system(tempscript_file)
      temp = "rm " tempscript_file " " tempscript_file0
      system(temp)
    }
  }

  END {
  }

' $defrouters
esac

#
# If the user does not want to save the script file, delete it
#
case "$savescript" in
n*|N*)
  rm -f $defscript
  ;;
esac

#
# Delete the temporary program files and reset the traps
#
rm -f $trapdeletefiles
trap 0 1 2 15

#
# End of script
#
exit 0