ref: ecba7822e316d6cb8370eec97862215402811e82
dir: /sys/src/cmd/xargs.c/
#include <u.h> #include <libc.h> #include <bio.h> void usage(void) { fprint(2, "usage: xargs [ -n lines ] [ -p procs ] args ...\n"); exits("usage"); } void dowait(void) { while(waitpid() != -1) ; } void main(int argc, char **argv) { int lines, procs, i, j, run; char **nargv, **args, **p; static Biobuf bp; lines = 10; procs = 1; ARGBEGIN { case 'n': lines = atoi(EARGF(usage())); break; case 'p': procs = atoi(EARGF(usage())); break; default: usage(); } ARGEND; if(argc < 1) usage(); nargv = malloc(sizeof(char *) * (argc + lines + 1)); if(nargv == nil) sysfatal("malloc: %r"); memcpy(nargv, argv, sizeof(char *) * argc); args = nargv + argc; if(Binit(&bp, 0, OREAD) < 0) sysfatal("Binit: %r"); Blethal(&bp, nil); atexit(dowait); for(j = 0, run = 1; run; j++){ if(j >= procs) waitpid(); memset(args, 0, sizeof(char *) * (lines + 1)); for(i = 0; i < lines; i++) if((args[i] = Brdstr(&bp, '\n', 1)) == nil){ if(i == 0) exits(nil); run = 0; break; } switch(fork()){ case -1: sysfatal("fork: %r"); case 0: exec(*nargv, nargv); if(**nargv != '/' && strncmp(*nargv, "./", 2) != 0 && strncmp(*nargv, "../", 3) != 0){ *nargv = smprint("/bin/%s", *nargv); exec(*nargv, nargv); } sysfatal("exec: %r"); } for(p = args; *p; p++) free(*p); } exits(nil); }