Timeout for interactive input 

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

eread 

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