#include "refer.h"
#include <signal.h>
/*
* 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;
}
|