#!/bin/sh # #From: Jeff Bowyer #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 <\&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 < .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 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