1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Fix command substitutions in here-docs (rhbz#994241, rhbz#1036802)

When ksh was compiled with SHOPT_SPAWN (the default), any command
substitution embedded in a here-document returned an empty string.
The bug was also present in 93u+ 2012-08-01 (although not in every
case as some systems compile it without SHOPT_SPAWN).

This fixes it by applying a slightly edited combination of two Red
Hat patches (the second containing a fix for the first), which
backport a new command substitution mechanism from the abandoned
ksh 93v- beta version. The originals are:

642af4d6/f/ksh-20120801-macro.patch
642af4d6/f/ksh-20120801-fd2lost.patch

src/cmd/ksh93/include/io.h:
- The iopipe() function from xec.c is now needed in sh_subshell()
  (subshell.c), so rename it to sh_iounpipe() and declare it as an
  extern here. The 93v- beta did it as well. (The Red Hat patch did
  this without renaming it.)

src/cmd/ksh93/sh/xec.c:
- Backport new versions of iousepipe() and sh_iounpipe() from ksh
  93v-. New 'type' flaggery is introduced to distinguish between
  different command substitution conditions. What all that means
  remains to be determined.
- sh_exec(): I made one change to the Red Hat patch myself: if in a
  subshell and the type flags FAMP (for "ampersand" as in '&' as in
  background job) and TFORK are set, continue to call sh_subfork()
  to fork the subshell unconditionally, instead of only if we're in
  a command substitution connected to an unseekable file. Maybe the
  latter works for the 93v- code, but on 93u+(m) it causes a couple
  of regressions, which are fixed by my change:
  signal.sh[273]: subshell ignoring signal does not send signal to parent
  signal.sh[276]: subshell catching signal does not send signal to parent
  Details: https://github.com/ksh93/ksh/issues/104#issuecomment-696341902

src/cmd/ksh93/sh/macro.c,
src/cmd/ksh93/sh/subshell.c:
- Updates that go with those new functions.

Fixes:   https://github.com/ksh93/ksh/issues/104
Affects: https://github.com/ksh93/ksh/issues/124
This commit is contained in:
Martijn Dekker 2020-09-21 23:02:08 +02:00
parent 0d3bedd67d
commit 970069a6fe
6 changed files with 111 additions and 30 deletions

View file

@ -272,10 +272,22 @@ done < tst.got
if [[ ${SIG[USR1]} ]]
then float s=$SECONDS
[[ $(LC_ALL=C $SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "" USR1 ; exec kill -USR1 $$ & sleep .5); print done') == SIGUSR1 ]] || err_exit 'subshell ignoring signal does not send signal to parent'
exp=SIGUSR1
got=$(LC_ALL=C $SHELL -c '
trap "print SIGUSR1 ; exit 0" USR1
(trap "" USR1 ; exec kill -USR1 $$ & sleep .5)
print done')
[[ $got == "$exp" ]] || err_exit 'subshell ignoring signal does not send signal to parent' \
"(expected '$exp', got '$got')"
(( (SECONDS-s) < .4 )) && err_exit 'parent does not wait for child to complete before handling signal'
((s = SECONDS))
[[ $(LC_ALL=C $SHELL -c 'trap "print SIGUSR1 ; exit 0" USR1; (trap "exit" USR1 ; exec kill -USR1 $$ & sleep .5); print done') == SIGUSR1 ]] || err_exit 'subshell catching signal does not send signal to parent'
exp=SIGUSR1
got=$(LC_ALL=C $SHELL -c '
trap "print SIGUSR1 ; exit 0" USR1
(trap "exit" USR1 ; exec kill -USR1 $$ & sleep .5)
print done')
[[ $got == "$exp" ]] || err_exit 'subshell catching signal does not send signal to parent' \
"(expected '$exp', got '$got')"
(( SECONDS-s < .4 )) && err_exit 'parent completes early'
fi

View file

@ -759,5 +759,40 @@ SHELL=$SHELL "$SHELL" -c '
' | awk '/^DEBUG/ { pid[NR] = $2; } END { exit !(pid[1] == pid[2] && pid[2] == pid[3]); }' \
|| err_exit "setting PATH to readonly in subshell triggers an erroneous fork"
# ======'
# Test command substitution with external command in here-document
# https://github.com/ksh93/ksh/issues/104
expect=$'/dev/null\n/dev/null'
actual=$(
cat <<-EOF
$(ls /dev/null)
`ls /dev/null`
EOF
)
[[ $actual == "$expect" ]] || err_exit 'Command substitution in here-document fails' \
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
# ...and in pipeline (rhbz#994251)
expect=/dev/null
actual=$(cat /dev/null | "$binecho" `ls /dev/null`)
[[ $actual == "$expect" ]] || err_exit 'Command substitution in pipeline fails (1)' \
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
# ...and in pipeline again (rhbz#1036802: standard error was misdirected)
expect=$'END2\naaa\nEND1\nEND3'
actual=$(export bincat binecho; "$SHELL" 2>&1 -c \
'function foo
{
"$binecho" hello >/dev/null 2>&1
"$binecho" aaa | "$bincat"
echo END1
echo END2 >&2
}
echo "$(foo)" >&2
echo END3 >&2
exit')
[[ $actual == "$expect" ]] || err_exit 'Command substitution in pipeline fails (2)' \
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
# ======
exit $((Errors<125?Errors:125))