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

'command -x': also bypass path-bound built-ins (re: 66e1d446)

Since 'command -x' provides xargs-like functionality to repeatedly
run external commands if the argument list is too long for one
invocation, it makes little sense to use with built-ins. So I
decided that 'command -x' should double as a way to guarantee
running an external command. However, it was only bypassing plain
built-ins and not path-bound builtins (the ones that show up with a
virtual directory path name in the output of 'builtin').

src/cmd/ksh93/sh/path.c:
- Before looking for a path-bound built-in, check that the SH_XARG
  state bit is not on. This needs to be done in path_absolute() as
  well as in path_spawn().
This commit is contained in:
Martijn Dekker 2022-07-24 07:26:43 +02:00
parent 89d5b8cde1
commit 3e79027cd1
3 changed files with 14 additions and 2 deletions

3
NEWS
View file

@ -14,6 +14,9 @@ Any uppercase BUG_* names are modernish shell bug IDs.
- Fixed a bug that caused the -b/--notify option to only notify on one job if - Fixed a bug that caused the -b/--notify option to only notify on one job if
more than one background job completed at the same time. more than one background job completed at the same time.
- Fixed a bug in the 'command -x' feature introduced on 2021-01-30; it is meant
to always run an external command, but failed to bypass path-bound builtins.
2022-07-21: 2022-07-21:
- Fixed a bug where a reproducible $RANDOM sequence (after assigning a - Fixed a bug where a reproducible $RANDOM sequence (after assigning a

View file

@ -757,7 +757,7 @@ Pathcomp_t *path_absolute(register const char *name, Pathcomp_t *pp, int flag)
int n; int n;
#endif #endif
/* Handle default path-bound builtins */ /* Handle default path-bound builtins */
if(*stakptr(PATH_OFFSET)=='/' && nv_search(stakptr(PATH_OFFSET),sh.bltin_tree,0)) if(!sh_isstate(SH_XARG) && *stakptr(PATH_OFFSET)=='/' && nv_search(stakptr(PATH_OFFSET),sh.bltin_tree,0))
return(oldpp); return(oldpp);
#if SHOPT_DYNAMIC #if SHOPT_DYNAMIC
/* Load builtins from dynamic libraries */ /* Load builtins from dynamic libraries */
@ -1054,7 +1054,7 @@ pid_t path_spawn(const char *opath,register char **argv, char **envp, Pathcomp_t
char *s, *v; char *s, *v;
int r, n, pidsize; int r, n, pidsize;
pid_t pid= -1; pid_t pid= -1;
if(nv_search(opath,sh.bltin_tree,0)) if(!sh_isstate(SH_XARG) && nv_search(opath,sh.bltin_tree,0))
{ {
/* Found a path-bound built-in. Since this was not caught earlier in sh_exec(), it must /* Found a path-bound built-in. Since this was not caught earlier in sh_exec(), it must
have been found on a temporarily assigned PATH, as with 'PATH=/opt/ast/bin:$PATH cat'. have been found on a temporarily assigned PATH, as with 'PATH=/opt/ast/bin:$PATH cat'.

View file

@ -518,6 +518,15 @@ then
"(expected $(printf %q "$exp"), got $(printf %q "$got"))" "(expected $(printf %q "$exp"), got $(printf %q "$got"))"
fi fi
# Check that adding '-x' runs an external command, also bypassing path-bound builtins
if ! test -x /opt/ast/bin/cat # a physical external utility here would invalidate these tests
then
got=$( PATH=/opt/ast/bin; command -x cat --about 2>&1 )
[[ $got == *version*'cat ('* ]] && err_exit 'command -x fails to bypass path-bound built-in found in PATH search'
got=$( command -x /opt/ast/bin/cat --about 2>&1 )
[[ $got == *version*'cat ('* ]] && err_exit 'command -x fails to bypass path-bound built-in by direct pathname'
fi
# ====== # ======
# 'command -x' used to hang in an endless E2BIG loop on Linux and macOS # 'command -x' used to hang in an endless E2BIG loop on Linux and macOS
ofile=$tmp/command_x_chunks.sh ofile=$tmp/command_x_chunks.sh