add stack backtrace to fatal problems in virtual field check
[freeside.git] / FS / bin / freeside-sqlradius-radacctd
1 #!/usr/bin/perl -Tw
2
3 use strict;
4 use vars qw( $log_file $sigterm $sigint );
5 use subs qw( _die _logmsg );
6 use Fcntl qw(:flock);
7 use POSIX qw(setsid);
8 use Date::Format;
9 use IO::File;
10 use FS::UID qw(adminsuidsetup);
11 #use FS::Record qw(qsearch qsearchs);
12 #use FS::part_export;
13 #use FS::svc_acct;
14 #use FS::cust_svc;
15
16 #lots of false laziness w/freeside-queued
17
18 my $user = shift or die &usage;
19
20 #my $pid_file = "/var/run/freeside-sqlradius-radacctd.$user.pid";
21 my $pid_file = "/var/run/freeside-sqlradius-radacctd.pid";
22
23 &daemonize1;
24
25 #sub REAPER { my $pid = wait; $SIG{CHLD} = \&REAPER; $kids--; }
26 #$SIG{CHLD} =  \&REAPER;
27
28 $sigterm = 0;
29 $sigint = 0;
30 $SIG{INT} = sub { warn "SIGINT received; shutting down\n"; $sigint++; };
31 $SIG{TERM} = sub { warn "SIGTERM received; shutting down\n"; $sigterm++; };
32
33 my $freeside_gid = scalar(getgrnam('freeside'))
34   or die "can't setgid to freeside group\n";
35 $) = $freeside_gid;
36 $( = $freeside_gid;
37 #if freebsd can't setuid(), presumably it can't setgid() either.  grr fleabsd
38 ($(,$)) = ($),$();
39 $) = $freeside_gid;
40
41 $> = $FS::UID::freeside_uid;
42 $< = $FS::UID::freeside_uid;
43 #freebsd is sofa king broken, won't setuid()
44 ($<,$>) = ($>,$<);
45 $> = $FS::UID::freeside_uid;
46
47 #$ENV{HOME} = (getpwuid($>))[7]; #for ssh
48 adminsuidsetup $user;
49
50 $log_file= "/usr/local/etc/freeside/sqlradius-radacctd-log.". $FS::UID::datasrc;
51
52 &daemonize2;
53
54 $SIG{__DIE__} = \&_die;
55 $SIG{__WARN__} = \&_logmsg;
56
57 warn "freeside-sqlradius-radacctd starting\n";
58
59 #eslaf
60
61 #my $machine = shift or die &usage; #would need to be up higher for real
62 my @exports = qsearch('part_export', { 'exporttype' => 'sqlradius' } );
63
64 while (1) {
65
66   my %seen = ();
67   foreach my $export ( @exports ) {
68     next if $seen{$export->option('datasrc')}++;
69     my $dbh = DBI->connect(
70       map { $export->option($_) } qw( datasrc username password )
71     ) or do {
72       warn "can't connect to ". $export->option('datasrc'). ": ". $DBI::errstr;
73       next;
74     }
75
76     # find old radacct position
77     #$lastid = 0;
78
79     # get new radacct records
80     my $sth = $dbh->prepare('SELECT * FROM radacct WHERE radacctid > ?') or do {
81       warn "can't select in radacct table from ". $export->option('datasrc').
82            ": ". $dbh->errstr;
83       next;
84     };
85
86     while ( my $radacct = $sth->fetchrow_arrayref({}) ) {
87
88       my $session = new FS::session {
89         portnum =>
90         svcnum  => 
91         login   =>
92         #logout  =>
93       };
94
95     }
96
97     # look for updated radacct records & replace them
98
99   }
100
101   sleep 5;
102
103 }
104
105 #more false laziness w/freeside-queued
106
107 sub usage {
108   die "Usage:\n\n  freeside-sqlradius-radacctd user\n";
109 }
110
111 sub _die {
112   my $msg = shift;
113   unlink $pid_file if -e $pid_file;
114   _logmsg($msg);
115 }
116
117 sub _logmsg {
118   chomp( my $msg = shift );
119   my $log = new IO::File ">>$log_file";
120   flock($log, LOCK_EX);
121   seek($log, 0, 2);
122   print $log "[". time2str("%a %b %e %T %Y",time). "] [$$] $msg\n";
123   flock($log, LOCK_UN);
124   close $log;
125 }
126
127 sub daemonize1 {
128
129   chdir "/" or die "Can't chdir to /: $!";
130   open STDIN, '/dev/null'   or die "Can't read /dev/null: $!";
131   defined(my $pid = fork) or die "Can't fork: $!";
132   if ( $pid ) {
133     print "freeside-sqlradius-radacctd started with pid $pid\n";
134           #logging to $log_file\n";
135     exit unless $pid_file;
136     my $pidfh = new IO::File ">$pid_file" or exit;
137     print $pidfh "$pid\n";
138     exit;
139   }
140   #open STDOUT, '>/dev/null'
141   #                          or die "Can't write to /dev/null: $!";
142   #setsid                  or die "Can't start a new session: $!";
143   #open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
144
145 }
146
147 sub daemonize2 {
148   open STDOUT, '>/dev/null'
149                             or die "Can't write to /dev/null: $!";
150   setsid                  or die "Can't start a new session: $!";
151   open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
152 }
153
154
155 #eslaf
156
157 =head1 NAME
158
159 freeside-sqlradius-radacctd - Real-time radacct import daemon
160
161 =head1 SYNOPSIS
162
163   freeside-sqlradius-radacctd username
164
165 =head1 DESCRIPTION
166
167 Imports records from an SQL radacct table in real-time into the session
168 monitor.
169
170 This enables per-minute or per-hour charges as well as the
171 "View active NAS ports" function.
172
173 B<username> is a username added by freeside-adduser.
174
175 =head1 SEE ALSO
176
177 session.html from the base documentation.
178
179 =cut
180