Two way pipes can be created by opening up two pipes, and properly
reassigning the file descriptors in the child process.
The pipe() call must be made BEFORE a call to fork(), or the descriptors
will not be inherited by the child! (same for popen()).
With half-duplex pipes, any connected processes must share a related
ancestry. Since the pipe resides within the confines of the kernel, any
process that is not in the ancestry for the creator of the pipe has no
way of addressing it. This is not the case with named pipes (FIFOS).