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

@ -12,18 +12,13 @@ extern nice int (int)
extern setreuid int (uid_t,uid_t)
extern setregid int (gid_t,gid_t)
tst note{ determining data alignment factor for arguments list }end output{
tst note{ determining extra bytes per argument for arguments list }end output{
/*
* Feature test to figure out if this OS does data alignment on
* the arguments list of a process, and if so, at how many bits.
* Outputs an appropriate #define ARG_ALIGN_BITS.
* Figure out if this OS requires extra bytes per argument
* in the arguments list of a process.
* Outputs an appropriate #define ARG_EXTRA_BYTES.
* Without this, 'command -x' failed with E2BIG on macOS and Linux even
* if all the arguments should fit in ARG_MAX based on their length.
*
* Strategy: first try to fill as many single-character arguments as
* should fit in ARG_MAX without alignment. If that fails with E2BIG,
* then start with a 2-byte alignment factor and keep doubling it
* until we either succeed or exceed an absurdly large value.
*/
/* AST includes */
@ -48,13 +43,13 @@ tst note{ determining data alignment factor for arguments list }end output{
int main(int argc,char *argv[])
{
int align_bytes = 0, envlen = 0, argmax, i;
int extra_bytes = 0, envlen = 0, argmax, i;
pid_t childpid;
error_info.id="args list aligment test (parent)";
error_info.id="ARG_EXTRA_BYTES test (parent)";
for(i=0; environ[i]; i++)
envlen += strlen(environ[i]) + 1;
argmax = strtoimax(astconf("ARG_MAX",NiL,NiL),NiL,0) - envlen - 1024;
argmax = strtoimax(astconf("ARG_MAX",NiL,NiL),NiL,0) - 2 * envlen;
if (argmax < 2048)
{
error(ERROR_ERROR|2, "argmax too small");
@ -67,7 +62,7 @@ tst note{ determining data alignment factor for arguments list }end output{
/* child */
int bytec;
error_info.id="args list aligment test (child)";
error_info.id="ARG_EXTRA_BYTES test (child)";
argv = (char **)stakalloc((argmax / 2 + 1) * sizeof(char*));
argc = bytec = 0;
while(bytec < argmax)
@ -78,9 +73,8 @@ tst note{ determining data alignment factor for arguments list }end output{
argv[argc] = "true";
else
argv[argc] = "x";
bytec += strlen(argv[argc]) + 1 + align_bytes;
if(align_bytes)
bytec += bytec % align_bytes;
/* also add 1 for terminating zero byte */
bytec += strlen(argv[argc]) + 1 + extra_bytes;
argc++;
}
argv[argc] = (char*)0;
@ -114,11 +108,8 @@ tst note{ determining data alignment factor for arguments list }end output{
}
if (exitstatus == 0)
break; /* yay :) */
if (!align_bytes)
align_bytes = 2;
else
align_bytes *= 2;
if (align_bytes > 256)
extra_bytes++;
if (extra_bytes > 256)
{
error(ERROR_ERROR|2, "giving up");
return 1;
@ -126,10 +117,10 @@ tst note{ determining data alignment factor for arguments list }end output{
}
}
sfprintf(sfstdout,
"#define ARG_ALIGN_BYTES\t%d\t/* data alignment factor for arguments list */\n",
align_bytes);
"#define ARG_EXTRA_BYTES\t%d\t/* extra bytes per argument for arguments list */\n",
extra_bytes);
return 0;
}
}end fail{
echo "#define ARG_ALIGN_BYTES 16 /* BUG: arg list alignment factor test failed; assuming 16 */"
echo "#define ARG_EXTRA_BYTES 8 /* BUG: test failed; assuming 8 */"
}end