tchrist@convex.com (Tom Christiansen) (08/31/89)
This is in response to article <848@radig.UUCP> by peter@radig.UUCP (Peter Radig) in comp.mail.sendmail and comp.sources.wanted, who wanted: >is there any public domain accounting package for the sendmail kit? >I need it for charging my users against their outgoing mail. I whipped together a quick perl script to do this. I call it ssl. It will summarize both incoming and outgoing mail by user according to bytes transferred and also according to message count. It has some remedial address parsing to try to determine the person's mbox part of the address, This is the first crude attempt, but it works. Things yet to do include: write a man page merge some of the common To: and From: code by using multi-dimensional arrays add sorting options add more intelligence to address parsing --tom #!/usr/local/bin/perl # # summarize sendmail syslog # # flags mean: # # -o outbound mail only # -i inbound mail only # -t suppress printing of totals # -e print strange lines to stderr # -m reduce to local mbox is possible ($program = $0) =~ s%.*/%%; while ($ARGV[0] =~ /^-/) { $ARGV[0] =~ s/^-//; foreach $flag ( split (//,$ARGV[0]) ) { if ( 'oitem' !~ /$flag/ ) { printf stderr "unknown flag: %s\n", $flag; die "usage: $program [-oitem] [syslog_file ...]\n"; } die "$0: '$flag' flag already set\n" if ($flags{$flag}++); } shift; } if ( !$flags{'o'} && !$flags{'i'} && !$flags{'t'}) { $flags{'o'}++; $flags{'i'}++; } do hash_passwd() if $flags{'m'}; while (<>) { if (/: [A-Z][A-Z](\d+): from=(.*), size=(\d+)/) { next unless $flags{'t'} || $flags{'o'}; ($id, $user, $size) = ($1, $2, $3); $user =~ s/.*<(.*)>/$1/; if ($flags{'m'}) { $ouser = $user; $user = do strip($user); $user = $ouser if ! $known{$user}; } $from_user_size{$user} += $size; $id_size{$id} = $size; $from_user_count{$user}++; $total_from++; } elsif (/: [A-Z][A-Z](\d+): to=(.*), delay=/) { next unless $flags{'t'} || $flags{'i'}; $id = $1; for (split(/,/, $2)) { s/.*<(.*)>/$1/; $to = $flags{'m'} ? do strip($_) : $_; printf "adding %d bytes to %s from %s\n", $id_size{$id},$to,$id; if (!$to) { die "to no one: $_\n"; } $to_user_size{$to} += $id_size{$id}; $to_user_count{$to}++; $total_to++; } } else { study; next if /message-id/; next if /locked/; next if /alias database (auto|)rebuilt/; #next if /aliases/; next if /rebuilding alias database/; print stderr if $flags{'e'}; $errors++; } } printf stderr "Error lines: %d\n", $errors if $errors && ($flags{'e'}) && !($flags{'t'}); if ($flags{'i'}) { printf "To: %d\n", $total_to unless $flags{'t'};; foreach $user ( keys(to_user_size) ) { printf "%4d message%s %7d bytes %s\n", $to_user_count{$user}, $to_user_count{$user} != 1 ? "s" : " ", $to_user_size{$user}, $user; } } if ($flags{'o'}) { printf "From: %d\n", $total_from unless $flags{'t'};; foreach $user ( keys(from_user_size) ) { printf "%4d message%s %7d bytes %s\n", $from_user_count{$user}, $from_user_count{$user} != 1 ? "s" : " ", $from_user_size{$user}, $user; } } sub strip { $_ = @_; s/@.*//; s/.*!//; s/\s*\(.*\)//; tr/A-Z/a-z/; return $_; } sub hash_passwd { chop($yp = `/bin/domainname`) if -x '/bin/domainname'; $passwd = $yp ? 'ypcat passwd |' : '/etc/passwd'; open passwd || die "$program: can't open $passwd: $!\n"; while (<passwd>) { /^(\w+):[^:]+:(\d+):.*/; ($who,$uid) = ($1, $2); $uid = 'zero' if ! $uid; # kludge for uid 0 $known{$who} = $uid; } close passwd; } Tom Christiansen {uunet,uiucdcs,sun}!convex!tchrist Convex Computer Corporation tchrist@convex.COM "EMACS belongs in <sys/errno.h>: Editor too big!"