#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFLEN 512



int main( int argc, char ** argv )
{
	int iWait;
	int iRead;
	char buf [BUFLEN];


	int childToParent[2],parentToChild[2];
	if (pipe(childToParent) == -1)	{
		perror("pipe failed");
		//exit(1);
		return 1;
	}
	if (pipe(parentToChild) == -1)	{
		perror("pipe failed");
		//exit(1);
		return 1;
	}
	// The kernel does not distinguish between the two pipes.

	pid_t iWhich = fork ();
	if (iWhich < 0)	{
		perror("fork failed");
		//exit(2);
		return 1;
	}
	else if (iWhich == 0) { /*child process*/
printf ("Childish <%d>\n", iWhich);
		// The child inherits all open file descriptors, including the pipes.
		int toParent = childToParent[1];
		// The writable end of one pipe.
		int fromParent = parentToChild[0];
		// The readable end of the other.
printf ("Child::childToParent <%d><%d><%d>\n", iWhich, childToParent[0], childToParent[1]);
printf ("Child::parentToChild <%d><%d><%d>\n", iWhich, parentToChild[0], parentToChild[1]);
		close(childToParent[0]);
		close(parentToChild[1]);
		// Close the end of each pipe the child is not going to use.
		// This permits the kernel to correctly transmit end of file.
//		write(toParent,whatever,length_of_whatever);
//		read(fromParent,whatever,length_of_whatever);

		// The child or parent can also do an exec to run a separate program. The
		// open pipe file descriptors remain open through an exec, so if, for
		// example, toParent equals 17 after the fork, you can exec another program
		// and still write to file descriptor 17 and it will be sent to the parent.
		// In such cases, the usual practice is to rename the descriptors to
		// well-known descriptors such as 0 (for input) and 1 (for output) using dup,
		// dup2, etc. For example, if the child process is to execute "xyz" and
		// doesn't need the parent's stdin or stdout,
//		int fromParentDup = dup2(fromParent,0); /* turn the pipe from-parent into stdin. */
		int toParentDup = dup2(toParent,1);   /* turn the pipe to-parent into stdout. */
		// the child process can then read and write its stdin and stdout and never know it is
		// actually communicating through a pipe to another process.
printf ("Child still here ... <%d>\n", iWhich);
		execlp("more","more","main.cpp",NULL);
		flush();
//		system ("more main.cpp");
		exit (0);
	}
	else	{	/* parent process */
//		sleep (5);
printf ("Parental watch ... <%d>\n", iWhich);
		// Sort of the mirror image of what we did with the child.
		int fromChild = childToParent[0];
		// The readable end of one pipe.
		int toChild = parentToChild[1];
		// The writeable end of the other.
printf ("Parent::childToParent <%d><%d><%d>\n", iWhich, childToParent[0], childToParent[1]);
printf ("Parent::parentToChild <%d><%d><%d>\n", iWhich, parentToChild[0], parentToChild[1]);
		close(childToParent[1]);
		close(parentToChild[0]);
		// Close the end of each pipe the parent is not going to use.
		// This permits the kernel to correctly transmit end of file.
printf ("Parental watch ... <%d>\n", iWhich);
		pid_t thePid = 0;
		while (read(fromChild,buf, BUFLEN))	{
//		while (thePid != iWhich)	{
			sleep (1);
			read(fromChild,buf, BUFLEN);
printf ("iWait !!!<%d> iWhich<%d>\n", iWait, iWhich);
			thePid = waitpid(iWhich, &iWait, WNOHANG);
			printf ("Parent:<%d> <%s>\n", (int)thePid, (char *)buf);

		}
//		write(toChild,whatever,length_of_whatever);
		// wait for child process to finish ..
		wait (&iWait);
printf ("Parental EXIT !!!<%d><%d><%d>\n", iWait, thePid, iWhich);
	}
	return 0;
}


