#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <process.h>
#include <malloc.h>

#ifdef __EMX__
#define itoa _itoa
#endif

int main (int argc, const char * const *argv)
{
    int ph[2];
    int n, size;
    void *p;
    char buf[80];
    char arg0[34];
    char arg1[34];
    int pid = getpid();

    if (argc > 1 && strcmp(argv[1], "pipe") == 0) {
	ph[0] = atoi(argv[2]);
	ph[1] = atoi(argv[3]);
    } else {
	if (pipe (ph) != 0) {
	    perror ("pipe");
	    return (2);
	}
    }

    printf("pid %d uses pipe handles in=%d out=%d\n", pid, ph[0], ph[1]);

    p = malloc(8192);
    if (p == NULL) {
	puts("error malloc");
	exit(1);
    }

    for (;;) {
	printf("[pid %d]:", pid);
	gets(buf);

	switch (*buf) {
	    case 'w':
		size = atoi(buf+1);
		if (!size || size>8192)
		    break;
		if ((n = write(ph[1], p, size)) < 0)
		    perror("write");
		else
		    printf("pid %d write %d bytes\n", pid, n);
		break;

	    case 'r':
		size = atoi(buf+1);
		if (!size || size>8192)
		    break;
		if ((n = read(ph[0], p, size)) < 0)
		    perror("read");
		else
		    printf("pid %d read %d bytes\n", pid, n);
		break;

	    case 'c':
		n = atoi(buf+1);
		if (n<0 || n>1)
		    break;
		close(ph[n]);
		break;

	    case 's':
		itoa(ph[0], arg0, 10);
		itoa(ph[1], arg1, 10);
		spawnl(P_NOWAIT, argv[0], argv[0], "pipe", arg0, arg1, NULL);
		break;

	    case 'h':
	    case '?':
		puts("w# - write # bytes to pipe");
		puts("r# - read # bytes to pipe");
		puts("c# - close pipe #");
		puts("s  - spawn next program");
		puts("q  - quit");
		break;

	    case 'q':
		exit(0);
	}
    }
    return (0);
}
