#!/usr/bin/perl

# logFifo
# This script illustrates how to have a fifo that processes textual input.
# Run this script and then write (e.g. with 'echo') to the fifo.
# Each message sent will be output to STDOUT tagged with the current time.
#
# Cameron Hayne (macdev@hayne.net)  Nov 2006

use warnings;
use strict;
use POSIX qw(mkfifo);
use Time::HiRes qw(time);

my $scriptname = "logFifo";
die "Usage: $scriptname: name_of_fifo\n" unless scalar(@ARGV) == 1;
my $fifoName = $ARGV[0];

sub fatalError($)
{
    my ($msg) = @_;

    print STDERR "$scriptname: $msg\n";
    finish();
}

sub createFifo()
{
    mkfifo($fifoName, 0666) or fatalError("name: can't mkfifo $fifoName: $!");
}

sub removeFifo()
{
    unlink($fifoName);
}

sub finish()
{
    removeFifo();
    exit;
}

sub openFifo()
{
    open(FIFO, "< $fifoName") or fatalError("can't read $fifoName: $!");
    #print "Somebody is writing to the fifo $fifoName\n";
}

sub readFromFifo()
{
    while (<FIFO>)
    {
        chomp();
        my $time = time();
        print "$time: $_\n";
    }
}

sub closeFifo()
{
    #print "Closing fifo\n";
    close(FIFO);
}

MAIN:
{
    # catch control-C and "kill" and clean up
    $SIG{INT} = $SIG{TERM} = sub { $SIG{INT} = $SIG{TERM} = 'DEFAULT';
                                   finish() };

    # install an alarm handler that closes the fifo (to avoid denial of service)
    $SIG{ALRM} = sub { closeFifo() };

    createFifo();

    while (1)
    {
        alarm(0);
        # next line blocks until there's a writer
        openFifo();
        alarm(3);  # allow 3 seconds for the writer to finish
        readFromFifo();
        closeFifo();
    }
}

