#!/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;