From c6a59dac98550cddc0b5160b22279fcdd5800708 Mon Sep 17 00:00:00 2001 From: tjr Date: Sat, 21 Dec 2002 10:17:13 +0000 Subject: Add the -P option which executes multiple copies of the specified utility in parallel. Idea from GNU xargs. --- usr.bin/xargs/xargs.1 | 10 +++++++- usr.bin/xargs/xargs.c | 66 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 57 insertions(+), 19 deletions(-) (limited to 'usr.bin') 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); } -- cgit v1.1