aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2019-01-18 16:54:13 -0800
committerRob Landley <rob@landley.net>2019-01-18 22:17:58 -0600
commite47144c8d0bc4fe1986403ade1e3d54a5c94f993 (patch)
tree1084cc7ceaf44539291e5135f4430caf81a316e4
parentad63ea18f8ff3c5e84fcec74a77c2a8146725eb2 (diff)
downloadtoybox-e47144c8d0bc4fe1986403ade1e3d54a5c94f993.tar.gz
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.
-rw-r--r--tests/xargs.test11
-rw-r--r--toys/posix/xargs.c50
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) {