*** empty log message ***
[freeside.git] / bin / freeside-session-kill
1 #!/usr/bin/perl -w
2
3 use strict;
4 use vars qw($conf);
5 use Fcntl qw(:flock);
6 use FS::UID qw(adminsuidsetup datasrc dbh);
7 use FS::Record qw(dbdef qsearch fields);
8 use FS::session;
9 use FS::svc_acct;
10
11 my $user = shift or die &usage;
12 adminsuidsetup $user;
13
14 my $sessionlock = "/usr/local/etc/freeside/session-kill.lock.". datasrc;
15
16 open(LOCK,"+>>$sessionlock") or die "Can't open $sessionlock: $!";
17 select(LOCK); $|=1; select(STDOUT);
18 unless ( flock(LOCK,LOCK_EX|LOCK_NB) ) {
19   seek(LOCK,0,0);
20   my($pid)=<LOCK>;
21   chop($pid);
22   #no reason to start loct of blocking processes
23   die "Is another session kill process running under pid $pid?\n";
24 }
25 seek(LOCK,0,0);
26 print LOCK $$,"\n";
27
28 $FS::UID::AutoCommit = 0;
29
30 my $now = time;
31
32 #uhhhhh
33
34 use DBIx::DBSchema;
35 use DBIx::DBSchema::Table; #down this path lies madness
36 use DBIx::DBSchema::Column;
37
38 my $dbdef = dbdef or die;
39 #warn $dbdef;
40 #warn $dbdef->{'tables'};
41 #warn keys %{$dbdef->{'tables'}};
42 my $session_table = $dbdef->table('session') or die;
43 my $svc_acct_table = $dbdef->table('svc_acct') or die;
44
45 my $session_svc_acct = new DBIx::DBSchema::Table ( 'session,svc_acct', '', '', '',
46   map( DBIx::DBSchema::Column->new( "session.$_",
47                               $session_table->column($_)->type,
48                               $session_table->column($_)->null,
49                               $session_table->column($_)->length,
50   ), $session_table->columns() ),
51   map( DBIx::DBSchema::Column->new( "svc_acct.$_",
52                               $svc_acct_table->column($_)->type,
53                               $svc_acct_table->column($_)->null,
54                               $svc_acct_table->column($_)->length,
55   ), $svc_acct_table->columns ),
56 #  map("svc_acct.$_", $svc_acct_table->columns),
57 );
58
59 $dbdef->addtable($session_svc_acct); #madness, i tell you
60
61 $FS::Record::DEBUG = 1;
62 my @session = qsearch('session,svc_acct', {}, '', ' WHERE '. join(' AND ',
63   'svc_acct.svcnum = session.svcnum',
64   '( session.logout IS NULL OR session.logout = 0 )',
65   "( $now - session.login ) >= svc_acct.seconds"
66 ). " FOR UPDATE" );
67
68 my $dbh = dbh;
69
70 foreach my $join ( @session ) {
71
72   my $session = new FS::session ( {
73     map { $_ => $join->{'Hash'}{"session.$_"} } fields('session')
74   } ); #see no evil
75
76   my $svc_acct = new FS::svc_acct ( {
77     map { $_ => $join->{'Hash'}{"svc_acct.$_"} } fields('svc_acct')
78   } );
79
80   #false laziness w/ fs_session_server
81   my $nsession = new FS::session ( { $session->hash } );
82   my $error = $nsession->replace($session);
83   if ( $error ) {
84     $dbh->rollback;
85     die $error;
86   }
87   my $time = $nsession->logout - $nsession->login;
88   my $new_svc_acct = new FS::svc_acct ( { $svc_acct->hash } );
89   my $seconds = $new_svc_acct->seconds;
90   $seconds -= $time;
91   $seconds = 0 if $seconds < 0;
92   $new_svc_acct->seconds( $seconds );
93   $error = $new_svc_acct->replace( $svc_acct );
94   warn "can't debit time from ". $svc_acct->username. ": $error\n"; #don't want to rollback, though
95   #ssenizal eslaf
96
97 }
98
99 $dbh->commit or die $dbh->errstr;
100
101 sub usage {
102   die "Usage:\n\n  freeside-session-kill user\n";
103 }