#!/usr/bin/perl
# 2007 Rune M. Barnkob
# -------------------------------------
# 2007-06-16  First release
# -------------------------------------
# We can always use another OSS license, so here goes: use this for whatever you want - 
# weapons, nuclear powerplants, chemical waste disposal plants - just dont come crying
# to me if it fails in any way. (but you are free to report bugs)
# Use whatever license you choose appropriate from 
# http://www.opensource.org/licenses/alphabetical

use strict;
use POSIX qw(setsid);

if (@ARGV < 3) {
  die "Usage: watch-file.pl <file-to-watch> <log-file> <command...>\n";
}


my $file = shift(@ARGV);
my $log = shift(@ARGV);
my $LOG;

# gracefully chopped from http://www.webreference.com/perl/tutorial/9/3.html
sub daemonize {
  open STDIN, '/dev/null'   or die "Can't read /dev/null: $!";
  open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!";
  open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!";
  defined(my $pid = fork)   or die "Can't fork: $!";
  exit if $pid;
  setsid                    or die "Can't start a new session: $!";
  umask 0;
  logmsg("Daemonized...");
}

# print new log message
sub logmsg {
  my ($msg) = @_;
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  $year += 1900; $mon += 1;
  if (not defined($LOG)) {
    open($LOG, ">>$log");
    printf($LOG "%04d-%02d-%02d %02d:%02d:%02d (%04d) %s\n",
                $year, $mon, $mday,
                $hour, $min, $sec,
                $$, "New log");
    $| = 1;
  }
  if (defined($msg)) {
    printf($LOG "%04d-%02d-%02d %02d:%02d:%02d (%04d) %s\n",
                $year, $mon, $mday,
                $hour, $min, $sec,
                $$, $msg);
  }
}

# handle SIGHUP by closing log and opening again - useful for log rotation
sub hndl_sighup {
  logmsg("Closing log on SIGHUP...");
  close($LOG); undef($LOG);
  logmsg();
}
$SIG{HUP} = \&hndl_sighup;

# handle SIGTERM gracefully
sub hndl_sigterm {
  logmsg("Exiting...");
  exit;
}
$SIG{TERM} = \&hndl_sigterm;


# ###########################################################
#
# we must daemonize first in order to open log file correctly
daemonize();
$| = 1;

my $last_mtime;
while (1) {
  my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($file);
  if ($mtime != $last_mtime) {
    $last_mtime = $mtime;
    logmsg("Exec '@ARGV'");
    open STDOUT, ">>$log-STDOUT";
    open STDERR, ">>$log-STDERR";
    system(@ARGV);
  }
  sleep(1);
}
