On Mon, 10 Jan 2011 14:55:25 +0200, Exim <exim ÎÁ daily.lv> wrote:
> äÏÂÒÙÊ ÄÅÎØ.
> îÁÓÔÒÁÉ×ÁÀ exim ÐÏ ÜÔÏÊ ÓÈÅÍÅ. ÷Ó£ ÒÁÂÏÔÁÅÔ ÐÏÞÔÉ ËÁË ÎÁÄÏ ËÒÏÍÅ
> Ë×ÏÔ.
×ÏÔ ÓËÒÉÐÔ ÄÌÑ ÐÒÏ×ÅÒËÉ Ë×ÏÔÙ ÎÁ ÜÔÁÐÅ rcpt to
ÚÁÐÕÓËÁÅÔÓÑ ÉÚ /etc/rc.local
# cat /etc/rc.local
/usr/local/etc/exim/quota_check2.pl &
ÒÏÕÔÅÒ × ËÏÍÅÎÔÁÒÉÑÈ
×ÏÚÍÏÖÎÏ ÐÏÔÒÅÂÕÅÔÓÑ ÐÏÐÒÁ×ÉÔØ $quota_fs, ÔË × ÄÅÆÏÌÔÏ×ÙÈ ÉÎÓÔÁÌÑÃÉÑÈ
ispmgr ÀÚÁÅÔ ÏÄÉÎ ÒÁÚÄÅÌ ÐÏÄ ×ÓÅ
#!/usr/bin/perl
# disabled_users:
# driver = redirect
# condition =
${extract{5}{:}{${lookup{$local_part@$domain}lsearch{CONFDIR/passwd}}}}
# allow_fail = yes
# data = :fail: User disabled
# no_more
#
# quota_check:
# # address_test = false
# driver = redirect
# domains = +local_domains
# allow_defer
# condition = ${if
match{${readsocket{/var/run/quota_check2.sock}{$local_part@$domain}}}{\Nover
quota\N}{yes}{no}}
# data = :defer: $local_part@$domain is over quota
use strict;
use Socket;
use Quota;
my $sockname = "/var/run/quota_check2.sock";
my $pidfile = "/var/run/quota_check2.pid";
my $log = "/var/log/quota_check2.log";
$|=1;
my $deb=0;
my $CONFDIR='/usr/local/etc/exim';
my $quota_fs = '/usr';
my $quota_thshd=1024; #1M
my $quota_time_check_thshd=15; #15s
my ($mtime, %hash) = parse_passwd();
socket(UNIX, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
unlink($sockname);
bind(UNIX, sockaddr_un($sockname)) || die "bind: $!";
chmod(0666, $sockname);
listen(UNIX, SOMAXCONN) || die "listen: $!";
if (open(F, "<$pidfile"))
{
my $running = <F>;
close(F);
chop($running);
die "Another quota_check.pl is running (pid = $running)\n" if $$ ==
$running;
}
# Record out PID.
open(F, ">$pidfile") || die "Can't write $pidfile: $!\n";
print F "$$\n";
close(F);
close(STDIN);
close(STDOUT);
close(STDERR) if !$deb;
$SIG{'PIPE'} = sub { };
while (1)
{
if ($deb)
{
open(DEB,">>".$log) || die "Can't open $log: $!\n";
}
my $email='';
accept(C, UNIX);
sysread(C, $email, 1024);
$email =~ s/\s*//;
$email =~ s/\r\n//;
print DEB localtime()." 2 get string $email\n" if $deb;
if ( check_mtime($mtime) )
{
print DEB localtime()." $email 2 need update hash\n" if
$deb;
$mtime=0;
%hash=();
($mtime, %hash) = parse_passwd();
}
my $rep='';
if ( defined($hash{$email}) )
{
#check for cached quotas
print DEB localtime()." $email 3 check cached quota for
$email $hash{$email}{'time'}\n" if $deb;
if ( defined($hash{$email}{'time'}) and
time()-$hash{$email}{'time'} <= $quota_time_check_thshd )
{
$rep=$hash{$email}{'rep'};
print DEB localtime()." $email 3.1 REP $rep\n"
if $deb;
syswrite(C, $rep);
close(C);
next;
}
#check quota for uid
my ($cur, $hard) = (Quota::query($quota_fs,
$hash{$email}{'uid'}))[0,2];
print DEB localtime()." $email 4 check quota for uid
$hash{$email}{'uid'} $cur $hard\n" if $deb;
if ( $hard > 0 and $cur+$quota_thshd >= $hard )
{
$rep='over quota';
$hash{$email}{'rep'}=$rep;
$hash{$email}{'time'}=time();
print DEB localtime()." $email 4.1 REP $rep\n"
if $deb;
syswrite(C, $rep);
close(C);
next;
}
#check quota for gid
my ($cur, $hard) = (Quota::query($quota_fs,
$hash{$email}{'gid'}, 1))[0,2];
print DEB localtime()." $email 5 check quota for gid
$hash{$email}{'gid'} $cur $hard\n" if $deb;
if ( $hard > 0 and $cur+$quota_thshd >= $hard )
{
$rep='over quota';
$hash{$email}{'rep'}=$rep;
$hash{$email}{'time'}=time();
print DEB localtime()." $email 5.1 REP $rep\n"
if $deb;
syswrite(C, $rep);
syswrite(C, $rep);
close(C);
next;
}
#check quota by maildirsize and passwd
if ( defined($hash{$email}{'quota'}) and
$hash{$email}{'quota'} > 0 )
{
my
$maildirsize=$hash{$email}{'home'}.'/.maildir/maildirsize';
my $totalsize=0;
print DEB localtime()." $email 6 check quota
for maildirsize ".$hash{$email}{'home'}.'/.maildir/maildirsize'."\n" if
$deb;
print DEB localtime()." $email 6.1 open file
$maildirsize\n" if $deb;
if ( open(FH, $maildirsize) )
{
while(<FH>)
{
next if /[a-z]/i;
my ($size) = (split('
'))[0];
$totalsize+=$size;
}
close(FH);
print DEB localtime()." $email 6.2
totalsize = $totalsize, mailquota = $hash{$email}{'quota'}\n" if $deb;
print DEB localtime()." $email 6.3
totalsize = ".($totalsize/1024/1024+$quota_thshd/1024).", mailquota =
$hash{$email}{'quota'}\n" if $deb;
}
if ( $totalsize/1024/1024+$quota_thshd/1024 >=
$hash{$email}{'quota'} )
{
$rep='over quota' ;
print DEB localtime()." $email 6.4
PREREP $rep\n" if $deb;
}else
{
$rep='' ;
print DEB localtime()." $email 6.4
PREREP $rep\n" if $deb;
}
}
}
print DEB localtime()." $email 7 REP $rep\n" if $deb;
$hash{$email}{'rep'}=$rep;
$hash{$email}{'time'}=time();
syswrite(C, $rep);
close(C);
if ($deb)
{
close(DEB);
}
}
sub check_mtime
{
my $new_mtime=(stat($CONFDIR."/passwd"))[9];
my $old_mtime=@_[0];
if ( $new_mtime != $old_mtime )
{
print DEB localtime()." 2.2 passwd changed $new_mtime
!= $old_mtime\n" if $deb;
return 1;
}
return 0;
}
sub parse_passwd
{
my %hash;
my $mtime = (stat($CONFDIR."/passwd"))[9];
open(FH, $CONFDIR."/passwd") or die "Cant open
".$CONFDIR."/passwd\n";
while(<FH>)
{
my ($email, $uid, $gid, $quota, $home) =
(split(':'))[0,1,2,3,4];
$hash{$email}{'uid'}=$uid;
$hash{$email}{'gid'}=$gid;
$hash{$email}{'quota'}=$quota;
$hash{$email}{'home'}=$home;
}
close(FH);
return $mtime, %hash;
}
}