#!/usr/bin/perl

# upsmon_launchd_wrapper
#
# upsmon (by default) forks off a child process where it drops privs and
# listens to network sockets.  Mac OS X 10.4's "launchd" isn't terribly
# fond of processes that fork and exit, so we've written this wrapper
# script which acts as a proxy between launchd and upsmon.
#
# Simply execute this script in place of a call to "upsmon", and it will
# make the necessary calls on your behalf.  Additionally, it catches
# TERM (exit) and HUP (reload) signals and passes them along to the daemon.
#
# Copyright 2006 Jason Healy (Suffield Academy)
#

use warnings;
use strict;

# path to upsmon binary
my $UPSMON = '/usr/local/nut_upsmon/sbin/upsmon';

# flag to set on termination
my $TERMINATED = 0;

# Trap for termination signals
sub terminate {
  print STDERR "Received termination signal; exiting\n";

  system($UPSMON, '-c', 'stop') == 0
    or warn "Could not stop upsmon: (perl code $?)\n";

  $TERMINATED = 1;
}

$SIG{TERM} = \&terminate;
$SIG{PIPE} = \&terminate;
$SIG{INT}  = \&terminate;

# Trap for reload signal
sub reload {
  print STDERR "Received hangup signal; reloading\n";

  system($UPSMON, '-c', 'reload') == 0
    or warn "Could not reload upsmon: (perl code $?)\n";
}

$SIG{HUP} = \&reload;


# Launch upsmon and listen to it until it dies
my $pid = fork;

if ($pid != 0) { # parent
  my $kid;
  do {
    # wait on the child...
    $kid = waitpid($pid, 0);

    # ... until the child is dead
  } until ($kid == -1);
}
else {           # child
  # the "-D" flag prevents upsmon from detaching
  exec($UPSMON, '-D') or die "Can't exec $UPSMON: $!";
}

# if the parent process was killed improperly, signal the child to exit
if ($TERMINATED < 1) {
  print STDERR "Parent upsmon killed improperly; trying to clean up...\n";

  system($UPSMON, '-c', 'stop') == 0
    or warn "Could not stop upsmon: (perl code $?)\n";
}

exit 0;
