#include "refer.h" #include /* * call rprog, with argument arg, as a coroutine: * send it the string in; * read the result string out (max. outlen bytes, including \0) */ void corout(char *in, char *out, char *rprog, char *arg, int outlen) { # define move(x, y) if (x != y) { dup2(x, y); close(x); } int pipev[2], fr1, fr2, fw1, fw2, n, pid; SIG_TYP sigf; Builtin *bp; for (bp = builtins; bp->cmd != 0; bp++) if (strcmp(bp->cmd, rprog) == 0) { (*bp->fn)(in, out, arg, outlen); return; } if (pipe(pipev) < 0) err("can't create pipe to %s", rprog); fr1 = pipev[0]; fw1 = pipev[1]; if (pipe(pipev) < 0) err("can't create pipe from %s", rprog); fr2 = pipev[0]; fw2 = pipev[1]; if ((pid = fork()) == 0) { close(fw1); close(fr2); move(fr1, 0); move(fw2, 1); if (rprog[0] != '/') if (chdir(referlib) < 0) err("can't chdir to %s", referlib); execl(rprog, rprog, arg, 0); err("can't run %s", rprog); } if (pid == -1) err("can't fork to run %s", rprog); close(fw2); close(fr1); sigf = signal(SIGPIPE, SIG_IGN); (void) write(fw1, in , strlen(in)); /* check return? */ close(fw1); signal(SIGPIPE, sigf); while ((n = wait((int *)0)) != -1 && n != pid) ; if (outlen) { n = fullread(fr2, out, outlen-1); /* allow for \0 */ out[n] = 0; } close(fr2); } /* * data arriving on a pipe need not arrive all at once: * collect up to nb bytes */ int fullread(int fd, char *buf, int nb) { int nr = 0; while (nb > 0) { int r; r = read(fd, buf, nb); if (r <= 0) return nr? nr: r; buf += r; nb -= r; nr += r; } return nr; }