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