summaryrefslogtreecommitdiffstats
path: root/usr.bin/xargs
diff options
context:
space:
mode:
authortjr <tjr@FreeBSD.org>2002-12-21 10:17:13 +0000
committertjr <tjr@FreeBSD.org>2002-12-21 10:17:13 +0000
commitc6a59dac98550cddc0b5160b22279fcdd5800708 (patch)
tree18dd980318ea84f5f5ade46ea82c4a22f10a84bb /usr.bin/xargs
parent0f6e64a394adb353a0093516585dc001d81a61bb (diff)
downloadFreeBSD-src-c6a59dac98550cddc0b5160b22279fcdd5800708.zip
FreeBSD-src-c6a59dac98550cddc0b5160b22279fcdd5800708.tar.gz
Add the -P option which executes multiple copies of the specified utility
in parallel. Idea from GNU xargs.
Diffstat (limited to 'usr.bin/xargs')
-rw-r--r--usr.bin/xargs/xargs.110
-rw-r--r--usr.bin/xargs/xargs.c66
2 files changed, 57 insertions, 19 deletions
diff --git a/usr.bin/xargs/xargs.1 b/usr.bin/xargs/xargs.1
index 6236c58..e10e56a 100644
--- a/usr.bin/xargs/xargs.1
+++ b/usr.bin/xargs/xargs.1
@@ -57,6 +57,7 @@
.Fl n Ar number
.Op Fl x
.Oc
+.Op Fl P Ar maxjobs
.Op Fl s Ar size
.Op Ar utility Op Ar argument ...
.Sh DESCRIPTION
@@ -191,6 +192,12 @@ arguments remaining for the last invocation of
The current default value for
.Ar number
is 5000.
+.It Fl P Ar maxprocs
+Parallel mode: run at most
+.Ar maxprocs
+invocations of
+.Ar utility
+at once.
.It Fl p
Echo each command to be executed and ask the user whether it should be
executed.
@@ -273,7 +280,8 @@ utility is expected to be
.St -p1003.2
compliant.
The
-.Fl J
+.Fl J ,
+.Fl P
and
.Fl R
options are non-standard
diff --git a/usr.bin/xargs/xargs.c b/usr.bin/xargs/xargs.c
index 5414e65..c692f30 100644
--- a/usr.bin/xargs/xargs.c
+++ b/usr.bin/xargs/xargs.c
@@ -76,6 +76,7 @@ static int prompt(void);
static void run(char **);
static void usage(void);
void strnsubst(char **, const char *, const char *, size_t);
+static void waitchildren(const char *, int);
static char echo[] = _PATH_ECHO;
static char **av, **bxp, **ep, **exp, **xp;
@@ -83,6 +84,9 @@ static char *argp, *bbp, *ebp, *inpline, *p, *replstr;
static const char *eofstr;
static int count, insingle, indouble, pflag, tflag, Rflag, rval, zflag;
static int cnt, Iflag, jfound, Lflag, wasquoted, xflag;
+static int curprocs, maxprocs;
+
+static volatile int childerr;
extern char **environ;
@@ -121,7 +125,8 @@ main(int argc, char *argv[])
/* 1 byte for each '\0' */
nline -= strlen(*ep++) + 1 + sizeof(*ep);
}
- while ((ch = getopt(argc, argv, "0E:I:J:L:n:pR:s:tx")) != -1)
+ maxprocs = 1;
+ while ((ch = getopt(argc, argv, "0E:I:J:L:n:P:pR:s:tx")) != -1)
switch(ch) {
case 'E':
eofstr = optarg;
@@ -145,6 +150,10 @@ main(int argc, char *argv[])
if ((nargs = atoi(optarg)) <= 0)
errx(1, "illegal argument count");
break;
+ case 'P':
+ if ((maxprocs = atoi(optarg)) <= 0)
+ errx(1, "max. processes must be >0");
+ break;
case 'p':
pflag = 1;
break;
@@ -249,8 +258,10 @@ parse_input(int argc, char *argv[])
switch(ch = getchar()) {
case EOF:
/* No arguments since last exec. */
- if (p == bbp)
+ if (p == bbp) {
+ waitchildren(*argv, 1);
exit(rval);
+ }
goto arg1;
case ' ':
case '\t':
@@ -327,8 +338,10 @@ arg2:
*xp++ = *avj;
}
prerun(argc, av);
- if (ch == EOF || foundeof)
+ if (ch == EOF || foundeof) {
+ waitchildren(*argv, 1);
exit(rval);
+ }
p = bbp;
xp = bxp;
count = 0;
@@ -467,10 +480,8 @@ prerun(int argc, char *argv[])
static void
run(char **argv)
{
- volatile int childerr;
- char **avec;
pid_t pid;
- int status;
+ char **avec;
/*
* If the user wants to be notified of each command before it is
@@ -512,17 +523,35 @@ exec:
childerr = errno;
_exit(1);
}
- pid = waitpid(pid, &status, 0);
- if (pid == -1)
- err(1, "waitpid");
- /* If we couldn't invoke the utility, exit. */
- if (childerr != 0)
- err(childerr == ENOENT ? 127 : 126, "%s", *argv);
- /* If utility signaled or exited with a value of 255, exit 1-125. */
- if (WIFSIGNALED(status) || WEXITSTATUS(status) == 255)
- exit(1);
- if (WEXITSTATUS(status))
- rval = 1;
+ curprocs++;
+ waitchildren(*argv, 0);
+}
+
+static void
+waitchildren(const char *name, int waitall)
+{
+ pid_t pid;
+ int status;
+
+ while ((pid = wait3(&status, !waitall && curprocs < maxprocs ?
+ WNOHANG : 0, NULL)) > 0) {
+ curprocs--;
+ /* If we couldn't invoke the utility, exit. */
+ if (childerr != 0) {
+ errno = childerr;
+ err(errno == ENOENT ? 127 : 126, "%s", name);
+ }
+ /*
+ * If utility signaled or exited with a value of 255,
+ * exit 1-125.
+ */
+ if (WIFSIGNALED(status) || WEXITSTATUS(status) == 255)
+ exit(1);
+ if (WEXITSTATUS(status))
+ rval = 1;
+ }
+ if (pid == -1 && errno != ECHILD)
+ err(1, "wait3");
}
/*
@@ -564,6 +593,7 @@ usage(void)
{
fprintf(stderr,
"usage: xargs [-0pt] [-E eofstr] [-I replstr [-R replacements]] [-J replstr]\n"
-" [-L number] [-n number [-x] [-s size] [utility [argument ...]]\n");
+" [-L number] [-n number [-x] [-P maxprocs] [-s size]\n"
+" [utility [argument ...]]\n");
exit(1);
}
OpenPOWER on IntegriCloud