Hi,

This is adds -P to xargs, taken from freebsd. Example usage:
 find . -type f -name \*.iso -print0 | xargs -0n1 -P4 bzip2 

- Axel Scheepers


diff --git a/usr.bin/xargs/xargs.1 b/usr.bin/xargs/xargs.1
index 045e235..4d76b98 100644
--- a/usr.bin/xargs/xargs.1
+++ b/usr.bin/xargs/xargs.1
@@ -58,6 +58,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
@@ -192,6 +193,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 o
 Reopen stdin as
 .Pa /dev/tty
@@ -285,7 +292,7 @@ utility is expected to be
 .St -p1003.2
 compliant.
 The
-.Fl J , o
+.Fl J , o , P
 and
 .Fl R
 options are non-standard
diff --git a/usr.bin/xargs/xargs.c b/usr.bin/xargs/xargs.c
index f48b975..cc0a59c 100644
--- a/usr.bin/xargs/xargs.c
+++ b/usr.bin/xargs/xargs.c
@@ -66,6 +66,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, **expx, **xp;
@@ -73,6 +74,8 @@ static char *argp, *bbp, *ebp, *inpline, *p, *replstr;
 static const char *eofstr;
 static int count, insingle, indouble, oflag, pflag, tflag, Rflag, rval, zflag;
 static int cnt, Iflag, jfound, Lflag, wasquoted, xflag;
+static int curprocs, maxprocs;
+static volatile int childerr;
 
 extern char **environ;
 
@@ -112,7 +115,9 @@ 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:opR:s:tx")) != -1)
+
+       maxprocs = 1;
+       while ((ch = getopt(argc, argv, "0E:I:J:L:n:P:opR:s:tx")) != -1)
                switch(ch) {
                case 'E':
                        eofstr = optarg;
@@ -144,6 +149,10 @@ main(int argc, char *argv[])
                case 'p':
                        pflag = 1;
                        break;
+               case 'P':
+                       if ((maxprocs = atoi(optarg)) <= 0)
+                               errx(1, "max.processes must be >0");
+                       break;
                case 'R':
                        if ((Rflag = atoi(optarg)) <= 0)
                                errx(1, "illegal number of replacements");
@@ -245,8 +254,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':
@@ -323,8 +334,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;
@@ -463,10 +476,8 @@ prerun(int argc, char *argv[])
 static void
 run(char **argv)
 {
-       volatile int childerr;
        char **avec;
        pid_t pid;
-       int status;
 
        /*
         * If the user wants to be notified of each command before it is
@@ -516,17 +527,40 @@ 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);
+}
+
+/*
+ * Handle child processes.
+ */
+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");
 }
 
 /*
@@ -567,6 +601,7 @@ usage(void)
 {
        fprintf(stderr,
 "usage: xargs [-0opt] [-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);
 }

Reply via email to