aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2019-08-17 20:13:38 -0700
committerRob Landley <rob@landley.net>2019-08-26 21:54:44 -0500
commit0ec6b113985f4470e021f84b216c1b98e1e194ad (patch)
treec286b8d3792648fd5eef78a65f4be8206b1f0079
parentc26870dab3462c6176936384b090df6b9ba46dee (diff)
downloadtoybox-0ec6b113985f4470e021f84b216c1b98e1e194ad.tar.gz
xargs: add --max-args synonym, -o option, and fix -p.
The Linux kernel uses the --max-args synonym for -n. Barbarians who use vi need xargs' -o to be able to do something like: find -name xargs.c | xargs vi # Sad vi. find -name xargs.c | xargs -o vi # Happy vi. The -p option needs fixing to read from /dev/tty because stdin is otherwise occupied in xargs. I think xargs is the only place that needs this, so it didn't seem sensible to make all callers to yesno() be specific about which they wanted, hence the new function. Also remove the documentation for the build-time XARGS_PEDANTIC option which isn't actually implemented. Also add a TODO for -P (which is used by at least one script in the Linux kernel).
-rw-r--r--lib/lib.c7
-rw-r--r--lib/lib.h1
-rw-r--r--toys/posix/xargs.c20
3 files changed, 16 insertions, 12 deletions
diff --git a/lib/lib.c b/lib/lib.c
index 282e16d3..ab66b66e 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -819,11 +819,16 @@ void base64_init(char *p)
int yesno(int def)
{
+ return fyesno(stdin, def);
+}
+
+int fyesno(FILE *in, int def)
+{
char buf;
fprintf(stderr, " (%c/%c):", def ? 'Y' : 'y', def ? 'n' : 'N');
fflush(stderr);
- while (fread(&buf, 1, 1, stdin)) {
+ while (fread(&buf, 1, 1, in)) {
int new;
// The letter changes the value, the newline (or space) returns it.
diff --git a/lib/lib.h b/lib/lib.h
index 25417105..6d63bb09 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -250,6 +250,7 @@ void replace_tempfile(int fdin, int fdout, char **tempname);
void crc_init(unsigned int *crc_table, int little_endian);
void base64_init(char *p);
int yesno(int def);
+int fyesno(FILE *fp, int def);
int qstrcmp(const void *a, const void *b);
void create_uuid(char *uuid);
char *show_uuid(char *uuid);
diff --git a/toys/posix/xargs.c b/toys/posix/xargs.c
index a8a7e339..f0d2efe0 100644
--- a/toys/posix/xargs.c
+++ b/toys/posix/xargs.c
@@ -8,8 +8,9 @@
* TODO: -I Insert mode
* TODO: -L Max number of lines of input per command
* TODO: -x Exit if can't fit everything in one command
+ * TODO: -P NUM Run up to NUM processes at once
-USE_XARGS(NEWTOY(xargs, "^E:ptrn#<1s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN))
+USE_XARGS(NEWTOY(xargs, "^E:optrn#<1(max-args)s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN))
config XARGS
bool "xargs"
@@ -24,18 +25,11 @@ config XARGS
-0 Each argument is NULL terminated, no whitespace or quote processing
-E Stop at line matching string
-n Max number of arguments per command
+ -o Open tty for COMMAND's stdin (default /dev/null)
-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 compatibility"
- default n
- depends on XARGS
- help
- This version supports insane posix whitespace handling rendered obsolete
- by -0 mode.
*/
#define FOR_xargs
@@ -47,6 +41,7 @@ GLOBALS(
long entries, bytes;
char delim;
+ FILE *tty;
)
// If out==NULL count TT.bytes and TT.entries, stopping at max.
@@ -188,14 +183,16 @@ void xargs_main(void)
for (i = 0; out[i]; ++i) fprintf(stderr, "%s ", out[i]);
if (FLAG(p)) {
fprintf(stderr, "?");
- doit = yesno(0);
+ if (!TT.tty) TT.tty = xfopen("/dev/tty", "re");
+ doit = fyesno(TT.tty, 0);
} else fprintf(stderr, "\n");
}
if (doit) {
if (!(pid = XVFORK())) {
xclose(0);
- open("/dev/null", O_RDONLY);
+ if (open(FLAG(o) ? "/dev/tty" : "/dev/null", O_RDONLY) != 0)
+ perror_exit("child stdin open");
xexec(out);
}
waitpid(pid, &status, 0);
@@ -212,4 +209,5 @@ void xargs_main(void)
}
free(out);
}
+ if (TT.tty) fclose(TT.tty);
}