Implementing subprocess * Introducing

pipe: * The pipe system call takes an uninitialized array of two integers (let’s call this array fds) and populates it with two file descriptors such that everything written to fds[1] can be read from fds[0].

~~~{.c}
int pipe(int fds[]); // fds array should be of length 2, return -1 on error, 0 otherwise
~~~

* <tt><b>pipe</b></tt> is particularly useful for allowing parent processes to
  communicate with forked child processes.  (Recall that <tt><b>fork</b></tt> 
  clones the caller’s virtual address space <b>and</b> duplicates all open file descriptors as well).
* Using <tt><b>pipe</b></tt>, <tt><b>fork</b></tt>, <tt><b>dup2</b></tt>,
  <tt><b>execvp</b></tt>, <tt><b>close</b></tt>, and <tt><b>waitpid</b></tt>,
  we can implement the <tt><b>subprocess</b></tt> function, which relies on the 
  following record definition and is implemented to the following prototype:
  
~~~{.c}
typedef struct {
  pid_t pid;
  int infd;
} subprocess_t;
subprocess_t subprocess(const char *command);
~~~

* The subprocess created by <tt><b>subprocess</tt></b> executes
  the provided command (guaranteed to be a <tt><b>'&#92;0'</b></tt>-terminated C string) by calling
  <tt><b>"/bin/sh -c command"</b></tt>.  Rather than waiting for <tt><b>command</b></tt> to finish,
  the implementation returns a <tt><b>subprocess_t</b></tt> with the <b><tt>command</tt></b>
  process’s pid and a single file descriptor.  In particular, arbitrary data can
  be published to the return value’s <tt><b>infd</b></tt> with the understanding
  that it’ll be read by <b><tt>command</tt></b>'s standard input.

Implementing subprocess (continued)

Implementing subprocess (continued)