From: Tollef Fog Heen Date: Tue, 30 Jun 2009 02:19:07 +0000 (+0200) Subject: Add initial writeup of parallel tool X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0f012c74fcfaea8d661a729fd5cc2ad4f3563115;p=moreutils Add initial writeup of parallel tool --- diff --git a/parallel.c b/parallel.c new file mode 100644 index 0000000..09588d6 --- /dev/null +++ b/parallel.c @@ -0,0 +1,144 @@ + +/* + * parallel.c - run commands in parallel until you run out of commands + * + * Copyright © 2008 Tollef Fog Heen + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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; +} +