implement FDrun; include "sys.m"; sys: Sys; include "draw.m"; include "sh.m"; sh: Sh; include "fdrun.m"; init() { sys = load Sys Sys->PATH; sh = load Sh Sh->PATH; } # run command args; spec specifies how to arrange the file descriptors # for the command; spec[i] specifies how to arrange fd i; a decimal digit n, # means use sfds[n]; 'x' means use /dev/null; '-' means leave untouched. # status of command is sent down result. run(ctxt: ref Draw->Context, args: list of string, spec: string, sfds: array of ref Sys->FD, result: chan of string): int { fds := array[len spec] of ref Sys->FD; for(i := 0; i < len spec; i++){ case spec[i] { 'x' => fds[i] = sys->open("/dev/null", Sys->ORDWR); '-' => ; '0' to '9' => p := spec[i] - '0'; if(p >= len sfds){ sys->werrstr("fd array too short"); return -1; } fds[i] = sfds[p]; * => sys->werrstr("invalid character in spec"); return -1; } } sfds = nil; spawn runpipe(ctxt, args, fds, sync := chan of int, result); <-sync; return 0; } runpipe(ctxt: ref Draw->Context, args: list of string, fds: array of ref Sys->FD, sync: chan of int, result: chan of string) { sys->pctl(Sys->FORKFD, nil); fl: list of int; for(i := 0; i < len fds; i++){ if(fds[i] != nil && fds[i].fd != i) sys->dup(fds[i].fd, i); fl = i :: fl; } fds = nil; sys->pctl(Sys->NEWFD, fl); sync <-= 0; result <-= sh->run(ctxt, args); }