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;
 }
 }

Ответить