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

Tweak and regress-test 'command -x' (re: 66e1d446)

Turns out the assumption I was operating on, that Linux and macOS
align arguments on 32 or 64 bit boundaries, is incorrect -- they
just need some extra bytes per argument. So we can use a bit more
of the arguments buffer on these systems than I thought.

src/cmd/ksh93/features/externs:
- Change the feature test to simply detect the # of extra bytes per
  argument needed. On *BSD and commercial Unices, ARG_EXTRA_BYTES
  shows as zero; on Linux and macOS (64-bit), this yields 8. On
  Linux (32-bit), this yields 4.

src/cmd/ksh93/sh/path.c: path_xargs():
- Do not try to calculate alignment, just add ARG_EXTRA_BYTES to
  each argument.
- Also add this when substracting the length of environment
  variables and leading and trailing static command arguments.

src/cmd/ksh93/tests/path.sh:
- Test command -v/-V with -x.
- Add a robust regression test for command -x.

src/cmd/ksh93/data/builtins.c, src/cmd/ksh93/sh.1:
- Tweak docs. Glob patterns also expand to multiple words.
This commit is contained in:
Martijn Dekker 2021-02-01 00:28:18 +00:00
parent f37098f177
commit 6a0e9a1a75
6 changed files with 103 additions and 44 deletions

View file

@ -489,17 +489,87 @@ EOF
print 'echo "wrong path used"' > $tmp/ls
chmod +x $tmp/ls
expect=/dev/null
actual=$(PATH=$tmp; redirect 2>&1; hash ls; command -p ls /dev/null)
actual=$(set +x; PATH=$tmp; redirect 2>&1; hash ls; command -p ls /dev/null)
[[ $actual == "$expect" ]] || err_exit "'command -p' fails to search default path if tracked alias exists" \
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
actual=$(PATH=$tmp; redirect 2>&1; hash ls; command -p ls /dev/null; exit) # the 'exit' disables subshell optimization
actual=$(set +x; PATH=$tmp; redirect 2>&1; hash ls; command -p ls /dev/null; exit) # the 'exit' disables subshell optimization
[[ $actual == "$expect" ]] || err_exit "'command -p' fails to search default path if tracked alias exists" \
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
expect=$(builtin getconf; PATH=$(getconf PATH); whence -p ls)
actual=$(PATH=$tmp; redirect 2>&1; hash ls; command -p -v ls)
actual=$(set +x; PATH=$tmp; redirect 2>&1; hash ls; command -p -v ls)
[[ $actual == "$expect" ]] || err_exit "'command -p -v' fails to search default path if tracked alias exists" \
"(expected $(printf %q "$expect"), got $(printf %q "$actual"))"
# Check that adding '-x' makes '-v'/'-V' look up external commands
if ((.sh.version >= 20210130))
then
exp=$tmp/echo
touch "$exp"
chmod +x "$exp"
got=$(PATH=$tmp; command -vx echo 2>&1)
[[ $got == "$exp" ]] || err_exit "'command -v -x' failed to look up external command in \$PATH" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
exp="echo is a tracked alias for $exp"
got=$(PATH=$tmp; command -Vx echo 2>&1)
[[ $got == "$exp" ]] || err_exit "'command -V -x' failed to look up external command in \$PATH" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
exp=$(PATH=${ getconf PATH 2>/dev/null; }; whence -p echo)
got=$(PATH=$tmp; command -pvx echo 2>&1)
[[ $got == "$exp" ]] || err_exit "'command -p -v -x' failed to look up external command in default path" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
exp="echo is $exp"
got=$(PATH=$tmp; command -pVx echo 2>&1)
[[ $got == "$exp" ]] || err_exit "'command -p -V -x' failed to look up external command in default path" \
"(expected $(printf %q "$exp"), got $(printf %q "$got"))"
fi
# 'command -x' used to hang in an endless E2BIG loop on Linux and macOS
ofile=$tmp/command_x_chunks.sh
trap 'sleep_pid=; while kill -9 $pid; do :; done 2>/dev/null; err_exit "'\''command -x'\'' hung"' TERM
{ sleep 15; kill $$; } &
sleep_pid=$!
(
export LC_ALL=C
unset IFS; set +f
builtin getconf && arg_max=$(getconf ARG_MAX) && let arg_max || { err_exit "getconf ARG_MAX not working"; exit 1; }
set +x # trust me, you don't want to xtrace what follows
# let's try to use a good variety of argument lengths
set -- $(typeset -p) $(functions) /dev/* /tmp/* /* *
args=$*
while let "${#args} < 3 * arg_max"
do set -- "$RANDOM" "$@" "$RANDOM" "$@" "$RANDOM"
args=$*
done
print "chunks=0 expargs=$# args=0 expsize=$((${#args}+1)) size=0"
unset args
command -px awk 'BEGIN {
ARGC -= 2; # final static args
for (i=1; i<ARGC; i++)
size += length(ARGV[i]) + 1;
print ("let chunks++ args+=")(ARGC - 1)(" size+=")(size);
if(ARGV[ARGC] != "static_arg_1" || ARGV[ARGC+1] != "final_static_arg_2")
print "err_exit \"'\''command -x'\'': static final arguments for chunk $chunks incorrect\"";
}' "$@" static_arg_1 final_static_arg_2
) >$ofile &
pid=$!
wait $pid
e=$?
trap - TERM
[[ $sleep_pid ]] && kill $sleep_pid
if let "e > 0"
then err_exit "'command -x' test yielded exit status $e$( let "e>128" && print -n / && kill -l "$e")"
fi
if [[ ! -s $ofile ]]
then err_exit "'command -x' test failed to produce output"
else save_Command=$Command
Command+=": ${ofile##*/}"
. "$ofile"
Command=$save_Command
let "args == expargs && size == expsize" || err_exit "'command -x' did not correctly divide arguments" \
"(expected $expargs args of total size $expsize, got $args args of total size $size;" \
"divided in $chunks chunks)"
fi
# ======
# whence -a/-v tests