Plan 9 from Bell Labs’s /usr/web/sources/contrib/steve/root/sys/src/cmd/refer/corout.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#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;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.