I'm writing a bash script to read some user input (like a password request), and I'd like to capture the result and pass it through its stdout. (I'm working in a GNU/Linux environment, with recent software).
Here is a simplified version of the script that reproduces the issues
# read_input.sh # # Issue B : redirection of "3>&1" here causes stty error when # this script is executed via a command subsitution context subshell exec 3>&1 </dev/tty >/dev/tty tty_settings=`stty -g` # Issue A : uncommented version doesn't restore tty properly. #trap 'stty "$tty_settings";' EXIT #trap 'echo "...interrupting"; exit 1' INT ABRT HUP QUIT TERM trap 'echo "...interrupting"; stty "$tty_settings"; exit 1' INT ABRT HUP QUIT TERM stty -echo echo "Enter input: " input="" while IFS= read -r -n1 char; do # nb: stripped out proper char handling code here, # (except return), for simplicity if [[ $char = "" ]]; then break fi input+=$char echo -n "*" done echo "" stty "$tty_settings" #trap - EXIT INT ABRT HUP QUIT TERM trap - INT ABRT HUP QUIT TERM echo "$input" >&3
The intention is to write to fd 3 the result input (if this script's stdout on invocation is connected in a pipe) - while still having tty during interaction. I then modify the tty with stty to control echo, etc, restoring any modifications via handling with trap.
I've encountered two problems with this.
On restoration to the controlling terminal, echo was suppressed. I had to use the two line trap handling case (commented out), instead of the active one line handler case uncommented.
In the one line case - say on INT : the tty is restored, then exit is called via the handler. I'm not trapping EXIT itself - why would that be required?
This is related to exec's "3>&1" redirection in a subshell context.
For some reason, say I run this script ("read_input.sh") in a subshell - and want to grab its output from another script via command substitution:
# read_input_caller.sh input=$(sh read_input.sh) echo "$input"
I found the stty invocation in the trap handler complained with the following on interrupting the calling script (say with ^C):
stty: 'standard input': Input/output error
That error message only happens because of the "3>&1" redirection in the exec line - calling that exec line without "3>&1", there's no stty error (but not very useful for passing the input to stdout). I can't think why this would be the case?
In the calling script, another subshell invocation like
sh read_input.sh | cat
Does not produce this error.
Interestingly, when issue B ocurred, the controlling terminal's tty seemed to be restored properly, even under the problematic trapping/restoration of issue A.