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: fix efficiency; always run external cmd (re: acf84e96)

This commit fixes 'command -x' to adapt to OS limitations with
regards to data alignment in the arguments list. A feature test is
added that detects if the OS aligns the argument on 32-bit or
64-bit boundaries or not at all, allowing 'command -x' to avoid
E2BIG errors while maximising efficiency.

Also, as of now, 'command -x' is a way to bypass built-ins and
run/query an external command. Built-ins do not limit the length of
their argument list, so '-x' never made sense to use for them. And
because '-x' hangs on Linux and macOS on every ksh93 release
version to date (see acf84e96), few use it, so there is little
reason not to make this change.

Finally, this fixes a longstanding bug that caused the minimum exit
status of 'command -x' to be 1 if a command with many arguments was
divided into several command invocations. This is done by replacing
broken flaggery with a new SH_XARG state flag bit.

src/cmd/ksh93/features/externs:
- Add new C feature test detecting byte alignment in args list.
  The test writes a #define ARG_ALIGN_BYTES with the amount of
  bytes the OS aligns arguments to, or zero for no alignment.

src/cmd/ksh93/include/defs.h:
- Add new SH_XARG state bit indicating 'command -x' is active.

src/cmd/ksh93/sh/path.c: path_xargs():
- Leave extra 2k in the args buffer instead of 1k, just to be sure;
  some commands add large environment variables these days.
- Fix a bug in subtracting the length of existing arguments and
  environment variables. 'size -= strlen(cp)-1;' subtracts one less
  than the size of cp, which makes no sense; what is necessary is
  to substract the length plus one to account for the terminating
  zero byte, i.e.: 'size -= strlen(cp)+1'.
- Use the ARG_ALIGN_BYTES feature test result to match the OS's
  data alignment requirements.
- path_spawn(): E2BIG: Change to checking SH_XARG state bit.

src/cmd/ksh93/bltins/whence.c: b_command():
- Allow combining -x with -p, -v and -V with the expected results
  by setting P_FLAG to act like 'whence -p'. E.g., as of now,
	command -xv printf
  is equivalent to
	whence -p printf
  but note that 'whence' has no equivalent of 'command -pvx printf'
  which searches $(getconf PATH) for a command.
- When -x will run a command, now set the new SH_XARG state flag.

src/cmd/ksh93/sh/xec.c: sh_exec():
- Change to using the new SH_XARG state bit.
- Skip the check for built-ins if SH_XARG is active, so that
  'command -x' now always runs an external command.

src/lib/libcmd/date.c, src/lib/libcmd/uname.c:
- These path-bound builtins sometimes need to run the external
  system command by the same name, but they did that by hardcoding
  an unportable direct path. Now that 'command -x' runs an external
  command, change this to using 'command -px' to guarantee using
  the known-good external system utility in the default PATH.
- In date.c, fix the format string passed to 'command -px date'
  when setting the date; it was only compatible with BSD systems.
  Use the POSIX variant on non-BSD systems.
This commit is contained in:
Martijn Dekker 2021-01-30 05:51:22 +00:00
parent 005d38f410
commit 66e1d44642
12 changed files with 239 additions and 75 deletions

View file

@ -5844,19 +5844,33 @@ rather than the one defined by the value of
.IP
The
.B \-x
option allows executing non-built-in commands with argument lists exceeding
limitations imposed by the operating system. This functionality is similar to
option runs
.I name\^
as an external command, bypassing built-ins.
If the arguments contain a word that expands to multiple arguments, such as
\f3"$@"\fP or \f3"${array[@]}"\fP, then the
.B \-x
option also allows executing external commands with argument lists that are
longer than the operating system allows. This functionality is similar to
.BR xargs (1)
but is easier to use.
If a command cannot ordinarily be executed because there are too many
arguments, the shell will invoke the indicated command multiple times
with a subset of the arguments on each invocation.
Any arguments (such as command options) that come before the first word
that expands to multiple arguments, as well as any that follow the last
word that expands to multiple arguments, are considered static arguments
and are repeated for each invocation. When all invocations are completed,
but is easier to use. The shell does this by invoking the external command
multiple times if needed, dividing the expanded argument list over the
invocations. Any arguments that come before the first \f3"$@"\fP or similar
expansion, as well as any that follow the last \f3"$@"\fP or similar, are
considered static arguments and are repeated for each invocation. This allows
each invocation to use the same command options, as well as the same trailing
destination arguments for commands like
.BR cp (1)
or
.BR mv (1).
When all invocations are completed,
.B "command \-x"
exits with the status of the invocation that had the highest exit status.
(Note that
.B "command \-x"
may still fail with an "argument list too long" error if a single argument
exceeds the maximum length of the argument list, or if no \f3"$@"\fP or
similar expansion was used.)
.TP
\(dd \f3compound\fP \f2vname\fP\*(OK\f3=\fP\f2value\^\fP\*(CK .\|.\|.
Causes each
@ -6838,7 +6852,7 @@ Any file descriptor numbers greater than
.B 2
that are opened with this mechanism are closed when invoking another program,
unless they are explicitly redirected to themselves as part of that invocation
(e.g. \fb4>&4\fR) or the \fBposix\fR shell option is active.
(e.g. \fB4>&4\fR) or the \fBposix\fR shell option is active.
.TP
\(dg \f3return\fP \*(OK \f2n\^\fP \*(CK
Causes a shell