#!/usr/bin/perl -w use strict; use vars qw($conf); use Fcntl qw(:flock); use FS::UID qw(adminsuidsetup datasrc dbh); use FS::Record qw(dbdef qsearch fields); use FS::session; use FS::svc_acct; my $user = shift or die &usage; adminsuidsetup $user; my $sessionlock = "/usr/local/etc/freeside/session-kill.lock.". datasrc; open(LOCK,"+>>$sessionlock") or die "Can't open $sessionlock: $!"; select(LOCK); $|=1; select(STDOUT); unless ( flock(LOCK,LOCK_EX|LOCK_NB) ) { seek(LOCK,0,0); my($pid)=; chop($pid); #no reason to start loct of blocking processes die "Is another session kill process running under pid $pid?\n"; } seek(LOCK,0,0); print LOCK $$,"\n"; $FS::UID::AutoCommit = 0; my $now = time; #uhhhhh use DBIx::DBSchema; use DBIx::DBSchema::Table; #down this path lies madness use DBIx::DBSchema::Column; my $dbdef = dbdef or die; #warn $dbdef; #warn $dbdef->{'tables'}; #warn keys %{$dbdef->{'tables'}}; my $session_table = $dbdef->table('session') or die; my $svc_acct_table = $dbdef->table('svc_acct') or die; my $session_svc_acct = new DBIx::DBSchema::Table ( 'session,svc_acct', '', '', '', map( DBIx::DBSchema::Column->new( "session.$_", $session_table->column($_)->type, $session_table->column($_)->null, $session_table->column($_)->length, ), $session_table->columns() ), map( DBIx::DBSchema::Column->new( "svc_acct.$_", $svc_acct_table->column($_)->type, $svc_acct_table->column($_)->null, $svc_acct_table->column($_)->length, ), $svc_acct_table->columns ), # map("svc_acct.$_", $svc_acct_table->columns), ); $dbdef->addtable($session_svc_acct); #madness, i tell you $FS::Record::DEBUG = 1; my @session = qsearch('session,svc_acct', {}, '', ' WHERE '. join(' AND ', 'svc_acct.svcnum = session.svcnum', '( session.logout IS NULL OR session.logout = 0 )', "( $now - session.login ) >= svc_acct.seconds" ). " FOR UPDATE" ); my $dbh = dbh; foreach my $join ( @session ) { my $session = new FS::session ( { map { $_ => $join->{'Hash'}{"session.$_"} } fields('session') } ); #see no evil my $svc_acct = new FS::svc_acct ( { map { $_ => $join->{'Hash'}{"svc_acct.$_"} } fields('svc_acct') } ); #false laziness w/ fs_session_server my $nsession = new FS::session ( { $session->hash } ); my $error = $nsession->replace($session); if ( $error ) { $dbh->rollback; die $error; } my $time = $nsession->logout - $nsession->login; my $new_svc_acct = new FS::svc_acct ( { $svc_acct->hash } ); my $seconds = $new_svc_acct->seconds; $seconds -= $time; $seconds = 0 if $seconds < 0; $new_svc_acct->seconds( $seconds ); $error = $new_svc_acct->replace( $svc_acct ); warn "can't debit time from ". $svc_acct->username. ": $error\n"; #don't want to rollback, though #ssenizal eslaf } $dbh->commit or die $dbh->errstr;