4 use vars qw( @part_export );
5 use subs qw(myshutdown);
6 use POSIX qw(:sys_wait_h);
8 use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm);
9 use FS::UID qw(adminsuidsetup); #forksuidsetup driver_name dbh myconnect);
10 use FS::Record qw(qsearch); # qsearchs);
15 my $user = shift or die &usage;
17 #daemonize1('freeside-sqlradius-radacctd', $user); #keep unique pid files w/multi installs
18 daemonize1('freeside-sqlradius-radacctd');
22 #$ENV{HOME} = (getpwuid($>))[7]; #for ssh
26 logfile( "/usr/local/etc/freeside/sqlradius-radacctd-log.". $FS::UID::datasrc );
32 #don't just look for ->can('usage_sessions'), we're sqlradius-specific
33 # (radiator is supposed to be setup with a radacct table)
36 qsearch('part_export', { 'exporttype' => 'sqlradius' } );
38 qsearch('part_export', { 'exporttype' => 'sqlradius_withdomain' } );
40 qsearch('part_export', { 'exporttype' => 'radiator' } );
42 @part_export = grep { ! $_->option('ignore_accounting') } @part_export;
44 die "no sqlradius or sqlradius_withdomain exports without ignore_accounting"
49 #fork off one kid per export (machine)
50 # _>{'_radacct_kid'} is an evil kludge
51 foreach my $part_export ( grep ! $_->{'_radacct_kid'}, @part_export ) {
53 defined( my $pid = fork ) or do {
54 warn "WARNING: can't fork to spawn child for ". $part_export->machine;
59 $part_export->{'_radacct_kid'} = $pid;
60 warn "child $pid spawned for ". $part_export->machine;
63 adminsuidsetup($user); #get our own db handle
65 until ( sigint || sigterm ) {
66 $part_export->update_svc_acct();
70 warn "child for ". $part_export->machine. " done";
77 #reap up any kids that died...
80 myshutdown() if sigterm() || sigint();
91 kill 'TERM', $_ foreach grep $_, map $_->{'_radacct_kid'}, @part_export;
93 my $wait = 12; #wait up to 1 minute
94 while ( ( grep $_->{'_radacct_kid'}, @part_export ) && $wait-- ) {
95 warn "waiting for children to terminate";
99 warn "abandoning children" if grep $_->{'_radacct_kid'}, @part_export;
104 #warn "reaping kids\n";
105 foreach my $part_export ( grep $_->{'_radacct_kid'}, @part_export ) {
106 my $pid = $part_export->{'_radacct_kid'};
107 my $kid = waitpid($pid, WNOHANG);
109 $part_export->{'_radacct_kid'} = '';
112 #warn "done reaping\n";
116 die "Usage:\n\n freeside-sqlradius-radacctd user\n";
121 freeside-sqlradius-radacctd - Real-time radacct import daemon
125 freeside-sqlradius-radacctd username
129 Imports records from an the SQL radacct tables of all sqlradius and
130 sqlradius_withdomain exports (except those with the ignore_accounting flag) and
131 updates the svc_acct.seconds for each account. Runs as a daemon and updates
132 the database in real-time.
134 B<username> is a username added by freeside-adduser.
136 =head1 RADIUS DATABASE CHANGES
138 ALTER TABLE radacct ADD COLUMN FreesideStatus varchar(32) NULL;
140 If you want to ignore the existing accountg records, also do:
142 UPDATE TABLE radacct SET FreesideStatus = 'done' WHERE FreesideStatus IS NULL;