#!/usr/bin/perl
# File: multi
# Reads from STDIN, writes to STDOUT
# Creates named pipe, name based on PID
# When receives a signal (HUP) (aka kill -1), reads command from named pipe
# Creates pipe and forks, child then resets pipe to STDIN and execs command
# Subsequent input from STDIN then goes to STDOUT and all pipes

$| = 1;    # Command buffer STDOUT
print $$;  # Print out pid for reference

# Set up signal handlers
$SIG{'HUP'} = 'create_pipe';  # Run create_pipe sub when SIGHUP caught.
$SIG{'TERM'} = sub { print STDOUT "OUCH!\n"; return; }; # Ignore SIGTERM

# create named pipe with mknod(1) utility
$npipe = "mknod multi".$$." p";
system($npipe);

# Open filehandle on named pipe
open(FH,"multi$$") or die "could not open named pipe for read\n";

$outpipe = 'aaa';   # Initialize some string for future filehandle names

# Define subroutine to make pipe and create child
sub create_pipe {
  my $command = <FH>;                     # Read command from named pipe
  pipe(PI,++$outpipe);                    #create new filehandle and pipe
  select $outpipe; $| = 1; select STDIN;  #command buffer data TO pipe

  #fork child
  unless ($child_pid{$outpipe} = fork) {
    # Do child stuff : reset pipe to STDIN
    open(STDIN, "<&PI") or die "child $$ failed stdin reset";
    close $outpipe;

    exec($command);   # exec command received from named pipe
    exit;
  }
  close $PI;   #close read side in parent
  system(ps);   #print out ps(1) output (just for fun)
} # end sub create_pipe
  
# main loop of program

while($data_in = <STDIN>) {
  print STDOUT "STDOUT: $data_in";
  for $key (keys(%child_pid)) { #loop through all the existing pipes
    print $key  $data_in;
  }
}
system("rm multi$$");   # Remove named pipe

