quota.pl
        
  1     #!/usr/local/bin/perl
  2      
  3     $AdminDir = "/u/arafel/adm/etc";
  4     $WarnAt = 0.90;
  5     
  6     # Read current quota map.
  7     
  8     open(INFILE, "$AdminDir/quotas") 
  9             || die "Can't open $AdminDir/quotas" ;
 10             
 11     open(LOGFILE, " | tee -a $AdminDir/quota.log  
 12             |/usr/ucb/Mail -s \"Quota Action report \" root")
 13             || die "Can't open $AdminDir/quota.log";
 14     
 15     print(LOGFILE "\nQuota run at ",`date`);
 16     
 17     while (<INFILE>) {
 18             ($user,$hisquota,$hishistory)=split(/\s+/);
 19             $history{$user}=$hishistory;
 20             $quota{$user}=$hisquota;
 21             }
 22     close(INFILE);
 23     
 24     #generate full userlist.
 25     
 26     open(INFILE,"ypcat passwd |");
 27     while (<INFILE>) {
 28             ($ypuser,$yppasswd,$uid,$gid,$Full,$Home)=split(/:/);
 29             if ($gid <= 100) {next;} # skip system accounts 
 30             push(@ypuserlist,$ypuser);
 31             $FullName{$ypuser} = $Full;
 32                     $HomeDir{$ypuser} = $Home;
 33             if ( $yppasswd !~ /^\*/ ) { 
 34                     $passwd{$ypuser} = "enabled";
 35                     } 
 36             else {
 37                     $passwd{$ypuser} = "disabled";
 38                     } 
 39             }               
 40     
 41     #Process each user;
 42     
 43     foreach $u ( @ypuserlist ){
 44             $hisquota = $quota{$u};
 45             $hishistory = $history{$u}; 
 46             if ($passwd{$u} eq "disabled") {
 47                     next;
 48                     }
 49     
 50             # get user's diskusage.
 51             ($diskusage) = split(/\s+/,`du -s ~$HomeDir{$u}`);
 52     
 53             # Is the user quotad?
 54             if ($hisquota == 0){ 
 55                     print LOGFILE "NOTQ: $u\n"; 
 56                     next;
 57                     }
 58     
 59             # He's over quota.
 60             if ($hisquota < $diskusage) {
 61                     $hishistory = "O".$hishistory; #O is for Over
 62                     chop $hishistory;
 63                     $history{$u} = $hishistory;
 64                     printf LOGFILE "OVER: %-8s %s U=%-8s Q=%-8s\n",
 65                             $u,$hishistory, $diskusage,$hisquota;
 66                     # Decide which message is mailed to him.
 67                     $NumOver = (split(/O/,$hishistory."X") - 1); #Fence post
 68                     if ($NumOver == 1 ) {&FirstOver;} 
 69                     elsif($NumOver < 6) {&MoreOver;}
 70                     elsif($NumOver = 6) {&LastOver;}
 71                     elsif($NumOver >= 7) {
 72                     &Disable;
 73                     printf LOGFILE "DSLB: %-8s %s U=%-8s Q=%-8s\n",
 74                             $u,$hishistory, $diskusage,$hisquota;
 75                             } #end elsif
 76                     } #endif
 77     
 78             # He's getting close
 79             elsif (($WarnAt *$hisquota) < $diskusage){
 80                     <%-3>$percentquota = sprintf("%3d",(100.0*$diskusage/$hisquota));<%0>
 81                     $quotaleft = $hisquota - $diskusage;
 82                     $hishistory = "W".$hishistory;
 83                     chop $hishistory;
 84                     $history{$u}= $hishistory;
 85                     printf LOGFILE "Warn: %-8s %s U=%-8s Q=%-8s\n",
 86                             $u,$hishistory, $diskusage,$hisquota;
 87                     &WarnUser;
 88                     }
 89     
 90             # He's ok.
 91             elsif (($WarnAt *$hisquota) >= $diskusage){
 92                     $hishistory = "-".$hishistory;
 93                     chop $hishistory;
 94                     $history{$u}= $hishistory;
 95                     }
 96             }
 97             
 98     # We're done, so now finish up the loose ends
 99     
100     close(LOGFILE);
101     
102     #Write out the new user history.
103     open(OUT,"|sort +1n >$AdminDir/quotas");
104     foreach $u ( @ypuserlist){
105             printf(OUT "%-10s%8d %s\n",
106                     $u,$quota{$u},$history{$u});
107             }
108     close(OUT);
109     
110     sub WarnUser{
111     open(MAILOUT, "|/usr/ucb/Mail -s \"Nearing Quota Limit \" $u");
112     print MAILOUT <<EOF;
113     
114     You are currently using $percentquota% of your disk quota.
115     Currently you have only $quotaleft kilobytes left.
116     You might look into various space space saving tricks.
117     I'd be glad to show you some.
118     
119     Sherwood
120     EOF
121     close MAILOUT;
122     }
123     
124     sub FirstOver{
125     open(MAILOUT, "|/usr/ucb/Mail -s \"OVER QUOTA!!\" $u");
126     print MAILOUT <<EOF;
127     You are OVER your disk quota.
128     Please take the time to clean out your files.
129     You might also compress or zipdir files that you don't
130     use often, move files to tape, or use the scratch disk.
131     EOF
132     close MAILOUT;
133     }
134     
135     sub MoreOver{
136     open(MAILOUT, "|/usr/ucb/Mail -s \"OVER QUOTA!!\" $u");
137     print MAILOUT <<EOF;
138     Ahem...
139     You were sent a note regarding being over quota.
140     You are still over quota.  Please reduce your file usage
141     until you are using less than $hisquota kilobytes.  We have
142     various tools to help you do this. Ask me for help if you need 
143     assistance.
144     
145     EOF
146     close MAILOUT;
147     }
148     
149     sub LastOver{
150     open(MAILOUT, "|/usr/ucb/Mail -s \"OVER QUOTA!!\" $u");
151     print MAILOUT <<EOF;
152     
153     Please be aware that you remain over quota.
154     If you are not under quota ($hisquota kilobytes) by
155     next time this program runs, your account will be disabled.
156     It will then be deleted after the next archival backup.
157     EOF
158     close MAILOUT;
159     }
160     
161     
162     sub Disable{
163             system("sed -e \"/$u/ s-\:-\:\*-\" 
164                             < /etc/passwd.yp > /etc/passwd.new");
165             system("mv /etc/passwd.new /etc/passwd.yp; cd /etc/yp; make");
166             }

