This commit was generated by cvs2svn to compensate for changes in r19841,

which included commits to RCS files with non-trunk default branches.
This commit is contained in:
Peter Wemm 1996-11-18 02:26:51 +00:00
commit dfae3a83bb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=19842
17 changed files with 946 additions and 354 deletions

View File

@ -1,12 +1,125 @@
SENDMAIL RELEASE NOTES
@(#)RELEASE_NOTES 8.8.2.1 (Berkeley) 10/18/96
@(#)RELEASE_NOTES 8.8.3.2 (Berkeley) 11/16/96
This listing shows the version of the sendmail binary, the version
of the sendmail configuration files, the date of release, and a
summary of the changes in that release.
8.8.2/8.8.2 96/11/18
8.8.3/8.8.3 96/11/17
SECURITY: it was possible to get a root shell by lying to sendmail
about argv[0] and then sending it a signal. Problem noted
by Leshka Zakharoff <leshka@leshka.chuvashia.su> on the
best-of-security list.
Log sendmail binary version number in "Warning: .cf version level
(%d) exceeds program functionality (%d) message" -- this
should make it clearer to people that they are running
the wrong binary.
Fix a problem that occurs when you open an SMTP connection and then
do one or more ETRN commands followed by a MAIL command; at
the end of the DATA phase sendmail would incorrectly report
"451 SMTP-MAIL: lost child: No child processes". Problem
noted by Eric Bishop of Virginia Tech.
When doing text-based host canonification (typically /etc/hosts
lookup), a null host name would match any /etc/hosts entry
with space at the end of the line. Problem noted by Steve
Hubert of the University of Washington, Seattle.
7 to 8 bit BASE64 MIME conversions could duplicate bits of text.
Problem reported by Tom Smith of Digital Equipment Corp.
Increase the size of the DNS answer buffer -- the standard UDP packet
size PACKETSZ (512) is not sufficient for some nameserver
answers containing very many resource records. The resolver
may also switch to TCP and retry if it detects UDP packet
overflow. Also, allow for the fact that the resolver
routines res_query and res_search return the size of the
*un*truncated answer in case the supplied answer buffer it
not big enough to accommodate the entire answer. Patch from
Eric Wassenaar.
Improvements to MaxDaemonChildren code. If you think you have too
many children, probe the ones you have to verify that they
are still around. Suggested by Jared Mauch of CICnet, Inc.
Also, do this probe before growing the vector of children
pids; this previously caused the vector to grow indefinitely
due to a race condition. Problem reported by Kyle Jones of
UUNET.
On some architectures, <db.h> (from the Berkeley DB library) defines
O_EXLOCK to zero; this fools the map compilation code into
thinking that it can avoid race conditions by locking on open.
Change it to check for O_EXLOCK non-zero. Problem noted by
Leif Erlingsson of Data Lege.
Always call res_init() on startup (if compiled in, of course) to
allow the sendmail.cf file to tweak resolver flags; without
it, flag tweaks in ResolverOptions are ignored. Patch from
Andrew Sun of Merrill Lynch.
Improvements to host status printing code. Suggested by Steve Hubert
of the University of Washington, Seattle.
Change MinQueueAge option processing to do the check for the job age
when reading the queue file, rather than at the end; this
avoids parsing the addresses, which can do DNS lookups.
Problem noted by John Beck of InReference, Inc.
When MIME was being 7->8 bit decoded, "From " lines weren't being
properly escaped. Problem noted by Peter Nilsson of the
University of Linkoping.
In some cases, sendmail would retain root permissions during queue
runs even if RunAsUser was set. Problem noted by Mark
Thomas of Mark G. Thomas Consulting.
If the F=l flag was set on an SMTP mailer to indicate that it is
actually local delivery, and NOTIFY=SUCCESS is specified in
the envelope, and the receiving SMTP server speaks DSN, then
the DSN would be both generated locally and propogated to the
other end.
The U= mailer field didn't correctly extract the group id if the
user id was numeric. Problem noted by Kenneth Herron of
MCI Telecommunications Communications.
If a message exceeded the fixed maximum size on input, the body of
the message was included in the bounce. Note that this did
not occur if it exceeded the maximum _output_ size. Problem
reported by Kyle Jones of UUNET.
PORTABILITY FIXES:
AIX4: 4.1 does't have a working setreuid(2); change the
AIX4 defines to use seteuid(2) instead, which
works on 4.1 as well as 4.2. Problem noted by
Håkan Lindholm of interAF, Sweden.
AIX4: use tzname[] vector to determine time zone name.
Patch from NAKAMURA Motonori of Kyoto University.
MkLinux: add Makefile.Linux.ppc and OSTYPE(mklinux) support.
Contributed by Paul DeBois <dubois@primate.wisc.edu>.
Solaris: kstat(3k) support for retrieving the load average.
This adds the LA_KSTAT definition for LA_TYPE.
The outline of the implementation was contributed
by Michael Tokarev of Telecom Service, JSC, Moscow.
HP-UX 10.0 gripes about the (perfectly legal!) forward
declaration of struct rusage at the top of conf.h;
change it to only be included if you are using gcc,
which is apparently the only compiler that requires
it in the first place. Problem noted by Jeff
Earickson of Colby College.
IRIX: don't default to using gcc. IRIX is a civilized
operating system that comes with a decent compiler
by default. Problem noted by Barry Bouwsma and
Kari Hurtta.
CONFIG: specify F=9 as default in FEATURE(local_procmail) for
consistency with other local mailers. Inconsistency
pointed out by Teddy Hogeborn <teddy@fukt.hk-r.se>.
CONFIG: if the "limited best mx" feature is used (to reduce DNS
overhead) as part of the bestmx_is_local feature, the
domain part was dropped from the name. Patch from Steve
Hubert of the University of Washington, Seattle.
CONFIG: catch addresses of the form "user@.dom.ain"; these could
end up being translated to the null host name, which would
return any entry in /etc/hosts that had a space at the end
of the line. Problem noted by Steve Hubert of the
University of Washington, Seattle.
CONFIG: add OSTYPE(aix4). From Michael Sofka of Rensselaer
Polytechnic Institute.
MAKEMAP: tweak hash and btree parameters for better performance.
Patch from Matt Dillon of Best Internet Communications.
NEW FILES:
src/Makefiles/Makefile.Linux.ppc
cf/ostype/aix4.m4
cf/ostype/mklinux.m4
8.8.2/8.8.2 96/10/18
SECURITY: fix a botch in the 7-bit MIME patch; the previous patch
changed the code but didn't fix the problem.
PORTABILITY FIXES:
@ -1089,7 +1202,7 @@ summary of the changes in that release.
Syntax errors such as unbalanced parentheses in the configuration
file could be omitted if you had "Oem" prior to the
syntax error in the config file. Change to always print
the error message. It was especially wierd because it
the error message. It was especially weird because it
would cause a "warning" message to be sent to the Postmaster
for every message sent (but with no transcript). Problem
noted by Gregory Paris of Motorola.
@ -1823,7 +1936,7 @@ summary of the changes in that release.
only works on adjacent preferences, so an MX list that
had A=5, B=10, A=15 would leave both As, but one that had
A=5, A=10, B=15 would reduce to A, B. This is intentional,
just in case there is something wierd I haven't thought of.
just in case there is something weird I haven't thought of.
Suggested by Barry Shein of Software Tool & Die.
SECURITY: .forward files cannot be symbolic links. If they are,
a bad guy can read your private files.
@ -2420,7 +2533,7 @@ summary of the changes in that release.
fixed by Michael Corrigan and Christophe Wolfhugel.
8.6.7/8.6.6 94/03/14
SECURITY: it was possible to get root access by using wierd
SECURITY: it was possible to get root access by using weird
values to the -d flag. Thanks to Alain Durand of
INRIA for forwarding me the notice from the bugtraq
list.
@ -2558,7 +2671,7 @@ summary of the changes in that release.
CNAME loops caused an error message to be generated, but also
re-queued the message. Changed to just re-queue the
message (it's really hard to just bounce it because
of the wierd way the name server works in the presence
of the weird way the name server works in the presence
of CNAME loops). Problem noted by James M.R.Matheson
of Cambridge University.
Avoid giving ``warning: foo owned process doing -bs'' messages
@ -2823,7 +2936,7 @@ summary of the changes in that release.
Make sure that route-addrs always have <angle brackets> around
them in non-SMTP envelopes (SMTP envelopes already do
this properly).
Avoid wierd headers on unbalanced punctuation of the form:
Avoid weird headers on unbalanced punctuation of the form:
``Joe User <user)'' -- this caused reference to the
null macro. Fix from Rick McCarty of IO.COM.
Fix a problem that caused an alias "user: user@local.host" to
@ -3488,7 +3601,7 @@ summary of the changes in that release.
the "to" address). Problem noted by John Myers.
Fix dfopen to return NULL if the open failed; I was depending
on fdopen(-1) returning NULL, which isn't the case. This
isn't serious, but does result in wierd error diagnoses.
isn't serious, but does result in weird error diagnoses.
From Michael Corrigan.
CONFIG: add UUCP_MAX_SIZE M4 macro to set the maximum size of
messages sent through UUCP-family mailers. Suggested
@ -3524,7 +3637,7 @@ summary of the changes in that release.
Changes from Eric Wassenaar.
Open /dev/null for the transcript if the create of the xf file
failed; this avoids at least one possible null pointer
reference in very wierd cases. From Eric Wassenaar.
reference in very weird cases. From Eric Wassenaar.
Clean up statistics gathering; it was over-reporting because of
forks. From Eric Wassenaar.
Fix problem that causes old Return-Path: line to override new
@ -3775,7 +3888,7 @@ summary of the changes in that release.
PRALIASES: support for printing NEWDB databases. From
Michael J. Corrigan of U.C. San Diego.
CONFIG: don't pass pseudo-domains to $[ ... $] (if you have
a wildcard MX it can have wierd results). From
a wildcard MX it can have weird results). From
Christophe Wolfhugel.
CONFIG: dot terminate relay hostnames in S0. From Christophe
Wolfhugel.
@ -3888,7 +4001,7 @@ summary of the changes in that release.
Don't try to flock non-regular files when mailing to a file.
In particular, this was a problem if you tried to
send to /dev/null.
Fix a wierd bug that can cause senders to be queued as
Fix a weird bug that can cause senders to be queued as
recipients if the name server is down when the mail
is initially sent. This hack just ignores sender
deletion (essentially, it sets the MeToo flag) if there
@ -4222,7 +4335,7 @@ summary of the changes in that release.
file to have an F line, and the format of the T option
to accept take the format "return/warn" (both intervals).
Don't force all local names to lower case -- this was left over
from the wierd handling of case mapping on aliases. It
from the weird handling of case mapping on aliases. It
is now driven (as expected) by the "u" mailer flag.
Problem noted by P{r Emanuelsson.
Fix problem that caused headers on returned email to be trashed;
@ -4325,7 +4438,7 @@ summary of the changes in that release.
mailer.
Additional debug printing in getcanonname (show query type).
Don't add the e_fromdomain on sender addresses -- this interacts
wierdly with the owner- code.
weirdly with the owner- code.
Improve delivery logging to not log obvious or meaningless stuff.
Include numeric IP address in Received: lines per RFC 1123 section
5.2.8.
@ -4407,7 +4520,7 @@ summary of the changes in that release.
Config extensions for Sam Leffler's FlexFAX software.
6.31/6.10 93/02/28
Fix some more bugs in alias owner code -- there were some wierd
Fix some more bugs in alias owner code -- there were some weird
cases where an error in a non-aliased name would override
the return info in an aliased name with an owner.
Changes from WIDE Project, forwarded to me by Motonori Nakamura:

View File

@ -4,7 +4,7 @@
Eric Allman <eric@CS.Berkeley.EDU>
@(#)README 8.106 (Berkeley) 10/12/96
@(#)README 8.108 (Berkeley) 11/16/96
This document describes the sendmail configuration files being used
@ -128,7 +128,7 @@ Let's examine a typical .mc file:
divert(0)
The divert(-1) will delete the crud in the resulting output file.
The copyright notice can be replace by whatever your lawyers require;
The copyright notice can be replaced by whatever your lawyers require;
our lawyers require the one that I've included in my files. A copyleft
is a copyright by another name. The divert(0) restores regular output.
@ -587,8 +587,10 @@ uucpdomain Similar feature for UUCP hosts. The default map definition
always_add_domain
Include the local host domain even on locally delivered
mail. Normally it is not added unless it is already
present.
mail. Normally it is not added on unqualified names.
However, if you use a shared message store but do not use
the same user name space everywhere, you may need the host
name on local names.
allmasquerade If masquerading is enabled (using MASQUERADE_AS), this
feature will cause recipient addresses to also masquerade
@ -940,8 +942,8 @@ You can have your host masquerade as another using
MASQUERADE_AS(host.domain)
This causes mail being sent to be labeled as coming from the
indicated domain, rather than $j. One normally masquerades as one
of one's own subdomains (for example, it's unlikely that I would
indicated host.domain, rather than $j. One normally masquerades as
one of one's own subdomains (for example, it's unlikely that I would
choose to masquerade as an MIT site). This behaviour is modified by
a plethora of FEATUREs; in particular, see masquerade_envelope,
allmasquerade, limited_masquerade, and masquerade_entire_domain.
@ -1217,6 +1219,11 @@ Plussed users
If that is not found, the alias "root+*" will be tried,
then "root".
LDAP
For notes on use LDAP in sendmail, see
http://www-leland.stanford.edu/~bbense/Inst.html
+----------------+
| SECURITY NOTES |

View File

@ -34,7 +34,7 @@ divert(-1)
#
divert(0)
VERSIONID(`@(#)bestmx_is_local.m4 8.3 (Berkeley) 5/11/96')
VERSIONID(`@(#)bestmx_is_local.m4 8.4 (Berkeley) 10/23/96')
divert(-1)
LOCAL_CONFIG
@ -60,7 +60,7 @@ LOCAL_NET_CONFIG
ifelse(_ARG_, `', `', `#')dnl unlimited bestmx
R$* < @ $* > $* $: $1 < @ $2 @@ $(bestmx $2 $) > $3
ifelse(_ARG_, `', `#', `')dnl limit bestmx to $=B
R$* < @ $* $=B > $* $: $1 < @ $2 @@ $(bestmx $2 $3 $) > $4
R$* < @ $* $=B > $* $: $1 < @ $2 $3 @@ $(bestmx $2 $3 $) > $4
R$* $=O $* < @ $* @@ $=w . > $* $@ $>97 $1 $2 $3
R$* < @ $* @@ $=w . > $* $#local $: $1
R$* < @ $* @@ $* > $* $: $1 < @ $2 > $4

View File

@ -34,7 +34,7 @@ divert(-1)
#
divert(0)
VERSIONID(`@(#)local_procmail.m4 8.5 (Berkeley) 2/12/96')
VERSIONID(`@(#)local_procmail.m4 8.6 (Berkeley) 10/20/96')
divert(-1)
define(`LOCAL_MAILER_PATH',
@ -43,5 +43,5 @@ define(`LOCAL_MAILER_PATH',
PROCMAIL_MAILER_PATH,
`/usr/local/bin/procmail'),
_ARG_))
define(`LOCAL_MAILER_FLAGS', `SPfhn')
define(`LOCAL_MAILER_FLAGS', `SPfhn9')
define(`LOCAL_MAILER_ARGS', `procmail -Y -a $h -d $u')

View File

@ -34,7 +34,7 @@ divert(-1)
#
divert(0)
VERSIONID(`@(#)proto.m4 8.134 (Berkeley) 10/13/96')
VERSIONID(`@(#)proto.m4 8.135 (Berkeley) 10/26/96')
MAILER(local)dnl
@ -662,7 +662,7 @@ R$* $: <> $1
R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3
R<> $* <$* : $* > $* $#error $@ 5.1.1 $: "colon illegal in host name part"
R<> $* $1
R$* < @ . > $* $#error $@ 5.1.2 $: "invalid host name"
R$* < @ . $* > $* $#error $@ 5.1.2 $: "invalid host name"
ifdef(`_MAILER_smtp_',
`# handle numeric address spec

View File

@ -32,8 +32,8 @@ divert(-1)
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
VERSIONID(`@(#)version.m4 8.8.2.1 (Berkeley) 10/18/96')
VERSIONID(`@(#)version.m4 8.8.3.1 (Berkeley) 11/16/96')
#
divert(0)
# Configuration version number
DZ8.8.2`'ifdef(`confCF_VERSION', `/confCF_VERSION')
DZ8.8.3`'ifdef(`confCF_VERSION', `/confCF_VERSION')

View File

@ -0,0 +1,41 @@
divert(-1)
#
# Copyright (c) 1996 Eric P. Allman
# Copyright (c) 1988, 1993
# The Regents of the University of California. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
divert(0)
VERSIONID(`@(#)aix4.m4 8.1 (Berkeley) 11/13/96')
ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /bin/bellmail)')dnl
ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', mail -F $g $u)')dnl
ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', `mn9')')dnl
define(`confTIME_ZONE', `USE_TZ')dnl

View File

@ -0,0 +1,44 @@
divert(-1)
#
# Copyright (c) 1983 Eric P. Allman
# Copyright (c) 1988, 1993
# The Regents of the University of California. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# MkLinux support contributed by Paul DeBois <dubois@primate.wisc.edu>
#
divert(0)
VERSIONID(`@(#)mklinux.m4 8.1 (Berkeley) 10/30/96')
ifdef(`STATUS_FILE',,
`define(`STATUS_FILE', /var/log/sendmail.st)')
ifdef(`PROCMAIL_MAILER_PATH',,
define(`PROCMAIL_MAILER_PATH', `/usr/bin/procmail'))
FEATURE(local_procmail)

View File

@ -1,280 +1,540 @@
Message-Id: <199412081919.NAA23234@austin.BSDI.COM>
To: Eric Allman <eric@cs.berkeley.edu>
Subject: Re: sorting mailings lists with fastest delivery users first
In-reply-to: Your message of Thu, 08 Dec 1994 06:08:33 PST.
References: <199412081408.GAA06210@mastodon.CS.Berkeley.EDU>
From: Tony Sanders <sanders@bsdi.com>
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, 08 Dec 1994 13:19:39 -0600
Sender: sanders@austin.BSDI.COM
Date: Thu, 31 Oct 1996 10:28:14 -0700
Sender: sanders@austin.bsdi.com
Eric Allman writes:
> Nope, that's a new one, so far as I know. Any interest in
> contributing it? For small lists it seems overkill, but for
> large lists it could be a major win.
Eric, please update contrib/mailprio in the sendmail distribution
to this version at your convenience. Thanks.
Sure, I will contribute it; after I sent you mail last night I went ahead
and finished up what I thought needed to be done. I would like to get
some feedback from you on a few items, if you have time.
I've also made this available in:
ftp://ftp.earth.com/pub/postmaster/
There are two programs, mailprio_mkdb and mailprio (source below).
mailprio_0_93.shar follows...
mailprio_mkdb reads maillog files and creates a DB file of address vs.
delay. I'm not too happy with how it does the averages right now but this
is just a quick hack. However, it should at least order sites that take
days vs. those that deliver on the first pass through. One thing that
would make this information a lot more accurate is if sendmail could log
a "transaction delay" (on failures also), as well as total delivery delay.
Perhaps, as an option, it could maintain the DB file itself?
mailprio then simply reads a list of addresses from stdin (the mailing
list), and tries to prioritize them according to the info the database.
It collects comment lines and other junk at the top of the file; all
mailprio does is reorder lines, the actual text of the file should
be unchanged to the extent that you can verify it with:
sort sorted_list > checkit; sort mailing-list | diff - checkit
Users with no delay information are put next. The prioritized list is last.
Of course, this function could also be built-into sendmail (eventually).
Putting "new account" info at the top with the current averaging function
probably adversly affects the prioritized list (at least in the short
term), but putting it at the bottom would not really give the new accounts
a fair chance. I suspect this isn't that big of a problem. I'm running
this here on a list with 461 accounts and about 10 messages per day so
I'll see how it goes. I'll keep some stats on delay times and see what
happens.
Another thing that would help this situation, is if sendmail had the queue
ordered by site (but you already know this). If you ever get to do per
site queuing you should consider "blocking" a queue for some short period
of time if a connection fails to that site [sendmail does this inside a
single process on a per account basis now right?]; this would allow multiple
sendmails to quickly skip over those sites for people like me that run:
for i in 1 2 3 4 5 6 7 8 ; do daemon sendmail -q; done
to flush a queue that has gotten behind. You could also do this inside
sendmail with a parallelism option (when it is time to run the queue, how
many processes to start).
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: mailprio mailprio_mkdb
# Wrapped by sanders@austin.BSDI.COM on Fri Dec 9 18:07:02 1994
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mailprio' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mailprio'\"
#!/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
echo shar: Extracting \"'mailprio'\" \(3093 characters\)
sed "s/^X//" >'mailprio' <<'END_OF_FILE'
X#!/usr/bin/perl
X#
X# mailprio -- setup mail priorities for a mailing list
X#
X# Sort mailing list by mailprio database:
X# mailprio < mailing-list > sorted_list
X# Double check against orig:
X# sort sorted_list > checkit; sort mailing-list | diff - checkit
X# If it checks out, install it.
X#
X# TODO:
X# option to process mqueue files so we can reorder files in the queue!
X$usage = "Usage: mailprio [-p priodb]\n";
X$home = "/home/sanders/lists";
X$priodb = "$home/mailprio";
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
Xif ($main'ARGV[0] =~ /^-/) {
X $args = shift;
X if ($args =~ m/\?/) { print $usage; exit 0; }
X if ($args =~ m/p/) {
X $priodb = shift || die $usage, "-p requires argument\n"; }
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
X# In shell script, it goes something like this:
X# old_mailprio > /tmp/a
X# fgrep -f lists/inet-access /tmp/a | sed -e 's/^.......//' > /tmp/b
X# ; /tmp/b contains list of known users, faster delivery first
X# fgrep -v -f /tmp/b lists/inet-access > /tmp/c
X# ; put all unknown stuff at the top of new list for now
X# echo '# -----' >> /tmp/c
X# cat /tmp/b >> /tmp/c
$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
X# Setup %list and @list
Xlocal($addr, $canon);
Xwhile ($addr = <STDIN>) {
X chop $addr;
X next if $addr =~ /^# ----- /; # that's our line
X push(@list, $addr), next if $addr =~ /^\s*#/; # save comments
X $canon = &canonicalize((&simplify_address($addr))[0]);
X unless (defined $canon) {
X warn "no address found: $addr\n";
X push(@list, $addr); # save it anyway
X next;
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 if (defined $list{$canon}) {
X warn "duplicate: ``$addr -> $canon''\n";
X push(@list, $addr); # save it anyway
X next;
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 $list{$canon} = $addr;
X}
X
Xlocal(*prio);
Xdbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n";
Xforeach $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 # 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}
Xdbmclose(%prio);
}
X
X# Put all the junk we found at the very top
X# (this might not always be a feature)
Xprint join("\n", @list), "\n";
sub output {
X local($sink, *list) = @_;
X
X# unprioritized users go next, slow accounts will get moved down quickly
Xprint '# ----- unprioritized users', "\n";
Xforeach $to (keys %list) { print $list{$to}, "\n"; }
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# finally, our prioritized list of users
Xprint '# ----- prioritized users', "\n";
Xforeach $to (sort { $userprio{$a} <=> $userprio{$b}; } keys %userprio) {
X die "Opps! Something is seriously wrong with useracct: $to\n"
X unless defined $useracct{$to};
X print $useracct{$to}, "\n";
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
Xexit(0);
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# REPL-LIB ---------------------------------------------------------------
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
Xsub canonicalize {
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}
}
X
X# @addrs = simplify_address($addr);
Xsub simplify_address {
# @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 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 1 while s/.*<(.*)>.*/\1/;
X s/^\s+//;
X s/\s+$//;
X }
X @_;
X}
END_OF_FILE
if test 3093 -ne `wc -c <'mailprio'`; then
echo shar: \"'mailprio'\" unpacked with wrong size!
fi
chmod +x 'mailprio'
# end of 'mailprio'
fi
if test -f 'mailprio_mkdb' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'mailprio_mkdb'\"
else
echo shar: Extracting \"'mailprio_mkdb'\" \(3504 characters\)
sed "s/^X//" >'mailprio_mkdb' <<'END_OF_FILE'
X#!/usr/bin/perl
X#
X# mailprio_mkdb -- make mail priority database based on delay times
X#
X$usage = "Usage: mailprio_mkdb [-l maillog] [-p priodb]\n";
X$home = "/home/sanders/lists";
X$maillog = "/var/log/maillog";
X$priodb = "$home/mailprio";
}
X
Xif ($main'ARGV[0] =~ /^-/) {
### ---- ###
#
# 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}
}
X
Xlocal(*prio);
X# We'll merge with existing information if it's already there.
Xdbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n";
X&getlog_stats($maillog, *prio);
X# foreach $addr (sort { $prio{$a} <=> $prio{$b}; } keys %prio) {
X# printf("%06d %s\n", $prio{$addr}, $addr); }
Xdbmclose(%prio);
Xexit(0);
$SIG{'PIPE'} = 'handle_pipe';
X
Xsub getlog_stats {
# 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 ($delay) = (m/, delay=([^,]*), /);
X $delay || next;
X ($h, $m, $s) = split(/:/, $delay);
X $delay = ($h * 60 * 60) + ($m * 60) + $s;
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 # deleting everything after ", " seems safe enough, though
X # it is possible that it was inside "..."'s and that we will
X # miss some addresses because of it. However, I'm not willing
X # to do full parsing just for that case. If this bothers you
X # you could do something like: s/, (delay|ctladdr)=.*//;
X # but you have to make sure you catch all the possible names.
X $to = $_; $to =~ s/^.* to=//; $to =~ s/, .*//;
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 # print $delay, " ", $addr, "\n";
X $stats{$addr} = $delay unless defined $stats{$addr}; # init
X
X # This average function moves the value around quite rapidly
X # which may or may not be a feature.
X #
X # This has at least one odd behavior because we currently only
X # use the delay information from maillog which is only logged
X # on actual delivery. This works backwards from what we really
X # want to happen when a fast host goes down for a while and then
X # comes back up.
X #
X # I spoke with Eric and he suggested adding an xdelay statistic
X # for a per transaction delay which would help that situation
X # a lot. What I believe you want in that cases something like:
X # delay fast, xdelay fast: smokin', these hosts go first
X # delay slow, xdelay fast: put host high on the list (back up?)
X # delay fast, xdelay slow: host is down/having problems/slow
X # delay slow, xdelay slow: poorly connected sites, very last
X # Of course, you have to reorder the distribution list fairly
X # often for that to help. Come to think of it, you should
X # also reorder /var/spool/mqueue files also (if they aren't
X # locked of course). Hmmm....
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}
}
X
X# REPL-LIB ---------------------------------------------------------------
# REPL-LIB ---------------------------------------------------------------
X
Xsub canonicalize {
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}
}
X
X# @addrs = simplify_address($addr);
Xsub simplify_address {
# @addrs = simplify_address($addr);
sub simplify_address {
X local($_) = shift;
X 1 while s/\([^\(\)]*\)//g; # strip comments
X 1 while s/"[^"]*"//g; # strip comments
@ -285,13 +545,13 @@ X s/^\s+//;
X s/\s+$//;
X }
X @_;
X}
END_OF_FILE
if test 3504 -ne `wc -c <'mailprio_mkdb'`; then
echo shar: \"'mailprio_mkdb'\" unpacked with wrong size!
}
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
chmod +x 'mailprio_mkdb'
# end of 'mailprio_mkdb'
fi
echo shar: End of shell archive.
exit 0

View File

@ -30,7 +30,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)op.me 8.97 (Berkeley) 10/17/96
.\" @(#)op.me 8.98 (Berkeley) 11/16/96
.\"
.\" eqn op.me | pic | troff -me
.eh 'SMM:08-%''Sendmail Installation and Operation Guide'
@ -68,7 +68,7 @@ Eric Allman
InReference, Inc.
eric@Sendmail.ORG
.sp
Version 8.97
Version 8.98
.sp
For Sendmail Version 8.8
.)l
@ -3561,6 +3561,25 @@ The full name of the sender.
The home directory of the recipient.
.ip $_
The validated sender address.
.ip ${bodytype}
The message body type
(7BIT or 8BITMIME),
as determined from the envelope.
.ip ${client_addr}
The IP address of the SMTP client.
Defined in the SMTP server only.
.ip ${client_name}
The host name of the SMTP client.
Defined in the SMTP server only.
.ip ${client_port}
The port number of the SMTP client.
Defined in the SMTP server only.
.ip ${envid}
The envelope id passed to sendmail as part of the envelope.
.ip ${opMode}
The current operation mode (from the
.b \-b
flag).
.pp
There are three types of dates that can be used.
The
@ -3758,10 +3777,12 @@ and the receiver has the IDENT protocol turned on,
it will include the user name on that host.
.pp
The
.b ${client_name}
.b ${client_name} ,
.b ${client_addr} ,
and
.b ${client_addr}
are set to the name and address of the SMTP client
.b ${client_port}
macros
are set to the name, address, and port number of the SMTP client
who is invoking
.i sendmail
as a server.
@ -8129,7 +8150,7 @@ A transcript of the current session.
.\"Eric Allman
.\"InReference, Inc.
.\".sp
.\"Version 8.97
.\"Version 8.98
.\".ce 0
.bp 2
.rs

View File

@ -30,7 +30,7 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# @(#)READ_ME 8.125 (Berkeley) 10/18/96
# @(#)READ_ME 8.130 (Berkeley) 11/10/96
#
This directory contains the source files for sendmail.
@ -168,7 +168,7 @@ LDAPMAP Lightweight Directory Lookup Protocol support. You will
this flag.
>>> NOTE WELL for NEWDB support: it is CRITICAL that you remove ndbm.o
>>> from libdb.a and ndbm.h from the appropriate include directories if
>>> from libdb.a before you install it and DO NOT install ndbm.h if
>>> you want to get ndbm support. If you don't delete these, there is
>>> absolutely no point to including -DNDBM, since it will just get you
>>> another (inferior) API to the same format database. These files
@ -355,11 +355,20 @@ LA_TYPE The type of load average your kernel supports. These
the dg_sys_info system call.
LA_HPUX (10) is an HP-UX specific version that uses the
pstat_getdynamic system call.
LA_IRIX6 (11) is an IRIX 6.x specific version that adapts
to 32 or 64 bit kernels; it is otherwise very similar
to LA_INT.
LA_KSTAT (12) uses the (Solaris-specific) kstat(3k)
implementation.
LA_DEVSHORT (13) reads a short from a system file (default:
/dev/table/avenrun) and scales it in the same manner
as LA_SHORT.
LA_INT, LA_SHORT, LA_FLOAT, and LA_READKSYM have several
other parameters that they try to divine: the name of your
kernel, the name of the variable in the kernel to examine,
the number of bits of precision in a fixed point load average,
and so forth.
and so forth. LA_DEVSHORT uses _PATH_AVENRUN to find the
device to be read to find the load average.
In desperation, use LA_ZERO. The actual code is in
conf.c -- it can be tweaked if you are brave.
FSHIFT For LA_INT, LA_SHORT, and LA_READKSYM, this is the number
@ -809,6 +818,26 @@ IRIX
the developers' option in order to get the necessary include
files.
If you compile with -lmalloc (the fast memory allocator), you may
get warning messages such as the following:
ld32: WARNING 85: definition of _calloc in /usr/lib32/libmalloc.so
preempts that definition in /usr/lib32/mips3/libc.so.
ld32: WARNING 85: definition of _malloc in /usr/lib32/libmalloc.so
preempts that definition in /usr/lib32/mips3/libc.so.
ld32: WARNING 85: definition of _realloc in /usr/lib32/libmalloc.so
preempts that definition in /usr/lib32/mips3/libc.so.
ld32: WARNING 85: definition of _free in /usr/lib32/libmalloc.so
preempts that definition in /usr/lib32/mips3/libc.so.
ld32: WARNING 85: definition of _cfree in /usr/lib32/libmalloc.so
preempts that definition in /usr/lib32/mips3/libc.so.
These are unavoidable and innocuous -- just ignore them.
According to Dave Sill <de5@ornl.gov>, there is a version of the
Berkeley db library patched to run on Irix 6.2 available from
http://reality.sgi.com/ariel/db-1.85-irix.tar.Z .
NeXT or NEXTSTEP
NEXTSTEP 3.3 and earlier ship with the old DBM library. You will
need to acquire the new Berkeley DB from ftp.cs.berkeley.edu.
@ -1348,4 +1377,4 @@ version.c The version number and information about this
Eric Allman
(Version 8.125, last update 10/18/96 07:32:40)
(Version 8.130, last update 11/10/96 11:15:30)

View File

@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)envelope.c 8.93 (Berkeley) 9/26/96";
static char sccsid[] = "@(#)envelope.c 8.96 (Berkeley) 11/11/96";
#endif /* not lint */
#include "sendmail.h"
@ -153,9 +153,24 @@ dropenvelope(e, fulldrop)
e->e_flags &= ~EF_QUEUERUN;
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
{
if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags) ||
bitset(QQUEUEUP, q->q_flags))
if (bitset(QQUEUEUP, q->q_flags) &&
bitset(QDONTSEND, q->q_flags))
{
/* I'm not sure how this happens..... */
if (tTd(50, 2))
{
printf("Bogus flags: ");
printaddr(q, FALSE);
}
q->q_flags &= ~QDONTSEND;
}
if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
queueit = TRUE;
#if XDEBUG
else if (bitset(QQUEUEUP, q->q_flags))
syslog(LOG_DEBUG, "%s: q_flags = %x",
e->e_id, q->q_flags);
#endif
/* see if a notification is needed */
if (bitset(QPINGONFAILURE, q->q_flags) &&
@ -203,8 +218,7 @@ dropenvelope(e, fulldrop)
fprintf(e->e_xfp, "Message will be deleted from queue\n");
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
{
if (bitset(QQUEUEUP, q->q_flags) ||
!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
{
q->q_flags |= QBADADDR;
q->q_status = "4.4.7";

View File

@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)map.c 8.140 (Berkeley) 10/12/96";
static char sccsid[] = "@(#)map.c 8.144 (Berkeley) 11/16/96";
#endif /* not lint */
#include "sendmail.h"
@ -107,7 +107,7 @@ static char sccsid[] = "@(#)map.c 8.140 (Berkeley) 10/12/96";
extern bool aliaswait __P((MAP *, char *, int));
extern bool extract_canonname __P((char *, char *, char[], int));
#if defined(O_EXLOCK) && HASFLOCK
#if O_EXLOCK && HASFLOCK
# define LOCK_ON_OPEN 1 /* we can open/create a locked file */
#else
# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */
@ -690,6 +690,8 @@ extract_canonname(name, line, cbuf, cbuflen)
p = get_column(line, i, '\0', nbuf, sizeof nbuf);
if (p == NULL)
break;
if (*p == '\0')
continue;
if (cbuf[0] == '\0' ||
(strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL))
{
@ -1034,17 +1036,30 @@ ndbm_map_close(map)
** be pokey about it. That's hard to do.
*/
extern bool db_map_open __P((MAP *, int, DBTYPE));
extern bool db_map_open __P((MAP *, int, DBTYPE, const void *));
/* these should be K line arguments */
#ifndef DB_CACHE_SIZE
# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */
#endif
#ifndef DB_HASH_NELEM
# define DB_HASH_NELEM 4096 /* (starting) size of hash table */
#endif
bool
bt_map_open(map, mode)
MAP *map;
int mode;
{
BTREEINFO btinfo;
if (tTd(38, 2))
printf("bt_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
return db_map_open(map, mode, DB_BTREE);
bzero(&btinfo, sizeof btinfo);
btinfo.cachesize = DB_CACHE_SIZE;
return db_map_open(map, mode, DB_BTREE, &btinfo);
}
bool
@ -1052,17 +1067,24 @@ hash_map_open(map, mode)
MAP *map;
int mode;
{
HASHINFO hinfo;
if (tTd(38, 2))
printf("hash_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
return db_map_open(map, mode, DB_HASH);
bzero(&hinfo, sizeof hinfo);
hinfo.nelem = DB_HASH_NELEM;
hinfo.cachesize = DB_CACHE_SIZE;
return db_map_open(map, mode, DB_HASH, &hinfo);
}
bool
db_map_open(map, mode, dbtype)
db_map_open(map, mode, dbtype, openinfo)
MAP *map;
int mode;
DBTYPE dbtype;
const void *openinfo;
{
DB *db;
int i;
@ -1113,7 +1135,7 @@ db_map_open(map, mode, dbtype)
omode |= O_TRUNC;
#endif
db = dbopen(buf, omode, DBMMODE, dbtype, NULL);
db = dbopen(buf, omode, DBMMODE, dbtype, openinfo);
saveerrno = errno;
#if !LOCK_ON_OPEN

View File

@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)mci.c 8.44 (Berkeley) 10/9/96";
static char sccsid[] = "@(#)mci.c 8.46 (Berkeley) 11/3/96";
#endif /* not lint */
#include "sendmail.h"
@ -362,6 +362,7 @@ mci_get(host, m)
**
** Parameters:
** mci -- the MCI structure to set.
** xstat -- the exit status code.
** dstat -- the DSN status code.
** rstat -- the SMTP status code.
**
@ -370,18 +371,19 @@ mci_get(host, m)
*/
void
mci_setstat(mci, dstat, rstat)
mci_setstat(mci, xstat, dstat, rstat)
MCI *mci;
int xstat;
char *dstat;
char *rstat;
{
mci->mci_exitstat = xstat;
mci->mci_status = dstat;
if (mci->mci_rstatus != NULL)
free(mci->mci_rstatus);
if (rstat != NULL)
{
if (mci->mci_rstatus != NULL)
free(mci->mci_rstatus);
mci->mci_rstatus = newstr(rstat);
}
rstat = newstr(rstat);
mci->mci_rstatus = rstat;
}
/*
** MCI_DUMP -- dump the contents of an MCI structure.
@ -1032,6 +1034,7 @@ mci_print_persistent(pathname, hostname)
int status;
int width = Verbose ? 78 : 25;
bool locked;
char *p;
MCI mcib;
if (!initflag)
@ -1061,16 +1064,34 @@ mci_print_persistent(pathname, hostname)
locked = !lockfile(fileno(fp), pathname, "", LOCK_EX|LOCK_NB);
fclose(fp);
if (mcib.mci_rstatus == NULL)
printf("%c%-39s %12s %.*s\n",
locked ? '*' : ' ', hostname,
pintvl(curtime() - mcib.mci_lastuse, TRUE),
width, errstring(mcib.mci_errno));
printf("%c%-39s %12s ",
locked ? '*' : ' ', hostname,
pintvl(curtime() - mcib.mci_lastuse, TRUE));
if (mcib.mci_rstatus != NULL)
printf("%.*s\n", width, mcib.mci_rstatus);
else if (mcib.mci_exitstat == EX_TEMPFAIL && mcib.mci_errno != 0)
printf("Deferred: %.*s\n", width - 10, errstring(mcib.mci_errno));
else if (mcib.mci_exitstat != 0)
{
int i = mcib.mci_exitstat - EX__BASE;
extern int N_SysEx;
extern char *SysExMsg[];
if (i < 0 || i > N_SysEx)
{
char buf[80];
snprintf(buf, sizeof buf, "Unknown mailer error %d",
mcib.mci_exitstat);
printf("%.*s\n", width, buf);
}
else
printf("%.*s\n", width, &(SysExMsg[i])[5]);
}
else if (mcib.mci_errno == 0)
printf("OK\n");
else
printf("%c%-39s %12s %.*s\n",
locked ? '*' : ' ', hostname,
pintvl(curtime() - mcib.mci_lastuse, TRUE),
width, mcib.mci_rstatus);
printf("OK: %.*s\n", width - 4, errstring(mcib.mci_errno));
return 0;
}

View File

@ -36,9 +36,9 @@
#ifndef lint
#ifdef QUEUE
static char sccsid[] = "@(#)queue.c 8.125 (Berkeley) 10/12/96 (with queueing)";
static char sccsid[] = "@(#)queue.c 8.131 (Berkeley) 11/8/96 (with queueing)";
#else
static char sccsid[] = "@(#)queue.c 8.125 (Berkeley) 10/12/96 (without queueing)";
static char sccsid[] = "@(#)queue.c 8.131 (Berkeley) 11/8/96 (without queueing)";
#endif
#endif /* not lint */
@ -296,40 +296,45 @@ queueup(e, announce)
printctladdr(NULL, NULL);
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
{
if (bitset(QQUEUEUP, q->q_flags) ||
!bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))
if (bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))
{
printctladdr(q, tfp);
if (q->q_orcpt != NULL)
fprintf(tfp, "Q%s\n",
denlstring(q->q_orcpt, TRUE, FALSE));
putc('R', tfp);
if (bitset(QPRIMARY, q->q_flags))
putc('P', tfp);
if (bitset(QHASNOTIFY, q->q_flags))
putc('N', tfp);
if (bitset(QPINGONSUCCESS, q->q_flags))
putc('S', tfp);
if (bitset(QPINGONFAILURE, q->q_flags))
putc('F', tfp);
if (bitset(QPINGONDELAY, q->q_flags))
putc('D', tfp);
putc(':', tfp);
fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE));
if (announce)
{
e->e_to = q->q_paddr;
message("queued");
if (LogLevel > 8)
logdelivery(q->q_mailer, NULL, "queued",
NULL, (time_t) 0, e);
e->e_to = NULL;
}
if (tTd(40, 1))
{
printf("queueing ");
printaddr(q, FALSE);
}
#if XDEBUG
if (bitset(QQUEUEUP, q->q_flags))
syslog(LOG_DEBUG, "%s: q_flags = %x",
e->e_id, q->q_flags);
#endif
continue;
}
printctladdr(q, tfp);
if (q->q_orcpt != NULL)
fprintf(tfp, "Q%s\n",
denlstring(q->q_orcpt, TRUE, FALSE));
putc('R', tfp);
if (bitset(QPRIMARY, q->q_flags))
putc('P', tfp);
if (bitset(QHASNOTIFY, q->q_flags))
putc('N', tfp);
if (bitset(QPINGONSUCCESS, q->q_flags))
putc('S', tfp);
if (bitset(QPINGONFAILURE, q->q_flags))
putc('F', tfp);
if (bitset(QPINGONDELAY, q->q_flags))
putc('D', tfp);
putc(':', tfp);
fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE));
if (announce)
{
e->e_to = q->q_paddr;
message("queued");
if (LogLevel > 8)
logdelivery(q->q_mailer, NULL, "queued",
NULL, (time_t) 0, e);
e->e_to = NULL;
}
if (tTd(40, 1))
{
printf("queueing ");
printaddr(q, FALSE);
}
}
@ -574,7 +579,7 @@ runqueue(forkflag)
if (forkflag)
{
int pid;
pid_t pid;
extern void intsig();
#ifdef SIGCHLD
extern void reapchild();
@ -625,6 +630,15 @@ runqueue(forkflag)
/* force it to run expensive jobs */
NoConnect = FALSE;
/* drop privileges */
if (geteuid() == (uid_t) 0)
{
if (RunAsGid != (gid_t) 0)
(void) setgid(RunAsGid);
if (RunAsUid != (uid_t) 0)
(void) setuid(RunAsUid);
}
/*
** Create ourselves an envelope
*/
@ -1387,6 +1401,7 @@ readqf(e)
struct stat st;
char *bp;
int qfver = 0;
long hdrsize = 0;
register char *p;
char *orcpt = NULL;
bool nomore = FALSE;
@ -1579,6 +1594,7 @@ readqf(e)
case 'H': /* header */
(void) chompheader(&bp[1], FALSE, NULL, e);
hdrsize += strlen(&bp[1]);
break;
case 'M': /* message */
@ -1611,6 +1627,26 @@ readqf(e)
case 'N': /* number of delivery attempts */
e->e_ntries = atoi(&buf[1]);
/* if this has been tried recently, let it be */
if (e->e_ntries > 0 &&
(curtime() - e->e_dtime) < MinQueueAge)
{
char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
extern void unlockqueue();
if (Verbose || tTd(40, 8))
printf("%s: too young (%s)\n",
e->e_id, howlong);
#ifdef LOG
if (LogLevel > 19)
syslog(LOG_DEBUG, "%s: too young (%s)",
e->e_id, howlong);
#endif
e->e_id = NULL;
unlockqueue(e);
return FALSE;
}
break;
case 'P': /* message priority */
@ -1694,25 +1730,6 @@ readqf(e)
return TRUE;
}
/* if this has been tried recently, let it be */
if (e->e_ntries > 0 && (curtime() - e->e_dtime) < MinQueueAge)
{
char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
extern void unlockqueue();
if (Verbose || tTd(40, 8))
printf("%s: too young (%s)\n",
e->e_id, howlong);
#ifdef LOG
if (LogLevel > 19)
syslog(LOG_DEBUG, "%s: too young (%s)",
e->e_id, howlong);
#endif
e->e_id = NULL;
unlockqueue(e);
return FALSE;
}
/*
** Arrange to read the data file.
*/
@ -1728,7 +1745,7 @@ readqf(e)
e->e_flags |= EF_HAS_DF;
if (fstat(fileno(e->e_dfp), &st) >= 0)
{
e->e_msgsize = st.st_size;
e->e_msgsize = st.st_size + hdrsize;
e->e_dfdev = st.st_dev;
e->e_dfino = st.st_ino;
}
@ -1971,7 +1988,7 @@ queuename(e, type)
register ENVELOPE *e;
int type;
{
static int pid = -1;
static pid_t pid = -1;
static char c0;
static char c1;
static char c2;

View File

@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)version.c 8.8.2.1 (Berkeley) 10/18/96";
static char sccsid[] = "@(#)version.c 8.8.3.2 (Berkeley) 11/16/96";
#endif /* not lint */
char Version[] = "8.8.2";
char Version[] = "8.8.3";

View File

@ -39,6 +39,7 @@ AIX 3.1.5 FAIL 93.08.07 David J. N. Begley
AIX 3.2.3e FAIL 93.07.26 Steve Bauer <sbauer@silver.sdsmt.edu>
AIX 3.2.4 FAIL 93.10.07 David J. N. Begley
AIX 3.2.5 FAIL 94.05.17 Steve Bauer <sbauer@hpcmmib.hpc.sdsmt.edu>
AIX 4.1 FAIL 96.10.21 Hakan Lindholm <hakan@af.lu.se>
AIX 4.2 OK 96.10.16 Steve Bauer <sbauer@krypton.hpc.sdsmt.edu>
IRIX 4.0.4 OK 93.09.25 Robert Elz
@ -78,6 +79,8 @@ Solaris 2.5 OK 96.02.29 Carson Gaspar <carson@lehman.com>
Linux 1.2.13 FAIL 95.11.02 Sven Neuhaus <sven@ping.de>
Linux 2.0.17 FAIL 96.09.03 Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
AIX 4.1 OK 96.10.21 Hakan Lindholm <hakan@af.lu.se>
IRIX 5.2 OK 95.12.01 Mark Andrews <mandrews@aw.sgi.com>
IRIX 5.3 OK 95.12.01 Mark Andrews <mandrews@aw.sgi.com>
IRIX 6.2 OK 96.09.16 Kari E. Hurtta <Kari.Hurtta@ozone.FMI.FI>