#!/bin/perl
# File: pcloop

# Create a pipe between a parent and child.  The parent will loop, repeatedly 
# prompting the user for a command to run, sending the command through the pipe # to the child, who will run the command with a fork and exec.  Verify that a 
# second command can be executed by the child before a first one is complete.


# Save stdin and stdout for later restoration. Create pipe.
open(SI, "<&STDIN");
open(SO, ">&STDOUT");
pipe(STDIN, STDOUT);      # STDIN/STDOUT are read/write

if (fork != 0) {  # Parent
   # Close the read side of the pipe, and restore original stdin.
   close(STDIN);            # Close read side of pipe (we *must*)
   open(STDIN, "<&SI");     # Put stdin back (to keyboard probably)

   # Dup stdout then put original stdout back.
   open(PW, ">&STDOUT");    # Dup stdout (write side) into new filehandle PW
   open(STDOUT, ">&SO");    # Put stdout back (to screen probably)
   select PW; $| = 1;       # Unbuffer pipe writes
   select STDOUT;

   # Get commands to send to child for execution.
   print "Command: ";
   while ($cmd = <STDIN>) {
      last if $cmd eq "q\n";
      print PW $cmd;
      print "Command: ";
   }
   close(PW);  # Close write side to send EOF to child.
   exit(0);  # Exit parent.
}
else {  # Child
   # Close write side of pipe.
   close(STDOUT);             # Child close write side of pipe.
   open(STDOUT, ">&SO");      # Put stdout back (to screen probably).
   select STDOUT; $| = 1;     # Unbuffer stdout.
   while ($cmd = <STDIN>) {   # Read pipe.
      chomp $cmd;
      if (fork == 0) {   # Child of child.
	 exec($cmd) || warn "Cannot exec $cmd: $!\n";
      }
   }
   close(STDIN);
   exit(0);
}
