V10/cmd/dblbuf.c

Compare this file to the similar file:
Show the results in this format:

#include <stdio.h>
#include <signal.h>

#define Read 1
#define Write 2
#define Endfile 3
#define Error 4

int inpipe, outpipe;
int infd = 0, outfd = 1;
int bufmax = 32768;
char *buffer;
int reclen;
extern char *optarg;
extern int optind;
extern char *malloc();

int
gettoken()
{
	char c;

	switch (read (inpipe, &c, 1)) {
	case 0:	return Endfile;
	case 1:	return c;
	default:
		perror ("gettoken");
		return Error;
	}
}

void
puttoken(t)
	char t;
{
	write (outpipe, &t, 1);
}

int
readbuf()
{
	reclen = read (infd, buffer, bufmax);

	if (reclen < 0) {
		perror ("read");
		return 0;
	}

	return reclen > 0;
}

int
writebuf()
{
	if (write (outfd, buffer, reclen) != reclen) {
		perror ("write");
		return 0;
	}
	return 1;
}

int
copyloop()
{
	for (;;) {
		int t;
		if ((t = gettoken()) != Read)
			return t;
		if (!readbuf()) {
			puttoken (Endfile);
			return Endfile;
		}
		puttoken (Read);
		if ((t = gettoken()) != Write)
			return t;
		if (!writebuf()) {
			puttoken (Error);
			return Error;
		}
		puttoken (Write);
	}
}

int
copyfile()
{
	int p0[2], p1[2];
	int p, pid, status;
	pipe (p0);
	pipe (p1);
	switch (pid = fork()) {
	default:			/* parent */
		inpipe = p0[0];
		close (p0[1]);
		outpipe = p1[1];
		close (p1[0]);

		status = copyloop();
		if (status != Endfile) {
			fprintf (stderr, "error: parent status %d\n", status);
			return 1;
		}

		do	p = wait (&status);
		while (p >= 0 && p != pid);
		if (p < 0) {
			perror ("wait");
			return 1;
		}

		if (status != Endfile<<8) {
			fprintf (stderr, "error: child status %d\n", status);
			return 1;
		}
		
		return 0;

	case 0:				/* child */
		inpipe = p1[0];
		close (p1[1]);
		outpipe = p0[1];
		close (p0[0]);
		puttoken (Read);
		puttoken (Write);
		exit (copyloop());

	case -1:			/* error */
		perror ("fork");
		return 1;
	}
}

main (argc, argv)
	int argc;
	char **argv;
{
	int c;
	while ((c = getopt (argc, argv, "b:")) != -1) {
		switch (c) {
		case 'b':
			bufmax = atoi (optarg);
			if (bufmax <= 0) {
				fprintf (stderr, "invalid buffer size\n");
				exit (1);
			}
		}
	}

	if ((buffer = malloc (bufmax)) == NULL) {
		fprintf (stderr, "out of memory\n");
		exit (1);
	}

	if (argc > optind + 1) {
		fprintf (stderr, "only one input file\n");
		exit (1);
	}

	if (argc > optind) {
		infd = open (argv[optind], 0);
		if (infd < 0) {
			perror (argv[optind]);
			exit (1);
		}
	}

	signal (SIGPIPE, SIG_IGN);
	return copyfile();
}