diff options
Diffstat (limited to 'usr.sbin/sendmail/contrib/mailprio')
-rw-r--r-- | usr.sbin/sendmail/contrib/mailprio | 557 |
1 files changed, 0 insertions, 557 deletions
diff --git a/usr.sbin/sendmail/contrib/mailprio b/usr.sbin/sendmail/contrib/mailprio deleted file mode 100644 index 58feba7..0000000 --- a/usr.sbin/sendmail/contrib/mailprio +++ /dev/null @@ -1,557 +0,0 @@ -Received: from austin.bsdi.com (root{9l9gVDC7v8t3dlv0OtXTlby6X1zBWd56}@austin.BSDI.COM [205.230.224.49]) by knecht.Sendmail.ORG (8.8.2/8.8.2) with ESMTP id JAA05023 for <eric@sendmail.org>; Thu, 31 Oct 1996 09:29:47 -0800 (PST) -Received: from austin.bsdi.com (localhost [127.0.0.1]) by austin.bsdi.com (8.7.4/8.7.3) with ESMTP id KAA19250; Thu, 31 Oct 1996 10:28:18 -0700 (MST) -Message-Id: <199610311728.KAA19250@austin.bsdi.com> -To: Eric Allman <eric@sendmail.org> -cc: marc@xfree86.org -Subject: Updated mailprio_0_93.shar -From: Tony Sanders <sanders@earth.com> -Organization: Berkeley Software Design, Inc. -Date: Thu, 31 Oct 1996 10:28:14 -0700 -Sender: sanders@austin.bsdi.com - -Eric, please update contrib/mailprio in the sendmail distribution -to this version at your convenience. Thanks. - -I've also made this available in: - ftp://ftp.earth.com/pub/postmaster/ - -mailprio_0_93.shar follows... - -#!/bin/sh -# This is a shell archive (produced by GNU sharutils 4.1). -# To extract the files from this archive, save it to some FILE, remove -# everything before the `!/bin/sh' line above, then type `sh FILE'. -# -# Made on 1996-10-31 10:07 MST by <sanders@earth.com>. -# -# Existing files will *not* be overwritten unless `-c' is specified. -# -# This shar contains: -# length mode name -# ------ ---------- ------------------------------------------ -# 8260 -rwxr-xr-x mailprio -# 3402 -rw-r--r-- mailprio.README -# 4182 -rwxr-xr-x mailprio_mkdb -# -touch -am 1231235999 $$.touch >/dev/null 2>&1 -if test ! -f 1231235999 && test -f $$.touch; then - shar_touch=touch -else - shar_touch=: - echo - echo 'WARNING: not restoring timestamps. Consider getting and' - echo "installing GNU \`touch', distributed in GNU File Utilities..." - echo -fi -rm -f 1231235999 $$.touch -# -# ============= mailprio ============== -if test -f 'mailprio' && test X"$1" != X"-c"; then - echo 'x - skipping mailprio (file already exists)' -else - echo 'x - extracting mailprio (text)' - sed 's/^X//' << 'SHAR_EOF' > 'mailprio' && -#!/usr/bin/perl -# -# mailprio,v 1.4 1996/10/31 17:03:52 sanders Exp -# Version 0.93 -- Thu Oct 31 09:42:25 MST 1996 -# -# mailprio -- setup mail priorities for a mailing list -# -# Copyright 1994, 1996, Tony Sanders <sanders@earth.com> -# Rights are hereby granted to download, use, modify, sell, copy, and -# redistribute this software so long as the original copyright notice -# and this list of conditions remain intact and modified versions are -# noted as such. -# -# I would also very much appreciate it if you could send me a copy of -# any changes you make so I can possibly integrate them into my version. -# -# Options: -# -p priority_database -- Specify database to use if not default -# -q -- Process sendmail V8.8.X queue format files -# -# Sort mailing lists or sendmail queue files by mailprio database. -# Files listed on the command line are locked and then sorted in place, in -# the absence of any file arguments it will read STDIN and write STDOUT. -# -# Examples: -# mailprio < mailing-list > sorted_list -# mailprio mailing-list1 mailing-list2 mailing-list3 ... -# mailprio -q /var/spool/mqueue/qf* -# To double check results: -# sort sorted_list > checkit; sort orig-mailing-list | diff - checkit -# -# To get the maximum value from a transaction delay based priority -# function you need to reorder the distribution list (and the mail -# queue files for that matter) fairly often; you could even have -# your mailing list software reorder the list before each outgoing -# message. -# -$usage = "Usage: mailprio [-p priodb] [-q] [mailinglists ...]\n"; -$home = "/home/sanders/lists"; -$priodb = "$home/mailprio"; -$locking = "flock"; # "flock" or "fcntl" -X -# In shell, it would go more or less like this: -# old_mailprio > /tmp/a -# fgrep -f lists/inet-access /tmp/a | sed -e 's/^.......//' > /tmp/b -# ; /tmp/b contains list of known users, faster delivery first -# fgrep -v -f /tmp/b lists/inet-access > /tmp/c -# ; put all unknown stuff at the top of new list for now -# echo '# -----' >> /tmp/c -# cat /tmp/b >> /tmp/c -X -$qflag = 0; -while ($main'ARGV[0] =~ /^-/) { -X $args = shift; -X if ($args =~ m/\?/) { print $usage; exit 0; } -X if ($args =~ m/q/) { $qflag = 1; } -X if ($args =~ m/p/) { -X $priodb = shift || die $usage, "-p requires argument\n"; } -} -X -push(@main'ARGV, '-') if ($#ARGV < 0); -while ($file = shift @ARGV) { -X if ($file eq "-") { -X $source = "main'STDIN"; -X $sink = "main'STDOUT"; -X } else { -X $sink = $source = "FH"; -X open($source, "+< $file") || do { warn "$file: $!\n"; next; }; -X if (!defined &seize($source, &LOCK_EX | &LOCK_NB)) { -X # couldn't get lock, just skip it -X close($source); -X next; -X } -X } -X -X local(*list); -X &process($source, *list); -X -X # setup to write output -X if ($file ne "-") { -X # zero the file (FH is hardcoded because truncate requires it, sigh) -X seek(FH, 0, 0) || die "$file: seek: $!\n"; -X truncate(FH, 0) || die "$file: truncate: $!\n"; -X } -X -X # do the dirty work -X &output($sink, *list); -X -X close($sink) || warn "$file: $!\n"; # close clears the lock -X close($source); -} -X -sub process { -X # Setup %list and @list -X local($source, *list) = @_; -X local($addr, $canon); -X while ($addr = <$source>) { -X chop $addr; -X next if $addr =~ /^# ----- /; # that's our line -X push(@list, $addr), next if $addr =~ /^\s*#/; # save comments -X if ($qflag) { -X next if $addr =~ m/^\./; -X push(@list, $addr), next if !($addr =~ s/^(R[^:]*:)//); -X $Rflags = $1; -X } -X $canon = &canonicalize((&simplify_address($addr))[0]); -X unless (defined $canon) { -X warn "$file: no address found: $addr\n"; -X push(@list, ($qflag?$Rflags:'') . $addr); # save it as is -X next; -X } -X if (defined $list{$canon}) { -X warn "$file: duplicate: ``$addr -> $canon''\n"; -X push(@list, ($qflag?$Rflags:'') . $addr); # save it as is -X next; -X } -X $list{$canon} = $addr; -X } -} -X -sub output { -X local($sink, *list) = @_; -X -X local($to, *prio, *userprio, *useracct); -X dbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n"; -X foreach $to (keys %list) { -X if (defined $prio{$to}) { -X # add to list of found users (%userprio) and remove from %list -X # so that we know what users were not yet prioritized -X $userprio{$to} = $prio{$to}; # priority -X $useracct{$to} = $list{$to}; # string -X delete $list{$to}; -X } -X } -X dbmclose(%prio); -X -X # Put all the junk we found at the very top -X # (this might not always be a feature) -X print $sink join("\n", @list), "\n" if int(@list); -X -X # prioritized list of users -X if (int(keys %userprio)) { -X print $sink '# ----- prioritized users', "\n" unless $qflag; -X foreach $to (sort by_userprio keys %userprio) { -X die "Opps! Something is seriously wrong with useracct: $to\n" -X unless defined $useracct{$to}; -X print $sink 'RFD:' if $qflag; -X print $sink $useracct{$to}, "\n"; -X } -X } -X -X # unprioritized users go last, fast accounts will get moved up eventually -X # XXX: should go before the "really slow" prioritized users? -X if (int(keys %list)) { -X print $sink '# ----- unprioritized users', "\n" unless $qflag; -X foreach $to (keys %list) { -X print $sink 'RFD:' if $qflag; -X print $sink $list{$to}, "\n"; -X } -X } -X -X print $sink ".\n" if $qflag; -} -X -sub by_userprio { -X # sort first by priority, then by key. -X $userprio{$a} <=> $userprio{$b} || $a cmp $b; -} -X -# REPL-LIB --------------------------------------------------------------- -X -sub canonicalize { -X local($addr) = @_; -X # lowercase, strip leading/trailing whitespace -X $addr =~ y/A-Z/a-z/; $addr =~ s/^\s+//; $addr =~ s/\s+$//; $addr; -} -X -# @addrs = simplify_address($addr); -sub simplify_address { -X local($_) = shift; -X 1 while s/\([^\(\)]*\)//g; # strip comments -X 1 while s/"[^"]*"//g; # strip comments -X split(/,/); # split into parts -X foreach (@_) { -X 1 while s/.*<(.*)>.*/\1/; -X s/^\s+//; -X s/\s+$//; -X } -X @_; -} -X -### ---- ### -# -# Error codes -# -do 'errno.ph'; -eval 'sub ENOENT {2;}' unless defined &ENOENT; -eval 'sub EINTR {4;}' unless defined &EINTR; -eval 'sub EINVAL {22;}' unless defined &EINVAL; -X -# -# File locking -# -do 'sys/unistd.ph'; -eval 'sub SEEK_SET {0;}' unless defined &SEEK_SET; -X -do 'sys/file.ph'; -eval 'sub LOCK_SH {0x01;}' unless defined &LOCK_SH; -eval 'sub LOCK_EX {0x02;}' unless defined &LOCK_EX; -eval 'sub LOCK_NB {0x04;}' unless defined &LOCK_NB; -eval 'sub LOCK_UN {0x08;}' unless defined &LOCK_UN; -X -do 'fcntl.ph'; -eval 'sub F_GETFD {1;}' unless defined &F_GETFD; -eval 'sub F_SETFD {2;}' unless defined &F_SETFD; -eval 'sub F_GETFL {3;}' unless defined &F_GETFL; -eval 'sub F_SETFL {4;}' unless defined &F_SETFL; -eval 'sub O_NONBLOCK {0x0004;}' unless defined &O_NONBLOCK; -eval 'sub F_SETLK {8;}' unless defined &F_SETLK; # nonblocking -eval 'sub F_SETLKW {9;}' unless defined &F_SETLKW; # lockwait -eval 'sub F_RDLCK {1;}' unless defined &F_RDLCK; -eval 'sub F_UNLCK {2;}' unless defined &F_UNLCK; -eval 'sub F_WRLCK {3;}' unless defined &F_WRLCK; -$s_flock = "sslll"; # struct flock {type, whence, start, len, pid} -X -# return undef on failure -sub seize { -X local ($FH, $lock) = @_; -X local ($ret); -X if ($locking eq "flock") { -X $ret = flock($FH, $lock); -X return ($ret == 0 ? undef : 1); -X } else { -X local ($flock, $type) = 0; -X if ($lock & &LOCK_SH) { $type = &F_RDLCK; } -X elsif ($lock & &LOCK_EX) { $type = &F_WRLCK; } -X elsif ($lock & &LOCK_UN) { $type = &F_UNLCK; } -X else { $! = &EINVAL; return undef; } -X $flock = pack($s_flock, $type, &SEEK_SET, 0, 0, 0); -X $ret = fcntl($FH, ($lock & &LOCK_NB) ? &F_SETLK : &F_SETLKW, $flock); -X return ($ret == -1 ? undef : 1); -X } -} -SHAR_EOF - $shar_touch -am 1031100396 'mailprio' && - chmod 0755 'mailprio' || - echo 'restore of mailprio failed' - shar_count="`wc -c < 'mailprio'`" - test 8260 -eq "$shar_count" || - echo "mailprio: original size 8260, current size $shar_count" -fi -# ============= mailprio.README ============== -if test -f 'mailprio.README' && test X"$1" != X"-c"; then - echo 'x - skipping mailprio.README (file already exists)' -else - echo 'x - extracting mailprio.README (text)' - sed 's/^X//' << 'SHAR_EOF' > 'mailprio.README' && -mailprio README -X -mailprio.README,v 1.2 1996/10/31 17:03:54 sanders Exp -Version 0.93 -- Thu Oct 31 09:42:25 MST 1996 -X -Copyright 1994, 1996, Tony Sanders <sanders@earth.com> -Rights are hereby granted to download, use, modify, sell, copy, and -redistribute this software so long as the original copyright notice -and this list of conditions remain intact and modified versions are -noted as such. -X -I would also very much appreciate it if you could send me a copy of -any changes you make so I can possibly integrate them into my version. -X -The current version of this and other related mail tools are available in: -X ftp://ftp.earth.com/pub/postmaster/ -X -Even with the new persistent host status in sendmail V8.8.X this -function can still reduce the lag time distributing mail to a large -group of people. It also makes it a little more likely that everyone -will get mailing list mail in the order sent which can help reduce -duplicate postings. Basically, the goal is to put slow hosts at -the bottom of the list so that as many fast hosts are delivered -as quickly as possible. -X -CONTENTS -======== -X -X mailprio.README -- simple docs -X mailprio -- the address sorter -X mailprio_mkdb -- builds the database for the sorter -X -X -CHANGES -======= -X Version 0.92 -X Initial public release. -X -X Version 0.93 -X Updated to make use of the (somewhat) new xdelay statistic. -X Changed -q flag to support new sendmail queue file format (RFD:<addr>). -X Fixed argument parsing bug. -X Fixed bug with database getting "garbage" in it. -X -X -CONFIGURATION -============= -X -X You need to edit each script and ensure proper configuration. -X -X In mailprio check: #!perl path, $home, $priodb, $locking -X -X In mailprio_mkdb check: #!perl path, $home, $priodb, $maillog -X -X -USAGE: mailprio -=============== -X -X Usage: mailprio [-p priodb] [-q] [mailinglists ...] -X -p priority_database -- Specify database to use if not default -X -q -- Process sendmail queue format files -X [USE WITH CAUTION] -X -X Sort mailing lists or sendmail V8 queue files by mailprio database. -X Files listed on the command line are locked and then sorted in place, in -X the absence of any file arguments it will read STDIN and write STDOUT. -X -X Examples: -X mailprio < mailing-list > sorted_list -X mailprio mailing-list1 mailing-list2 mailing-list3 ... -X mailprio -q /var/spool/mqueue/qf* [not recommended] -X To double check results: -X sort sorted_list > checkit; sort orig-mailing-list | diff - checkit -X -X NOTE: -X To get the maximum value from a transaction delay based priority -X function you need to reorder the distribution list (and the mail -X queue files for that matter) fairly often; you could even have -X your mailing list software reorder the list before each outgoing -X message. -X -X -USAGE: mailprio_mkdb -==================== -X -X Usage: mailprio_mkdb [-l maillog] [-p priodb] -X -l maillog -- Specify maillog to process if not default -X -p priority_database -- Specify database to use if not default -X -X Builds the mail priority database using information from the maillog. -X -X Run at least nightly before you rotate the maillog. If you are -X going to run mailprio more often than that then you will need to -X load the current maillog information before that will do any good -X (and to keep from reloading the same information you will need -X some kind of incremental maillog information to load from). -SHAR_EOF - $shar_touch -am 1031100396 'mailprio.README' && - chmod 0644 'mailprio.README' || - echo 'restore of mailprio.README failed' - shar_count="`wc -c < 'mailprio.README'`" - test 3402 -eq "$shar_count" || - echo "mailprio.README: original size 3402, current size $shar_count" -fi -# ============= mailprio_mkdb ============== -if test -f 'mailprio_mkdb' && test X"$1" != X"-c"; then - echo 'x - skipping mailprio_mkdb (file already exists)' -else - echo 'x - extracting mailprio_mkdb (text)' - sed 's/^X//' << 'SHAR_EOF' > 'mailprio_mkdb' && -#!/usr/bin/perl -# -# mailprio_mkdb,v 1.5 1996/10/31 17:03:53 sanders Exp -# Version 0.93 -- Thu Oct 31 09:42:25 MST 1996 -# -# mailprio_mkdb -- make mail priority database based on delay times -# -# Copyright 1994, 1996, Tony Sanders <sanders@earth.com> -# Rights are hereby granted to download, use, modify, sell, copy, and -# redistribute this software so long as the original copyright notice -# and this list of conditions remain intact and modified versions are -# noted as such. -# -# I would also very much appreciate it if you could send me a copy of -# any changes you make so I can possibly integrate them into my version. -# -# The average function moves the value around quite rapidly (half-steps) -# which may or may not be a feature. This version uses the new xdelay -# statistic (new as of sendmail V8) which is per transaction. We also -# weight the result based on the overall delay. -# -# Something that might be worth doing for systems that don't support -# xdelay would be to compute an approximation of the transaction delay -# by sorting by messages-id and delay then computing the difference -# between adjacent delay values. -# -# To get the maximum value from a transaction delay based priority -# function you need to reorder the distribution list (and the mail -# queue files for that matter) fairly often; you could even have -# your mailing list software reorder the list before each outgoing -# message. -X -$usage = "Usage: mailprio_mkdb [-l maillog] [-p priodb]\n"; -$home = "/home/sanders/lists"; -$maillog = "/var/log/maillog"; -$priodb = "$home/mailprio"; -X -while ($ARGV[0] =~ /^-/) { -X $args = shift; -X if ($args =~ m/\?/) { print $usage; exit 0; } -X if ($args =~ m/l/) { -X $maillog = shift || die $usage, "-l requires argument\n"; } -X if ($args =~ m/p/) { -X $priodb = shift || die $usage, "-p requires argument\n"; } -} -X -$SIG{'PIPE'} = 'handle_pipe'; -X -# will merge with existing information -dbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n"; -&getlog_stats($maillog, *prio); -dbmclose(%prio); -exit(0); -X -sub handle_pipe { -X dbmclose(%prio); -} -X -sub getlog_stats { -X local($maillog, *stats) = @_; -X local($to, $delay); -X local($h, $m, $s); -X open(MAILLOG, "< $maillog") || die "$maillog: $!\n"; -X while (<MAILLOG>) { -X next unless / to=/ && / stat=/; -X next if / stat=queued/; -X if (/ stat=sent/i) { -X # read delay and xdelay and convert to seconds -X ($delay) = (m/ delay=([^,]*),/); -X next unless $delay; -X ($h, $m, $s) = split(/:/, $delay); -X $delay = ($h * 60 * 60) + ($m * 60) + $s; -X -X ($xdelay) = (m/ xdelay=([^,]*),/); -X next unless $xdelay; -X ($h, $m, $s) = split(/:/, $xdelay); -X $xdelay = ($h * 60 * 60) + ($m * 60) + $s; -X -X # Now weight the delay factor by the transaction delay (xdelay). -X $xdelay /= 300; # [0 - 1(@5 min)] -X $xdelay += 0.5; # [0.5 - 1.5] -X $xdelay = 1.5 if $xdelay > 1.5; # clamp -X $delay *= $xdelay; # weight delay by xdelay -X } -X elsif (/, stat=/) { -X # delivery failure of some sort (i.e. bad) -X $delay = 432000; # force 5 days -X } -X $delay = 1000000 if $delay > 1000000; -X -X # filter the address(es); isn't perfect but is "good enough" -X $to = $_; $to =~ s/^.* to=//; -X 1 while $to =~ s/\([^\(\)]*\)//g; # strip comments -X 1 while $to =~ s/"[^"]*"//g; # strip comments -X $to =~ s/, .*//; # remove other stat info -X foreach $addr (&simplify_address($to)) { -X next unless $addr; -X $addr = &canonicalize($addr); -X $stats{$addr} = $delay unless defined $stats{$addr}; # init -X # pseudo-average in the new delay (half-steps) -X # simple, moving average -X $stats{$addr} = int(($stats{$addr} + $delay) / 2); -X } -X } -X close(MAILLOG); -} -X -# REPL-LIB --------------------------------------------------------------- -X -sub canonicalize { -X local($addr) = @_; -X # lowercase, strip leading/trailing whitespace -X $addr =~ y/A-Z/a-z/; $addr =~ s/^\s+//; $addr =~ s/\s+$//; $addr; -} -X -# @addrs = simplify_address($addr); -sub simplify_address { -X local($_) = shift; -X 1 while s/\([^\(\)]*\)//g; # strip comments -X 1 while s/"[^"]*"//g; # strip comments -X split(/,/); # split into parts -X foreach (@_) { -X 1 while s/.*<(.*)>.*/\1/; -X s/^\s+//; -X s/\s+$//; -X } -X @_; -} -SHAR_EOF - $shar_touch -am 1031100396 'mailprio_mkdb' && - chmod 0755 'mailprio_mkdb' || - echo 'restore of mailprio_mkdb failed' - shar_count="`wc -c < 'mailprio_mkdb'`" - test 4182 -eq "$shar_count" || - echo "mailprio_mkdb: original size 4182, current size $shar_count" -fi -exit 0 |