From 965f2376eca3e53f98eb26c53d8ff3c40c17d1de Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Wed, 8 Mar 2023 10:56:34 -0600 Subject: Rewrite readc to work with ash Also tested with dash --- does not work with bash --- vellum | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/vellum b/vellum index b436b6c..aee12d5 100755 --- a/vellum +++ b/vellum @@ -1,7 +1,7 @@ #!/bin/sh -# https://unix.stackexchange.com/a/464963 readc() { # arg: + # adapted from https://unix.stackexchange.com/a/464963 if [ -t 0 ]; then # if stdin is a tty device, put it out of icanon, set min and # time to sane value, but don't otherwise touch other input or @@ -10,21 +10,36 @@ readc() { # arg: saved_tty_settings=$(stty -g) stty -icanon min 1 time 0 fi - eval "$1=" - while - # read one byte, using a work around for the fact that command - # substitution strips the last character. - c=$(dd bs=1 count=1 2> /dev/null; echo .) + + # Sanitize any variable that's passed in + case "$1" in + c) var=_c ;; + var) var=_var ;; + '') var=REPLY ;; + *) var="$1" ;; + esac + + # Zero-out the variable + eval "$var=" + + # Read one full *character*, not *byte* + while :; do + c=$(dd bs=1 count=1 2>/dev/null; echo .) c=${c%.} - # break out of the loop on empty input (eof) or if a full character - # has been accumulated in the output variable (using "wc -m" to count - # the number of characters). - [ -n "$c" ] && - eval "$1=\${$1}"'$c - [ "$(($(printf %s "${'"$1"'}" | wc -m)))" -eq 0 ]'; do - continue + # Break on EOF + test -n "$c" || break + + eval "$var=\${$var}$c" + + # Break when we have a full character (wc -m) + test "$(eval printf %s "\$$var" | wc -m)" -eq 0 || break done + + # Round-trip sanitized variables + test "x$var" = x_c && eval c="\$$var" + test "x$var" = x_var && eval var="\$$var" + if [ -t 0 ]; then # restore settings saved earlier if stdin is a tty device. stty "$saved_tty_settings" -- cgit 1.4.1-21-gabe81