From e47144c8d0bc4fe1986403ade1e3d54a5c94f993 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 18 Jan 2019 16:54:13 -0800 Subject: xargs: make --help match reality. Implement -p, -t, and -r. Add some missing tests. Move -L and -x back to TODO since they're not implemented and I haven't yet even understood what they're supposed to do. --- tests/xargs.test | 11 +++++++++++ toys/posix/xargs.c | 50 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/tests/xargs.test b/tests/xargs.test index 407817cc..dce93ed3 100644 --- a/tests/xargs.test +++ b/tests/xargs.test @@ -27,6 +27,17 @@ rm one two three testing "-0 -n1" "printf 'a\0b\0c\0d\0e\0f' | xargs -0 -n1 echo _" "_ a\n_ b\n_ c\n_ d\n_ e\n_ f\n" "" "" testing "-0 -n2" "printf 'a\0b\0c\0d\0e\0f' | xargs -0 -n2 echo _" "_ a b\n_ c d\n_ e f\n" "" "" +testing "-t" "xargs -t 2>stderr ; cat stderr ; rm stderr" "one two\necho one two \n" "" "one\ntwo\n" + +testing "-E END" "xargs -E END" "a b\n" "" "a\nb\nEND\nc\nd\n" + +testing "-r" "xargs -r echo x" "" "" "" + +# TODO: what exactly is -x supposed to do? why does coreutils output "one"? +#testing "-x" "xargs -x -s 9 || echo expected" "one\nexpected\n" "" "one\ntwo\nthree" + +# TODO: test for -L? what exactly is the difference between -n and -L? + #testing "-n exact match" #testing "-s exact match" #testing "-s 0" diff --git a/toys/posix/xargs.c b/toys/posix/xargs.c index d25a2e3f..e23d14c4 100644 --- a/toys/posix/xargs.c +++ b/toys/posix/xargs.c @@ -5,28 +5,28 @@ * See http://opengroup.org/onlinepubs/9699919799/utilities/xargs.html * * TODO: Rich's whitespace objection, env size isn't fixed anymore. + * TODO: -x Exit if can't fit everything in one command + * TODO: -L Max number of lines of input per command -USE_XARGS(NEWTOY(xargs, "^I:E:L#ptxrn#<1s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN)) +USE_XARGS(NEWTOY(xargs, "^I:E:ptrn#<1s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN)) config XARGS bool "xargs" default y help - usage: xargs [-ptxr0] [-s NUM] [-n NUM] [-L NUM] [-E STR] COMMAND... + usage: xargs [-0prt] [-s NUM] [-n NUM] [-E STR] COMMAND... Run command line one or more times, appending arguments from stdin. If command exits with 255, don't launch another even if arguments remain. - -s Size in bytes per command line - -n Max number of arguments per command -0 Each argument is NULL terminated, no whitespace or quote processing - #-p Prompt for y/n from tty before running each command - #-t Trace, print command line to stderr - #-x Exit if can't fit everything in one command - #-r Don't run command with empty input - #-L Max number of lines of input per command - -E stop at line matching string + -E Stop at line matching string + -n Max number of arguments per command + -p Prompt for y/n from tty before running each command + -r Don't run command with empty input + -s Size in bytes per command line + -t Trace, print command line to stderr config XARGS_PEDANTIC bool "TODO xargs pedantic posix compatability" @@ -41,7 +41,7 @@ config XARGS_PEDANTIC #include "toys.h" GLOBALS( - long s, n, L; + long s, n; char *E, *I; long entries, bytes; @@ -134,6 +134,8 @@ void xargs_main(void) // Loop through exec chunks. while (data || !done) { + int doit = 1; + TT.entries = 0; TT.bytes = bytes; @@ -163,6 +165,8 @@ void xargs_main(void) break; } + if (TT.entries == 0 && FLAG(r)) continue; + // Accumulate cally thing if (data && !TT.entries) error_exit("argument too long"); @@ -176,13 +180,25 @@ void xargs_main(void) for (dtemp = dlist; dtemp; dtemp = dtemp->next) handle_entries(dtemp->data, out+entries); - if (!(pid = XVFORK())) { - xclose(0); - open("/dev/null", O_RDONLY); - xexec(out); + if (FLAG(p) || FLAG(t)) { + int i; + + for (i = 0; out[i]; ++i) fprintf(stderr, "%s ", out[i]); + if (FLAG(p)) { + fprintf(stderr, "?"); + doit = yesno(0); + } else fprintf(stderr, "\n"); + } + + if (doit) { + if (!(pid = XVFORK())) { + xclose(0); + open("/dev/null", O_RDONLY); + xexec(out); + } + waitpid(pid, &status, 0); + status = WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+127; } - waitpid(pid, &status, 0); - status = WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+127; // Abritrary number of execs, can't just leak memory each time... while (dlist) { -- cgit v1.2.3