Package: moreutils
Severity: normal
Tags: patch

Attached a patch to add a -n option to parallel. Note that it has the
side effect to fix a segfault if no '--' is passed to parallel.
>From b1f1f34329a2c8eb4e8034802ba5102f9e3c3b57 Mon Sep 17 00:00:00 2001
From: Pierre Habouzit <madco...@debian.org>
Date: Wed, 22 Jul 2009 11:17:20 +0200
Subject: [PATCH] support -n option

This makes parallel stuff more than one argument to the subcommands.
It's very useful when subcommands are slow to start and are able to
process multiple files at once, that tasks are small but plenty.

For example:
    $ ./parallel -n 3 echo -- a b c d e f g h
    a b c
    d e f
    g h

Signed-off-by: Pierre Habouzit <madco...@debian.org>
---
 parallel.c       |   46 +++++++++++++++++++++++++++++++---------------
 parallel.docbook |    8 ++++++++
 2 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/parallel.c b/parallel.c
index 8045e22..99a9727 100644
--- a/parallel.c
+++ b/parallel.c
@@ -38,7 +38,7 @@ void usage() {
        exit(1);
 }
 
-void exec_child(char **command, char *argument, int replace_cb) {
+void exec_child(char **command, char **arguments, int replace_cb, int nargs) {
        char **argv;
        int argc = 0;
        int i;
@@ -48,14 +48,14 @@ void exec_child(char **command, char *argument, int 
replace_cb) {
        }
        if (replace_cb == 0)
                argc++;
-       argv = calloc(sizeof(char*), argc+1);
+       argv = calloc(sizeof(char*), argc + nargs);
        for (i = 0; i < argc; i++) {
                argv[i] = command[i];
                if (replace_cb && (strcmp(argv[i], "{}") == 0))
-                       argv[i] = argument;
+                       argv[i] = arguments[0];
        }
        if (replace_cb == 0)
-               argv[i-1] = argument;
+               memcpy(argv + i - 1, arguments, nargs * sizeof(char *));
        if (fork() == 0) {
                /* Child */
                execvp(argv[0], argv);
@@ -81,16 +81,18 @@ int main(int argc, char **argv) {
        int maxjobs = -1;
        int curjobs = 0;
        int maxload = -1;
+       int argsatonce = 1;
        int opt;
        char **command = calloc(sizeof(char*), argc);
        char **arguments = NULL;
        int argidx = 0;
+       int arglen = 0;
        int cidx = 0;
        int returncode = 0;
        int replace_cb = 0;
        char *t;
 
-       while ((opt = getopt(argc, argv, "+hij:l:")) != -1) {
+       while ((opt = getopt(argc, argv, "+hij:l:n:")) != -1) {
                switch (opt) {
                case 'h':
                        usage();
@@ -116,12 +118,26 @@ int main(int argc, char **argv) {
                                exit(2);
                        }
                        break;
+               case 'n':
+                       errno = 0;
+                       argsatonce = strtoul(optarg, &t, 0);
+                       if (errno != 0 || argsatonce < 1 || (t-optarg) != 
strlen(optarg)) {
+                               fprintf(stderr, "option '%s' is not a positive 
number\n",
+                                       optarg);
+                               exit(2);
+                       }
+                       break;
                default: /* ’?’ */
                        usage();
                        break;
                }
        }
 
+       if (replace_cb && argsatonce > 1) {
+               fprintf(stderr, "options -i and -n are incomaptible\n");
+               exit(2);
+       }
+
        if (maxjobs < 0) {
 #ifdef _SC_NPROCESSORS_ONLN
                maxjobs = sysconf(_SC_NPROCESSORS_ONLN);
@@ -134,18 +150,15 @@ int main(int argc, char **argv) {
        while (optind < argc) {
                if (strcmp(argv[optind], "--") == 0) {
                        int i;
-                       size_t mem = (sizeof (char*)) * (argc - optind);
 
-                       arguments = malloc(mem);
+                       optind++;
+                       arglen = argc - optind;
+                       arguments = calloc(sizeof(char *), arglen);
                        if (! arguments) {
                                exit(1);
                        }
-                       memset(arguments, 0, mem);
-                       optind++; /* Skip the -- separator, skip after
-                                  * malloc so we have a trailing
-                                  * null */
 
-                       for (i = 0; i < argc - optind; i++) {
+                       for (i = 0; i < arglen; i++) {
                                arguments[i] = strdup(argv[optind + i]);
                        }
                        optind += i;
@@ -157,15 +170,18 @@ int main(int argc, char **argv) {
                optind++;
        }
 
-       while (arguments[argidx] != 0) {
+       while (argidx < arglen) {
                double load;
 
                getloadavg(&load, 1);
 
                if ((maxjobs > 0 && curjobs < maxjobs) ||
                    (maxload > 0 && load < maxload)) {
-                       exec_child(command, arguments[argidx], replace_cb);
-                       argidx++;
+                       if (argsatonce > arglen - argidx)
+                               argsatonce = arglen - argidx;
+                       exec_child(command, arguments + argidx,
+                                  replace_cb, argsatonce);
+                       argidx += argsatonce;
                        curjobs++;
                }
 
diff --git a/parallel.docbook b/parallel.docbook
index 9d5714c..2c5cf14 100644
--- a/parallel.docbook
+++ b/parallel.docbook
@@ -84,6 +84,14 @@ Written by Joey Hess
                        </listitem>
                </varlistentry>
                
+               <varlistentry>
+                       <term><option>-n</option></term>
+                       <listitem>
+                               <para>Number of arguments to pass to one 
command at
+                                  once. Incompatible with -i</para>
+                       </listitem>
+               </varlistentry>
+               
                </variablelist>
                
        </refsect1>
-- 
1.6.3.3.420.gd4b46

Reply via email to