#!/usr/local/bin/perl # Copyright (c) 1998 Gabor Egressy gabor@vmunix.com # All rights reserved. All wrongs reversed. This program is free # software; you can redistribute it and/or modify it under the same # terms as Perl itself. # # Parses the mailq; only been tested on Sun boxes use strict; use Getopt::Std; use vars qw(%mail %opts $opt %cc $got_one); sub do_move($$@); sub do_delete($@); $opt = getopts "dhla:m:r:t:",\%opts; if(! $opt || defined $opts{'h'}) { print "Usage : $0 [-dl] [-a address] [-m dir] [-r ratio] [-t threshold]\n". "\t-d\t\tdelete messages for those who exceed -t count mails,\n". "\t\t\tor -r ratio\n". "\t-l\t\tlist number of messages, number of recipients,\n". "\t\t\tthe ratio between the two, and the sender\n". "\t-a address\tspecify an address to delete\n". "\t\t\trequires -d or -m, -m overrides -d\n". "\t-m directory\tmove messages for those who exceed -t count mails,\n". "\t\t\tor who exceed -r ratio; overrides -d\n". "\t-r ratio\tratio of receivers to messages for move or delete,\n". "\t\t\tdefault is 150.0, must be a floating point number\n". "\t-t count\tset delete/move threshold, default is 500\n"; exit; } # $opts{'a'} = quotemeta $opts{'a'} if defined $opts{'a'}; if(defined $opts{'m'}) { do { print "-m requires a directory argument on the same file system\n"; exit; } unless -d $opts{'m'} && (stat "/var/spool/mqueue")[0] == (stat "$opts{'m'}")[0]; $opts{'m'} =~ s/$/\// unless $opts{'m'} =~ /\/$/; } $opts{'r'} = 150.0 unless defined $opts{'r'} && $opts{'r'} =~ /^\d+\.\d+$/; $opts{'t'} = 500 unless defined $opts{'t'} && $opts{'t'} =~ /^\d+$/; $? = 0; open MAIL,"mailq|" or die "$!"; while() { if(/^([A-Z0-9]{2,})\*?\s+\d+\s+[a-zA-Z]+\s+[a-zA-Z]+\s+\d+\s+\d+:\d+\s+(.+)/) { push @{$mail{$2}},$1; $got_one = $2; next; } if($got_one && /^\s+([^\s]+)$/) { ++$cc{$got_one}; next; } if(/^[A-Z0-9]/) { $got_one = 0; } } close MAIL; do { print "*** ERROR *** reading the mailq\n"; exit; } if $?; if(defined $opts{'l'} && keys %mail > 0) { print " MSGS CC RATIO SENDER\n"; for (keys %mail) { printf "%6d %6d %6.2f %s\n", scalar @{$mail{$_}}, $cc{$_}, $cc{$_} / @{$mail{$_}}, $_ if scalar @{$mail{$_}} > $opts{'t'} || $cc{$_} / @{$mail{$_}} > $opts{'r'}; } } if(defined $opts{'a'}) { if(defined $opts{'m'}) { do_move $opts{'m'},$opts{'a'},@{$mail{$opts{'a'}}}; } elsif(defined $opts{'d'}) { do_delete $opts{'a'},@{$mail{$opts{'a'}}}; } else { print "-a requires one of -d or -m flag to work\n"; } } elsif(defined $opts{'m'}) { for (keys %mail) { if(scalar @{$mail{$_}} > $opts{'t'} || $cc{$_} / @{$mail{$_}} > $opts{'r'}) { do_move $opts{'m'},$_,@{$mail{$_}}; } } } elsif(defined $opts{'d'}) { for (keys %mail) { if(scalar @{$mail{$_}} > $opts{'t'} || $cc{$_} / @{$mail{$_}} > $opts{'r'}) { do_delete $_,@{$mail{$_}}; } } } sub do_delete($@) { my ($address,@mail) = @_; my $file; for $file (@mail) { unlink "/var/spool/mqueue/qf$file" and print "DELETING /var/spool/mqueue/qf$file\n"; unlink "/var/spool/mqueue/df$file" and print "DELETING /var/spool/mqueue/df$file\n"; unlink "/var/spool/mqueue/xf$file" and print "DELETING /var/spool/mqueue/xf$file\n"; } } sub do_move($$@) { my ($path,$address,@mail) = @_; my $file; for $file (@mail) { rename "/var/spool/mqueue/qf$file","${path}qf$file" and print "MOVING to ${path}qf$file"; rename "/var/spool/mqueue/df$file","${path}df$file" and print "MOVING to ${path}qf$file"; rename "/var/spool/mqueue/xf$file","${path}xf$file" and print "MOVING to ${path}qf$file"; } }