]> err.no Git - moreutils/commitdiff
Add initial writeup of parallel tool
authorTollef Fog Heen <tfheen@err.no>
Tue, 30 Jun 2009 02:19:07 +0000 (04:19 +0200)
committerTollef Fog Heen <tfheen@err.no>
Tue, 30 Jun 2009 02:19:07 +0000 (04:19 +0200)
parallel.c [new file with mode: 0644]

diff --git a/parallel.c b/parallel.c
new file mode 100644 (file)
index 0000000..09588d6
--- /dev/null
@@ -0,0 +1,144 @@
+
+/*
+ *  parallel.c - run commands in parallel until you run out of commands
+ *
+ *  Copyright © 2008  Tollef Fog Heen <tfheen@err.no>
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ */
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdlib.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+void usage()
+{
+       printf("parallel [OPTIONS] command -- arguments: for each argument,"
+              "run command with argument\n");
+       exit(1);
+}
+
+void exec_child(char **command, char *argument)
+{
+       char **argv;
+       int argc = 0;
+       int i;
+
+       while (command[argc] != 0) {
+               argc++;
+       }
+       argc++;
+       argv = calloc(sizeof(char*), argc+1);
+       for (i = 0; i < argc; i++) {
+               argv[i] = command[i];
+       }
+       argv[i-1] = argument;
+       if (fork() == 0) {
+               /* Child */
+               execvp(argv[0], argv);
+               exit(1);
+       }
+       return;
+}
+
+int main(int argc, char **argv)
+{
+       int maxjobs = -1;
+       int curjobs = 0;
+       int maxload = -1;
+       int opt;
+       char **command = calloc(sizeof(char*), argc);
+       char **arguments;
+       int argidx = 0;
+       int cidx = 0;
+
+       while ((opt = getopt(argc, argv, "+hj:l:")) != -1) {
+               switch (opt) {
+               case 'h':
+                       usage();
+                       break;
+               case 'j':
+                       maxjobs = atoi(optarg);
+                       break;
+               case 'l':
+                       maxload = atoi(optarg);
+                       break;
+               default: /* ’?’ */
+                       usage();
+                       break;
+               }
+       }
+
+       if (maxjobs < 0) {
+               usage();
+       }
+
+       while (optind < argc) {
+               if (strcmp(argv[optind], "--") == 0) {
+                       int i;
+                       size_t mem = (sizeof (char*)) * (argc - optind);
+
+                       arguments = malloc(mem);
+                       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++) {
+                               arguments[i] = strdup(argv[optind + i]);
+                       }
+                       optind += i;
+               } else {
+                       command[cidx] = strdup(argv[optind]);
+                       cidx++;
+               }
+               optind++;
+       }
+
+       while (arguments[argidx] != 0) {
+               if (maxjobs > 0 && curjobs < maxjobs) {
+                       exec_child(command, arguments[argidx]);
+                       argidx++;
+                       curjobs++;
+               }
+
+               if (maxjobs > 0 && curjobs == maxjobs) {
+                       id_t id_ignored;
+                       siginfo_t infop_ignored;
+                       waitid(P_ALL, id_ignored, &infop_ignored, WEXITED);
+                       curjobs--;
+               }
+       }
+       while (curjobs > 0) {
+               id_t id_ignored;
+               siginfo_t infop_ignored;
+               waitid(P_ALL, id_ignored, &infop_ignored, WEXITED);
+               curjobs--;
+       }
+
+       return 0;
+}
+