Newsgroups: comp.unix.shell Date: 1998/09/26 http://groups.google.com/groups?hl=en&safe=off&th=b447f98bb582494e,3&seekm=6ujb2j%24442%241%40supernews.com#p
: Anyone know how to create a timeout when the shell script is waiting : for interactive input ?
There was a thread on this a few weeks ago, you can get probably still get the posts off of www.dejanews.com. I can't remember them all, but mine was something like:
case `uname` in SunOS) ALRM=14;; *) ALRM=14;; esac alarm () { alrm_tmout="$1"; shift if [ "$alrm_tmout" -ne 0 ]; then trap "trap $ALRM; wait \$alrm_pid; unset alrm_pid; $*" $ALRM alrm_ppid=$$ (sleep $alrm_tmout; kill -$ALRM $alrm_ppid) >&- 2>&- & alrm_pid=$! elif [ -n "$alrm_pid" ]; then trap $ALRM kill -15 $alrm_pid wait $alrm_pid unset alrm_pid fi }
Then use it like so:
echo 'prompt \c' alarm 5 "signal=2" read ans alarm 0 echo "the answer was '$ans'; signal='$signal'"
You may have to check the value of ALRM, some older systems have been known to change it.
I would look at the news postings from a few weeks ago to find an appropriate solution for you.
Arcege
Here is a enhanced "read" function suitable for specifing timeouts (option -t) as well as many other features, including prompts, default values, unbuffered mode, and no-echo mode.
Eread has been optimized to function best as an autoloaded function. In such a case, a symbolic link in your FPATH may be made to "read", in which case the function below will be used in lieu of the builtin, with no change of code.
You do not specify the shell, so I presume that you are able to use the "autoload" built in to ksh(1).
-Brian
file "eread" in FPATH:
#! /bin/echo error: only source #*TAG:34872 5:Sep 25 1998:0644:eread: # Author: Brian Hiles <bsh@iname.com> # Copyright: (c) 1996-1998 # Description: enhanced read function # Name: eread # Sccs: @(#)eread.sh 1.5 1997/12 bsh@iname.com (Brian Hiles) # Usage: eread [-ce] [-dp string] [-t digit] -- [read-option]... [varname]... # Varmap: /_1/default/,/_2/inkey/,/_3/noecho/,/_4/ntharg/,/_5/ostty/,/_6/prmpt/,/_7/readopts/,/_8/ring/,/_9/tmout/ # Version: 1.05 #01 eread() # [-ce] [-dp string] [-t digit] -- [read-option]... [varname]... { OPTIND=1 deflt= inkey= noecho= ntharg= ostty= prmpt= readopts= ring= tmout= while getopts :Ccd:Eep:t: _inst do case $_inst in c) inkey=ON ;; +c|C) inkey= ;; d) deflt=$OPTARG ;; e) noecho=ON autoload echon ;; # sh: need to source ./autoload! +e|E) noecho= ;; p) prmpt=$OPTARG autoload echon ;; # sh: need to source ./autoload! t) tmout=$OPTARG ;; [:?]) echo >&2 'usage: eread [-ce] [-d default]' \ '[-p prompt] [-t timeout] [-u filedes] --' \ '[read-option]... [varname]...' return 2 ;; esac done # do: shift `/bin/expr 0$OPTIND - 1` if test 0$OPTIND -gt 0$# then set X && shift else eval ntharg=\$$OPTIND shift $OPTIND set -- "$ntharg" "$@" fi for _inst do case $_inst in -*) readopts="$readopts $_inst" shift ;; *) break ;; esac done eval ${prmpt:+'echon "$prmpt"'} test X$noecho = XON -o X$inkey = XON && ostty=`/bin/stty -g` eval ${noecho:+'/bin/stty -echo'} #XXX -ixon ?? eval ${inkey:+'/bin/stty -icanon -noflsh isig eof \^A'} if test X$inkey = XON then # stty timeout apparently works only with _buffered_ input eval ${tmout:+'/bin/stty time ${tmout}0 min 0'} eval "${1:-REPLY}=`/bin/dd count=1 bs=1 2>/dev/null`" else # another technique is needed with unbuffered input # ksh: turn off job control mode: "set +o monitor" eval ${tmout:+'trap ring=ON 2 (sleep $tmout; kill -2 $$) >/dev/null 2>&1 &'} read $readopts ${*:-REPLY} eval ${tmout:+'test X$ring = X && kill $! trap 2'} fi eval ${deflt:+": \${${1:-REPLY}:='$deflt'}"} eval ${ostty:+'/bin/stty $ostty'} return 0 } #02 EMBEDDED MAN-PAGE FOR "src2man" : ' #++ NAME eread - enhanced read function SYNOPSIS eread [-ce] [-dp string] [-t digit] -- [read-option]... [varname]... DESCRIPTION Eread extends the "read" builtin in sh(1) and ksh(1) to provide a default (given a null input), a selectable time limit, canonical input (a newline is not waited for), suppression of terminal echo (handy for the entering of passwords), as well as other features. In both the shells, if IFS is null the read will not strip leading and following whitespace before assigning it to the variable, as it will do by default. In ksh(1) only, the value of IFS is used to perform word splitting upon the input. Many Unix users are not aware that a simple built-in editor comprising the commands ^R, ^U, ^V, and ^W are almost always available (even during reads) as a feature of the terminal driver, performing the interactive functions redisplay-line, erase-line, quote-next, and backspace-over-word, respectively. ^H is similarly available to do backspace-over-character, but this is frequently mapped to another key, usually DEL or Backspace. Command "stty -a" to determine these. In addition: an undocumented feature in ksh(1) is that history substitution is available even within a read if $HISTFILE is set and a built-in editor is enabled with "set -o vi" or "set -o emacs". Give the line-up, line-down, or search-pattern commands of those editors to scroll from command to command (or input to input). The "-s" option to "print" and "read" is available to append to this history non-interactively. See the man pages for sh(1) and ksh(1) for more details. Eread has been developed and tested under SunOS 4.x, but should ;) be portable to other Unices and bourne compatible shells. OPTIONS -c - Read one character; do not wait for a newline. -d str - Specify default value <str> if input is null. -e - Input is not echoed to terminal. -p str - Print a prompt <str>. -t num - Timeout the read after <num> seconds. RETURN CODE 0 for successful read, 1 for unsuccessful read, and 2 for error in options parsing. EXAMPLE Refer to script $SIDEROOT/demo/eread.demo. ENVIRONMENT IFS SEE ALSO echon(3L) BUGS Note that it makes no sense to specify more than one variable when eread is given the -c and/or -d options. Typing the INT signal (typically ^C) before terminal line discipline is reset after a -c or -e option may leave the terminal in an undefined state. This function works better in ksh(1) than in sh(1), although it is only written using the syntax of the latter shell. #-- '
file "echon" in FPATH:
#! /bin/echo error: only source #*TAG:56509 2:Sep 25 1998:0644:echon: # Author: Brian Hiles <bsh@iname.com> # Copyright: (c) 1996-1998 # Description: portable version of echo when no terminating newline is desired # Name: echon # Sccs: @(#)echon.sh 1.2 1998/04 bsh@iname.com (Brian Hiles) # Usage: echon [string]... # Varmap: /_1/bsd_nonl/,/_2/sysv_nonl/ # Version: 1.02 #01 echon() # [string]... { _1= _2= # Warning: always set variable ECHON to null whenever changing PATH # Warning: never export variable ECHON! case ${ECHON:=`echo -n X`} in -n*) # SysV echo emulation: /usr/5bin/echo _1= _2=\\c ;; X) # BSD echo emulation: /usr/bin/echo _1=-n _2= ;; *) ;; esac echo $_1 "$@"$_2 return 0 } #02 EMBEDDED MAN-PAGE FOR "src2man" : ' #++ NAME echon - echo when no terminating newline is desired SYNOPSIS echon [string]... DESCRIPTION One would think that because the echo is a builtin in modern shells would guarantee a consistent option syntax for printing with a terminating newline. Unfortunately, because System V Unix and BSD Unix have a version of /bin/echo that implement different option syntax to print with no terminating newlines, scripts that desire to do so have to be manually configured. SunOS Unix has an echo builtin that will emulate either behavior depending on whether /usr/5bin appears before /usr/bin in the PATH. Unfortunately again, this is but a half-measure, and endemic only to that OS. Ksh "print" has a consistent interface, but scripts designed to be portable need to be scripted in sh(1). Echon serves to print with no newline in a completely portable fashion, regardless of the Unix implementation or whether echo is an external command or a builtin. ENVIRONMENT ECHON - caches result of test between System V echo and BSD echo. XXX SEE ALSO eread(3L) BUGS If echon has been previously executed and variable PATH is then changed, echon may erroneously use the wrong echo syntax. If PATH is changed, unset variable ECHON at the same time. #-- '