38e6d7577bd033ae69d0a9cba80ec117a4b01226
[freeside.git] / FS / FS / Daemon.pm
1 package FS::Daemon;
2
3 use vars qw( @ISA @EXPORT_OK );
4 use vars qw( $pid_dir $me $pid_file $sigint $sigterm $NOSIG $logfile );
5 use Exporter;
6 use Fcntl qw(:flock);
7 use POSIX qw(setsid);
8 use IO::File;
9 use Date::Format;
10
11 #this is a simple refactoring of the stuff from freeside-queued, just to
12 #avoid duplicate code.  eventually this should use something from CPAN.
13
14 @ISA = qw(Exporter);
15 @EXPORT_OK = qw(
16   daemonize1 drop_root daemonize2 myexit logfile sigint sigterm
17 );
18 %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK ] );
19
20 $pid_dir = '/var/run';
21
22 $NOSIG = 0;
23
24 sub daemonize1 {
25   $me = shift;
26
27   $pid_file = "$pid_dir/$me";
28   $pid_file .= '.'.shift if scalar(@_);
29   $pid_file .= '.pid';
30
31   chdir "/" or die "Can't chdir to /: $!";
32   open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
33   defined(my $pid = fork) or die "Can't fork: $!";
34   if ( $pid ) {
35     print "$me started with pid $pid\n"; #logging to $log_file\n";
36     exit unless $pid_file;
37     my $pidfh = new IO::File ">$pid_file" or exit;
38     print $pidfh "$pid\n";
39     exit;
40   }
41
42   #sub REAPER { my $pid = wait; $SIG{CHLD} = \&REAPER; $kids--; }
43   #$SIG{CHLD} =  \&REAPER;
44   $sigterm = 0;
45   $sigint = 0;
46   unless ( $NOSIG ) {
47     $SIG{INT}  = sub { warn "SIGINT received; shutting down\n"; $sigint++;  };
48     $SIG{TERM} = sub { warn "SIGTERM received; shutting down\n"; $sigterm++; };
49   }
50 }
51
52 sub drop_root {
53   my $freeside_gid = scalar(getgrnam('freeside'))
54     or die "can't find freeside group\n";
55   $) = $freeside_gid;
56   $( = $freeside_gid;
57   #if freebsd can't setuid(), presumably it can't setgid() either.  grr fleabsd
58   ($(,$)) = ($),$();
59   $) = $freeside_gid;
60   
61   $> = $FS::UID::freeside_uid;
62   $< = $FS::UID::freeside_uid;
63   #freebsd is sofa king broken, won't setuid()
64   ($<,$>) = ($>,$<);
65   $> = $FS::UID::freeside_uid;
66 }
67
68 sub daemonize2 {
69   open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
70   setsid                    or die "Can't start a new session: $!";
71   open STDERR, '>&STDOUT'   or die "Can't dup stdout: $!";
72
73   $SIG{__DIE__} = \&_die;
74   $SIG{__WARN__} = \&_logmsg;
75
76   warn "$me starting\n";
77 }
78
79 sub sigint  { $sigint; }
80 sub sigterm { $sigterm; }
81
82 sub logfile { $logfile = shift; } #_logmsg('test'); }
83
84 sub myexit {
85   unlink $pid_file if -e $pid_file;
86   exit;  
87 }
88
89 sub _die {
90   die @_ if $^S; # $^S = 1 during an eval(), don't break exception handling
91   my $msg = shift;
92   unlink $pid_file if -e $pid_file;
93   _logmsg($msg);
94 }
95
96 sub _logmsg {
97   chomp( my $msg = shift );
98   my $log = new IO::File ">>$logfile";
99   flock($log, LOCK_EX);
100   seek($log, 0, 2);
101   print $log "[". time2str("%a %b %e %T %Y",time). "] [$$] $msg\n";
102   flock($log, LOCK_UN);
103   close $log;
104 }
105
106 1;