From 53f4bc6a53fc228461d99e4f2d001d5f018fa883 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Thu, 13 May 2021 09:30:28 +0200 Subject: [PATCH] Re-fix 'test -t 1' in command substitutions (re: 090b65e7) Since a command substitution no longer forks on non-permanently redirecting standard output within it for a specific command, test -t 1, [ -t 1 ], and [[ -t 1 ]] broke as follows: v=$(test -t 1 >/dev/tty && echo ok) did not assign 'ok' to v. This is because the assumption in tty_check() that standard output is never on a terminal in a non-forked command substitution, added in 55f0f8ce, was made invalid by 090b65e7. src/cmd/ksh93/edit/edit.c: tty_check(): - Implement a new method. Return false if the file descriptor stream is of type SF_STRING, which is the case for non-forked command substitutions -- it means the sfio stream writes directly into a memory area. This can be checked with the sfset(3) function (see src/lib/libast/man/sfio.3). To avoid a segfault when accessing sh.sftable, we need to validate the FD first. src/cmd/ksh93/tests/pty.sh: - Add the above reproducer. --- NEWS | 5 +++++ src/cmd/ksh93/edit/edit.c | 10 ++++------ src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/tests/pty.sh | 2 ++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 72b9be4c1..87e19b1cb 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,11 @@ For full details, see the git log at: https://github.com/ksh93/ksh Any uppercase BUG_* names are modernish shell bug IDs. +2021-05-13: + +- Fixed a bug with 'test -t 1' that was introduced on 2021-04-26: + v=$(test -t 1 >/dev/tty && echo ok) did not assign 'ok' to v. + 2021-05-10: - Release 1.0.0-beta.1. diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c index a97f60adf..f48f83741 100644 --- a/src/cmd/ksh93/edit/edit.c +++ b/src/cmd/ksh93/edit/edit.c @@ -161,13 +161,11 @@ int tty_check(int fd) { register Edit_t *ep = (Edit_t*)(shgd->ed_context); struct termios tty; - /* - * The tty_get check below does not work on 1 (stdout) in command substitutions. But comsubs fork upon redirecting 1, - * and forking resets sh.subshell to 0, so we can safely return false when in a virtual subshell that is a comsub. - */ - if(fd==1 && sh.subshell && sh.comsub) - return(0); + Sfio_t *sp; ep->e_savefd = -1; + if(fd < 0 || fd > shgd->lim.open_max || sh.fdstatus[fd] == IOCLOSE + || (sp = sh.sftable[fd]) && (sfset(sp,0,0) & SF_STRING)) + return(0); return(tty_get(fd,&tty)==0); } diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index 93c1eb886..fa0e53090 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -21,7 +21,7 @@ #define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */ #define SH_RELEASE_SVER "1.0.0-beta.2" /* semantic version number: https://semver.org */ -#define SH_RELEASE_DATE "2021-05-10" /* must be in this format for $((.sh.version)) */ +#define SH_RELEASE_DATE "2021-05-13" /* must be in this format for $((.sh.version)) */ #define SH_RELEASE_CPYR "(c) 2020-2021 Contributors to ksh " SH_RELEASE_FORK /* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */ diff --git a/src/cmd/ksh93/tests/pty.sh b/src/cmd/ksh93/tests/pty.sh index 0101a4747..2975bb4b1 100755 --- a/src/cmd/ksh93/tests/pty.sh +++ b/src/cmd/ksh93/tests/pty.sh @@ -581,6 +581,7 @@ actual=$(echo begin; exec >/dev/tty; [ -n X -a -t ] && test -n X -a -t) \ # [ -t 1 ] to fail in non-comsub virtual subshells. ( test -t 1 ) && echo OK9 || echo 'test -t 1 in virtual subshell fails' ( test -t ) && echo OK10 || echo 'test -t in virtual subshell fails' +got=$(test -t 1 >/dev/tty && echo ok) && [[ $got == ok ]] && echo OK11 || echo 'test -t 1 in comsub fails' EOF tst $LINENO <<"!" L test -t 1 inside command substitution @@ -599,6 +600,7 @@ r ^OK7\r\n$ r ^OK8\r\n$ r ^OK9\r\n$ r ^OK10\r\n$ +r ^OK11\r\n$ r ^:test-2: !