Add a FREEBSD-upgrade file describing what was done for the import

Remove obsolete files after the 8.11.0 import
This commit is contained in:
Gregory Neil Shapiro 2000-08-12 22:25:19 +00:00
parent 3299c2f123
commit cd904b75f9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=64566
19 changed files with 49 additions and 5781 deletions

View File

@ -0,0 +1,49 @@
$FreeBSD$
sendmail 8.11.0
originals can be found at: ftp://ftp.sendmail.org/pub/sendmail/
For the import of sendmail, the following files were removed:
cf/cf/generic-bsd4.4.cf
cf/cf/generic-hpux10.cf
cf/cf/generic-hpux9.cf
cf/cf/generic-linux.cf
cf/cf/generic-osf1.cf
cf/cf/generic-solaris2.cf
cf/cf/generic-sunos4.1.cf
cf/cf/generic-ultrix4.cf
devtools/*
doc/op/op.ps
mail.local/mail.local.0
mailstats/mailstats.0
makemap/makemap.0
praliases/praliases.0
rmail/rmail.0
sendmail/aliases.0
sendmail/mailq.0
sendmail/newaliases.0
sendmail/sendmail.0
sendmail/sysexits.h
smrsh/smrsh.0
vacation/vacation.0
The following directories were renamed:
sendmail -> src
Imported using:
cvs import -m 'Import sendmail 8.11.0' \
src/contrib/sendmail SENDMAIL v8_11_0
To make local changes to sendmail, simply patch and commit to the main
branch (aka HEAD). Never make local changes on the vendor (SENDMAIL)
branch.
All local changes should be submitted to the Sendmail Consortium
<sendmail@sendmail.org> for inclusion in the next vendor release.
gshapiro@FreeBSD.org
12-August-2000

View File

@ -1,113 +0,0 @@
divert(-1)
#
# Copyright (c) 1998 Sendmail, Inc. All rights reserved.
# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved.
# Copyright (c) 1988, 1993
# The Regents of the University of California. All rights reserved.
#
# By using this file, you agree to the terms and conditions set
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
#
divert(0)
VERSIONID(`@(#)nullrelay.m4 8.19 (Berkeley) 5/19/1998')
#
# This configuration applies only to relay-only hosts. They send
# all mail to a hub without consideration of the address syntax
# or semantics, except for adding the hub qualification to the
# addresses.
#
# This is based on a prototype done by Bryan Costales of ICSI.
#
######################################################################
######################################################################
#####
##### REWRITING RULES
#####
######################################################################
######################################################################
###########################################
### Rulset 3 -- Name Canonicalization ###
###########################################
S3
# handle null input
R$@ $@ <@>
# strip group: syntax (not inside angle brackets!) and trailing semicolon
R$* $: $1 <@> mark addresses
R$* < $* > $* <@> $: $1 < $2 > $3 unmark <addr>
R$* :: $* <@> $: $1 :: $2 unmark node::addr
R:`include': $* <@> $: :`include': $1 unmark :`include':...
R$* : $* <@> $: $2 strip colon if marked
R$* <@> $: $1 unmark
R$* ; $1 strip trailing semi
R$* < $* ; > $1 < $2 > bogus bracketed semi
# null input now results from list:; syntax
R$@ $@ :; <@>
# basic textual canonicalization -- note RFC733 heuristic here
R$* $: < $1 > housekeeping <>
R$+ < $* > < $2 > strip excess on left
R< $* > $+ < $1 > strip excess on right
R<> $@ < @ > MAIL FROM:<> case
R< $+ > $: $1 remove housekeeping <>
ifdef(`_NO_CANONIFY_', `dnl',
`# eliminate local host if present
R@ $=w $=: $+ $@ @ $M $2 $3 @thishost ...
R@ $+ $@ @ $1 @somewhere ...
R$=E @ $=w $@ $1 @ $2 leave exposed
R$+ @ $=w $@ $1 @ $M ...@thishost
R$+ @ $+ $@ $1 @ $2 ...@somewhere
R$=w ! $=E $@ $2 @ $1 leave exposed
R$=w ! $+ $@ $2 @ $M thishost!...
R$+ ! $+ $@ $1 ! $2 @ $M somewhere ! ...
R$=E % $=w $@ $1 @ $2 leave exposed
R$+ % $=w $@ $1 @ $M ...%thishost
R$+ % $+ $@ $1 @ $2 ...%somewhere
R$=E $@ $1 @ $j leave exposed
R$+ $@ $1 @ $M unadorned user')
######################################
### Ruleset 0 -- Parse Address ###
######################################
S0
R$*:;<@> $#error $@ USAGE $: "List:; syntax illegal for recipient addresses"
# pass everything else to a relay host
R$* $#_RELAY_ $@ $H $: $1
##################################################
### Ruleset 4 -- Final Output Post-rewriting ###
##################################################
S4
R$* <@> $@ handle <> and list:;
# strip trailing dot off before passing to nullclient relay
R$* @ $+ . $1 @ $2
#
######################################################################
######################################################################
#####
`##### MAILER DEFINITIONS'
#####
######################################################################
######################################################################
undivert(7)dnl

View File

@ -1,20 +0,0 @@
divert(-1)
#
# Copyright (c) 1998 Sendmail, Inc. All rights reserved.
# Copyright (c) 1997 Eric P. Allman. All rights reserved.
# Copyright (c) 1988, 1993
# The Regents of the University of California. All rights reserved.
#
# By using this file, you agree to the terms and conditions set
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
#
#
divert(0)
VERSIONID(`@(#)gnuhurd.m4 8.8 (Berkeley) 10/6/1998')
ifdef(`HELP_FILE',, `define(`HELP_FILE', ifdef(`_USE_ETC_MAIL_', `/etc/mail/helpfile', `/share/misc/sendmail.hf'))')dnl
ifdef(`STATUS_FILE',, `define(`STATUS_FILE', ifdef(`_USE_ETC_MAIL_', `/etc/mail/statistics', `/var/log/sendmail.st'))')dnl
ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /libexec/mail.local)')dnl
define(`confEBINDIR', `/libexec')dnl

View File

@ -1,446 +0,0 @@
Converting Standard Sun Config
Files to Sendmail Version 8
Rick McCarty
Texas Instruments Inc.
Latest Update: 08/25/93 - RJMc
This document details the changes necessary to continue using your
current SunOS sendmail.cf with sendmail version 8. In the longer term,
it is recommended that one move to using an m4 based configuration such
as those shipped with sendmail, but if you're like me and have made
enough modifications to your .cf file that you'd rather put that task
off until later, here's the sum total of my experience to get you to
version 8 with minimal pain. I'll cover .cf as well as build issues.
Some background - as many are surely aware, Sun has some "special"
features in the sendmail they ship ($%x, %y LHS lookup, NIS alias DB
search, etc.). (Some of those features can be had in alternative forms
in IDA sendmail, but v8 has picked up some IDA capabilities as well as
new ones, making it IMHO a most desirable version to go to.) What I
will explain below includes v8 functional "equivalences" to these Sun
sendmail features.
So with that out of the way, let's begin.
First, some assumptions:
1) I'm going to assume you've got sendmail version 8.6 or
later in hand - if not, grab it from ftp.cs.berkeley.edu
in the ucb/sendmail directory. There are bugs in earlier
versions which affect some of the needed functionality.
2) Second, I'm going to detail this based upon the
"sendmail.main.cf" configuration. (BTW, if you attempt
to move to using an m4 generated config in the future,
MAIL_HUB is the feature which should provide similar
functionality).
In general, the changes will be similar for a subsidiary
file, but since we (my TI group) funnel all non-local mail
through our mailhost, we're not as interested in getting v8
to run on such systems and I haven't tried it.
3) You're using DNS and sendmail.mx. If you're not, you ought
to be, even if you're also running it along with NIS (which
we do - except for gethostbyxxx() lookups, which I'll be
talking about later). I would imagine you could get things
running OK without DNS support, but I haven't tried it myself.
4) You're not mounting /var/spool/mail from other systems.
I haven't found a v8 feature to guarantee this will work
correctly. Anyway, in the past, we've tried doing that
here and found it to be a rather "ugly" feature, though
Sun ostensibly supports it ("R" option). Perhaps v8
will one day have a similar feature, but for now, bottom
line, I would recommend against it.
5) You're not on Solaris or using NIS+. I'm on 4.1.3. I've
looked at Solaris briefly and have noted that things are
pretty much similar there except that they've moved some
things into the /etc/mail directory. I'd guess the
executables aren't functionally all that different from
what they had before - the configs are roughly the same.
So I'd bet most of what I say in here will apply to
Solaris.
OK, let's configure our sendmail.cf! I'll just go from the top down...
VARIOUS DECLARATIONS
1) For v8, you need to define your .cf as AT LEAST a version level 4
configuration. Add the following line:
V4
There are some issues regarding certain predefined macros - $w, $j, and
$m. With a V4 configuration:
$w is defined to be the hostname, which will usually be fully
qualified (i.e. "firefly.add.itg.ti.com").
$j should have the same value as $w.
$m will be predefined as the domain portion of $w
(ex. "add.itg.ti.com").
One note about this - if your configuration relies on the "w" macro to
be the "simple" hostname (as mine does)...
If the configuration version is 5 or larger:
$w is supposed to be the "simple" name (ex. "firefly")
$j should be the fully qualified name (i.e. "firefly.add.itg.ti.com")
$m will be predefined as the domain portion of $j
(ex. "add.itg.ti.com").
I have not experimented with the various combinations, so I cannot
guarantee you that the above definitions will always come out as
expected. Bottom line: if your sendmail.cf depends on $w being the
simple hostname, test it carefully or define the name explicitly,
for example:
Dwfirefly
2) To replace the Sun's "%y" feature, we must use a hostname mapping
feature in v8. If you want to do similar lookups with v8, you need
to define the following map (we'll go over the rules that use this
map later):
Khostlookup host -f -m -a.
This will define a "lookup only" map that is otherwise the same as
sendmail version 8's built-in "host" map (see the "Sendmail
Installation and Operation Guide" for details on this map.).
An important note: Whether or not these lookups will be done via
NIS is a function of what gethostbyxxx() functions you link into
your sendmail. DO NOT redefine your host mapping to use NIS
explicitly within sendmail - there can be unexpected behaviour if
you do so (if you do any canonicalization in your .cf, you can get
incorrect results, for one thing).
For example, DO NOT TRY:
Khost nis -f -a. hosts.byname
3) If you're doing reverse alias mapping as done in ruleset 22, instead of:
DZmail.byaddr
you'll need to declare the following:
Kaliasrev nis -f -N mail.byaddr
4) If you are doing any other NIS map lookups, you'll need to define the
map as done in the below example. I have a "mailhosts" map, which I
use to distinguish between local and non-local hosts. Look at the
sendmail doc for details on this stuff.
Kmailhosts nis -f -m -a. mailhosts
5) You might wish to add the following line to support Errors-To: headers.
I don't.
Ol
6) Comment out/remove the following line:
OR
The R option means something different under v8 - check the documentation
if you're interested in using it.
7) If you're running NIS and have a separate alias map, BELOW the
following line where the alias file is declared:
OA/etc/aliases
ADD the following:
OAnis:mail.aliases
This will set things up so v8 will look at the local alias DB first,
then the NIS map, just as Sun sendmail does.
8) Though you don't have to, I'd suggest changing:
OT3d
to use v8's warning feature, which allows a warning message to be
sent if a message cannot be delivered within a specified period.
I use:
OT5d/4h
which says - bounce after 5 days, warn after 4 hours.
9) I set the following option to be explicit about how I want DNS
handled:
OI +DNSRCH +DEFNAMES
10) The following line:
T root daemon uucp
may be deleted, though it will be ignored if you leave it around.
11) It would probably be good to change the version macro value (which
shows up in "Received:" headers) so no one debugging mail problems
gets the wrong idea about what config you're running under. Look
for something like:
DVSMI-4.1
Mine, for example is:
DVADD-HUB-2.1
RULESETS
1) In ruleset 3, BELOW this rule:
# basic textual canonicalization
R$*<$+>$* $2 basic RFC822 parsing
I add the following rule to remove a trailing dot in the domain spec so
it won't interfere with v8 mapping features, etc. (Having a trailing dot is
not RFC-compliant anyway.):
R$+. $1
2) Because ruleset 5 is special in v8, I rename it to S95 and also change
all RHS expressions containing ">5" to use ">95" instead. In v8,
5 is executed against addresses which resolve to the local mailer and
are not an alias. If you don't change S5 to something else, you might
get a surprise!
3) If you're doing any lookups via the generalized NIS "$%x/$!x"
mechanisms (such as with the mailhost map I referred to earlier) it's
done differently under v8. For example:
DMmailhosts
...
R$*<@$%M.uucp>$* $#ether $@$2 $:$1<@$2>$3
takes a different map definition and two rules under version 8:
Kmailhosts nis -f -m -a. mailhosts
...
R$*<@$+.uucp>$* $: $1<@$(mailhosts $2 $).uucp>$3
R$*<@$+..uucp>$* $#ether $@$2 $:$1<@$2>$3
4) Sun has a special case of the "$%x" feature for host lookups - "%y" is
automagically defined to do an NIS "hosts.byname" search with no other
definition, as done in the below example:
R$*<@$%y.LOCAL>$* $#ether $@$2 $:$1<@$2>$3
(Sun does this in more than one place. But the above syntax is almost
identical in each - mostly a case of changing names to protect the
innocent.)
In version 8, the predefined "host" map can be used to do essentially
the same thing. (However, whether or not it does an NIS lookup is
a function of what gethostbyxxx() functions are linked in.)
Recall the map definition I mentioned earlier in the DECLARATIONS
section:
Khostlookup host -f -m -a.
Here's where we will use it. It will take two rules:
R$*<@$+.LOCAL>$* $: $1<@$(hostlookup $2 $).LOCAL>$3
R$*<@$+..LOCAL>$* $#ether $@$2 $:$1<@$2>$3
Note that this is almost verbatim the same change as was used in the
previous "mailhosts" example.
5) Although Sun's default configs don't do this, because I mentioned
canonicalization earlier, it deserves an example, as it's illustrative
of the functional difference in the map definitions I discussed before.
This stuff is also convered in the "Sendmail Installation and Operation
Guide".
Remember the built-in "host" map definition? As you'll recall, unlike
the "hostlookup" map we defined, "host" will actually CHANGE the
hostname in addition to appending a dot. "hostlookup" only appends a
dot if the name is found and doesn't change it otherwise. Anyway,
here's the example:
R$*<@$+>$* $: $1<@$(host $2 $)>$3 canonicalize
R$*<@$+.>$* $1<@$2>$3 remove trailing dot
Using the above, say you had input of:
joe<@tilde>
OR
joe<@[128.247.160.56]>
Assuming "tilde" or the IP address is found, it might be
canonicalized as:
joe<@tilde.csc.ti.com>
6) As another instance of the NIS lookup feature, with a slightly
different twist, Sun implements reverse alias mapping in ruleset 22
with the below:
DZmail.byaddr
...
R$-<@$-> $:$>3${Z$1@$2$} invert aliases
To use this feature under v8, change the above rule a (remember to
define the alias map as I showed earlier):
R$-<@$-> $:$>3$(aliasrev $1@$2 $) invert aliases
MAILER DEFINITIONS
1) Where "TCP" is defined in the "P=" and "A=" parameters of mailers, I
changed it to "IPC". Version 8 will accept "TCP", but "IPC" is
preferred.
2) On all IPC mailers, I also defined "E=\r\n" and added an "L=1000" as
in the below example:
Mether, P=[IPC], F=mDFMuCX, S=11, R=21, L=1000, E=\r\n, A=IPC $h
The "E=\r\n" will save you headaches interoperating with such things as
VMS TCP products.
The "L=1000" is for RFC821 compatibility. Not strictly necessary.
I also removed the "s" (strip quotes) mailer flag Sun puts in for
these mailers. Stripping quotes violates protocols, which say
clearly that you can't touch the local-part (left hand side of
the @) until you are on the delivering host.
NOW. If I haven't left anything out, you should be able to run through
your Sun sendmail.cf file and convert it to run under v8.
BUILD ISSUES
Some important notes on building v8 on SunOS:
Makefile
The default makefile in the version 8 source (src) directory assumes the
new Berkeley make. Unless you want to go to the trouble of building it,
you can use your regular make, but you need to use a different makefile.
You can use "Makefile.dist" or "Makefile.SunOS" in the src directory. I
made changes to get it to build so it is as compatible as possible with
the file/directory locations Sun uses. Here are some relevant sections
out of my makefile:
CC=gcc
# use O=-O (usual) or O=-g (debugging)
O= -O
# define the database mechanisms available for map & alias lookups:
# -DNDBM -- use new DBM
# -DNEWDB -- use new Berkeley DB
# -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
# -DNIS -- include client NIS support
# The really old (V7) DBM library is no longer supported.
# See README for a description of how these flags interact.
#DBMDEF= -DNDBM -DNEWDB
DBMDEF= -DNDBM -DNIS
# environment definitions (e.g., -D_AIX3)
ENVDEF=
# see also conf.h for additional compilation flags
# library directories
LIBDIRS=-L/usr/local/lib
# libraries required on your system
#LIBS= -ldb -ldbm
LIBS= -ldbm -lresolv
# location of sendmail binary (usually /usr/sbin or /usr/lib)
BINDIR= ${DESTDIR}/usr/lib
# location of sendmail.st file (usually /var/log or /usr/lib)
STDIR= ${DESTDIR}/etc
# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
HFDIR= ${DESTDIR}/usr/lib
For the resolver library, you can use the one shipped with Sun if you
want. But I'd recommend using another version of the resolver library
(such as the one with Bind 4.8.3 or 4.9). Sun's resolver stuff (at
least with 4.1.x) is quite old - I believe it is of 4.3.1 vintage. (Do
you get the impression I don't TRUST what Sun ships with their systems?)
If you want NIS host lookup while maintaining DNS capability, you might
take a look at resolv+, which has NIS capable gethostbyxxx() functions
in it. My recommendation, however, is to avoid doing NIS host lookups
in sendmail altogether, and to use a "pure" version of the resolver
library.
There are probably no situations (at least I think so) where it makes
any sense to link in Sun's NIS gethostbyxxx() functions from libc.
You could, I guess do it (I haven't tried it) and wind up with a
sendmail equivalent to the non-mx version Sun ships. You'd need to
insure that NAMED_BIND is not defined in the build. (If you do
this and have the "-b" DNS passthru option set in NIS, remember that
while you have some DNS functionality you'll not have any MX support.
(This, IMO, is what makes this a non-optimal choice.)
INSTALLATION/TESTING ISSUES
The sendmail.hf file in the src directory should replace the one currently
in /usr/lib. You also might choose to edit it a bit to "localize" what it
says.
The sendmail executable goes, of course, in /usr/lib in place of the current
one. What I did was create a subdirectory in /usr/lib and put all of the
Sun sendmail stuff in there. I named the v8 sendmail executable to be
sendmail.v8.mx and then symbolically linked it to sendmail.
One other thing. If you use address test mode, keep in mind that
Version 8 is like IDA in that it does not automatically execute ruleset
3 first. So say you're playing around with things testing addresses and
you're used to things like:
0 jimbob@good.old.boy.com
under v8 you need to say instead:
3,0 jimbob@good.old.boy.com
INTEROPERABILITY ISSUES YOU MIGHT ENCOUNTER
Be aware that sendmail v8 issues a multi-line SMTP welcome (220)
response upon a client connection. Most systems in your network should
handle it OK, but there are some that choke on it, because whoever wrote
the clients assumed only a single line. THIS IS NOT SENDMAIL's FAULT.
A multi-line 220 response is perfectly valid. A likely place you'll
encounter this problem is with non-Un*x SMTP clients. If you do run
into it, you should report it to the vendor.
A final note about version 8 - if you follow the above configuration
scenario, you'll notice it doesn't like to get envelope sender
addresses it doesn't know how to get back to. Sun sendmail would take
anything, even though it might not be able to bounce the message back
should something happen downstream. So if another sendmail on a host
that's not locally known is trying to pump mail through your v8 host,
the ENVELOPE sender it gives had better be fully qualified. This is
a GREAT thing, because it helps clear up problems we've had with not
being able to get things back to the sender, resulting in an
overburdened postmaster.
I hope this helps those running Sun sendmail feel more at ease with moving
on to v8. It's really worth going to.

View File

@ -1,13 +0,0 @@
# @(#)Makefile 8.1 (Berkeley) 4/13/1994
DIR= smm/09.sendmail
SRCS= changes.me
MACROS= -me
all: changes.ps
changes.ps: ${SRCS}
rm -f ${.TARGET}
${PIC} ${SRCS} | ${ROFF} > ${.TARGET}
.include <bsd.doc.mk>

View File

@ -1,975 +0,0 @@
.\" Copyright (c) 1998 Sendmail, Inc. All rights reserved.
.\" Copyright (c) 1994 Eric P. Allman. All rights reserved.
.\" Copyright (c) 1988, 1994
.\" The Regents of the University of California. All rights reserved.
.\"
.\" By using this file, you agree to the terms and conditions set
.\" forth in the LICENSE file which can be found at the top level of
.\" the sendmail distribution.
.\"
.\"
.\" @(#)changes.me 8.7 (Berkeley) 5/19/1998
.\"
.\" ditroff -me -Pxx changes.me
.eh '%''Changes in Sendmail Version 8'
.oh 'Changes in Sendmail Version 8''%'
.nr si 3n
.if n .ls 2
.+c
.(l C
.sz 14
Changes in Sendmail Version 8*
.sz
.sp
Eric Allman
.sp 0.5
.i
University of California, Berkeley
Mammoth Project
.)l
.(f
*An earlier version of this paper was printed in the
Proceedings of the 1994 AUUG Queensland Summer Technical Conference,
Gateway Hotel, Brisbane, March 1994.
.)f
.sp
.(l F
.ce
ABSTRACT
.sp \n(psu
Version 8 of
.i sendmail
includes a number of major changes from previous versions.
This paper gives a very short history of
.i sendmail ,
a summary of the major differences between version 5
(the last publically available version)
and version 8,
and some discussion of future directions.
.)l
.sp 2
.pp
In 1987, the author stopped major work on
.i sendmail
due to other time committments,
only to return to active work in 1991.
This paper explores why work resumed
and what changes have been made.
.pp
Section 1 gives a short history of
.i sendmail
through version 5 and the motivation behind working on version 8.
Section 2 has
a rather detailed description of what has changed
between version 5 and version 8.
The paper finishes off with some thoughts
about what still needs to be done.
.sh 1 "HISTORY"
.pp
As discussed elsewhere,
[Allman83a, Allman83b, Allman&Amos85]
sendmail has existed in various forms since 1980.
It was released under the name
.i delivermail
in 4BSD and 4.1BSD, and as
.i sendmail
in 4.2BSD.
.\"4.0BSD delivermail 1.10
.\"4.1BSD delivermail 1.10
.\"4.2BSD sendmail 4.12
.\"4.3BSD sendmail 5.52
It quickly became the dominant mail system for networked UNIX systems.
.pp
Prior the release of 4.3BSD in November 1986,
the author had left the University for private industry,
but continued to do some work on
.i sendmail
with activity slowly trailing off
until effectively stopping after February 1987.
There was minimal support done by many people for several years,
until July of 1991 when the original author,
who had returned the University,
started active work on it again.
.pp
There were several reasons for renewed work on
.i sendmail .
There was a desire at Berkeley to convert to a subdomained structure
so that individuals were identified by their subdomain
rather than by their individual workstation;
although possible in the old code, there were some problems,
and the author was the obvious person to address them.
The Computer Systems Research Group (CSRG),
the group that produced the Berkeley Software Distributions,
was working on 4.4BSD,
and wanted an update to the mail system.
Bryan Costales was working on a book on
.i sendmail
that was being reviewed by the author,
which encouraged him to make some revisions.
And the author wanted to try to unify some of the disparate versions of
.i sendmail
that had been permitted to proliferate.
.pp
During the 1987\-91 fallow period,
many vendors and outside volunteers
had produced variants of
.i sendmail .
Perhaps the best known is the IDA version
[IDA87].
Originally intended to be a new set of configuration files,
IDA expanded into a fairly large set of patches for the code.
Originally produced in Sweden,
IDA development passed to the University of Illinois,
and was widely used by the fairly large set of people
who prefer to get and compile their own source code
rather than use vendor-supplied binaries.
.pp
In about the same time frame,
attempts were made to clean up and extend the Simple Mail Transport Protocol
(SMTP)
[RFC821].
This involved clarifications of some ambiguities in the protocol,
and correction of some problem areas
[RFC1123],
as well as extensions for additional functionality
(dubbed Extended Simple Mail Transport Protocol, or ESMTP)
[RFC1425, RFC1426, RFC1427]
and a richer set of semantics in the body of messages
(the Multipurpose Internet Mail Extensions, a.k.a. MIME)
[RFC1521, RFC1344].
Neither the IDA group nor most vendors
were modifying
.i sendmail
to conform to these new standards.
It seemed clear that these were ``good things''
that should be encouraged.
However, since no one was working on a publically available version of
.i sendmail
with these updates,
they were unlikely to be widely deployed any time in the near future.
.pp
There are, of course, other mail transport agents available,
such as
.i MMDF
.\"[ref],
.i zmailer
.\"[ref],
.i smail
.\"[ref],
and
.i PP
.\"[ref].
However, none of these seemed to be gaining the prominence of
.i sendmail ;
it appeared that most companies would not convert to another
mail transport agent any time in the forseeable future.
However, they might be persuaded to convert to a newer version of
.i sendmail .
.pp
All of these convinced the author
to work on a updated version of
.i sendmail
for public distribution.
.pp
The new version of
.i sendmail
is referred to as version eight (V8).
Versions six and seven were skipped
because of an agreement
that all files in 4.4BSD would be numbered as
.q 8.1 .
Rather than have an external version number
that differed from the file version numbers,
.i sendmail
just jumped directly to V8.
.sh 1 "CHANGES IN VERSION EIGHT"
.pp
The following is a summary of the changes between the last commonly
available version of sendmail from Berkeley (5.67) and the latest
version (8.6.6).
.pp
Many of these are ideas that had been tried in IDA,
but many of them were generalized in V8.
.sh 2 "Performance Enhancements"
.pp
Instead of closing SMTP connections immediately, open connections are
cached for possible future use. There is a limit to the number of
simultaneous open connections and the idle time of any individual
connection.
.pp
This is of best help during queue processing (since there is the
potential of many different messages going to one site), although
it can also help when processing MX records which aren't handled
by MX Piggybacking.
.pp
If two hosts with different names in a single message happen to
have the same set of MX hosts, they can be sent in the same
transaction. Version 8 notices this and tries to batch the messages.
.pp
For example, if two sites ``foo.com'' and ``bar.com'' are both
served by UUNET, they will have the same set of MX hosts and will
be sent in one transaction. UUNET will then split the message
and send it to the two individual hosts.
.sh 2 "RFC 1123 Changes"
.pp
A number of changes have been made to make sendmail ``conditionally
compliant'' (that is, it satisfies all of the MUST clauses and most
but not all of the SHOULD clauses in RFC 1123).
.pp
The major areas of change are (numbers are RFC 1123 section numbers):
.nr ii 0.75i
.ip \(sc5.2.7
Response to RCPT command is fast. Previously, sendmail
expanded all aliases as far as it could \*- this could
take a very long time, particularly if there were
name server delays. Version 8 only checks for the
existence of an alias and does the expansion later.
It does still do a DNS lookup if there is an explicit host name
in the RCPT command,
but this time is bounded.
.ip \(sc5.2.8
Numeric IP addresses are logged in Received: lines.
This helps tracing spoofed messages.
.ip \(sc5.2.17
Self domain literal is properly handled. Previously,
if someone sent to user@[1.2.3.4], where 1.2.3.4 is
your IP address, the mail would probably be rejected
with a ``configuration error''.
Version 8 can handle these addresses.
.ip \(sc5.3.2
Better control over individual timeouts. RFC 821 specified
no timeouts. Older versions of sendmail had a single
timeout, typically set to two hours. Version 8 allows
the configuration file to set timeouts for various
SMTP commands individually.
.ip \(sc5.3.3
Error messages are sent as From:<>. This was urged by
RFC 821 and reiterated by RFC 1123, but older versions
of sendmail never really did it properly. Version 8
does. However, some systems cannot handle this
perfectly legal address; if necessary, you can create
a special mailer that uses the `g' flag to disable this.
.ip \(sc5.3.3
Error messages are never sent to <>. Previously,
sendmail was happy to send responses-to-responses which
sometimes resulted in responses-to-responses-to-responses
which resulted in .... you get the idea.
.ip \(sc5.3.3
Route-addrs (the ugly ``<@hosta,@hostb:user@hostc>''
syntax) are pruned. RFC 821 urged the use of this
bletcherous syntax. RFC 1123 has seen the light and
officially deprecates them, further urging that you
eliminate all but ``user@hostc'' should you receive
one of these things. Version 8 is slightly more generous
than the standards suggest; instead of stripping off all
the route addressees, it only strips hosts off up to
the one before the last one known to DNS, thus allowing
you to have pseudo-hosts such as foo.BITNET. The `R'
option will turn this off.
.lp
The areas in which sendmail is not ``unconditionally compliant'' are:
.ip \(sc5.2.6
Sendmail does do header munging.
.ip \(sc5.2.10
Sendmail doesn't always use the exact SMTP message
text from RFC 821. This is a rather silly requirement.
.ip \(sc5.3.1.1
Sendmail doesn't guarantee only one connect for each
host on queue runs. Connection caching gives you most
of this, but it does not provide a guarantee.
.ip \(sc5.3.1.1
Sendmail doesn't always provide an adequate limit
on concurrency. That is, there can be several
independent sendmails running at once. My feeling
is that doing an absolute limit would be a mistake
(it might result in lost mail). However, if you use
the XLA contributed software, most of this will be
guaranteed (but I don't guarantee the guarantee).
.sh 2 "Extended SMTP Support
.pp
Version 8 includes both sending and receiving support for Extended
SMTP support as defined by RFC 1425 (basic) and RFC 1427 (SIZE);
and limited support for RFC 1426 (BODY).
The body support is minimal because the
.q 8BITMIME
body type is not currently advertised.
Although such a body type will be accepted,
it will not be correctly converted to 7 bits
if speaking to a non-8-bit-MIME aware SMTP server.
.pp
.i Sendmail
tries to speak ESMTP if you have the `a' flag set
in the flags for the mailer descriptor,
or if the other end advertises the fact that it speaks ESMTP.
This is a non-standard advertisement:
.i sendmail
announces
.q "ESMTP spoken here"
during the initial connection message,
and client sendmails search for this message.
This creates some problems for some PC-based mailers,
which do not understand two-line greeting messages
as required by RFC 821.
.sh 2 "Eight-Bit Clean
.pp
Previous versions of sendmail used the 0200 bit for quoting. This
version avoids that use.
However, you can set option `7' to get seven bit stripping
for compatibility with RFC 821,
which is a 7-bit protocol.
This option says ``strip to 7 bits on input''.
.pp
Individual mailers can still produce seven bit out put using the
`7' mailer flag.
This flag says ``strip to 7 bits on output''.
.sh 2 "User Database"
.pp
The User Database (UDB) is an as-yet experimental attempt to provide
unified large-site name support.
We are installing it at Berkeley;
future versions may show significant modifications.
Briefly, UDB contains a database that is intended to contain
all the per-user information for your workgroup,
such as people's full names, their .plan information,
their outgoing mail name, and their mail drop.
.pp
The user database allows you to map both incoming and outgoing
addresses, much like IDA. However, the interface is still
better with IDA;
in particular, the alias file with incoming/outgoing marks
provides better locality of information.
.sh 2 "Improved BIND Support"
.pp
The BIND support, particularly for MX records, had a number of
annoying ``features'' which have been removed in this release. In
particular, these more tightly bind (pun intended) the name server
to sendmail, so that the name server resolution rules are incorporated
directly into sendmail.
.pp
The major change has been that the $[ ... $] operator didn't fully
qualify names that were in DNS as A or MX records. Version 8 does
this qualification.
.pp
This has proven to be an annoyance in Sun shops,
who often still run without BIND support.
However, it is really critical that this be supported,
since MX records are mandatory.
In SunOS you can choose either MX support or NIS support,
but not both.
This is fixed in Solaris,
and some
.i sendmail
support to allow this in SunOS should be forthcoming in a future release.
.sh 2 "Keyed Files"
.pp
Generalized keyed files is an idea taken directly from IDA sendmail
(albeit with a completely different implementation).
They can be useful on large sites.
.pp
Version 8 includes the following built-in map classes:
.ip dbm
Support for the ndbm(3) library.
.ip hash
Support for the ``Hash'' type from the new Berkeley db(3) library.
this library provides substantially better database support
than ndbm(3),
including in-memory caching,
arbitrarily long keys and values,
and better disk utilization.
.ip btree
Support for the ``B-Tree'' type from the new Berkeley db(3) library.
B-Trees provide better clustering than Hashed files
if you are fetching lots of records that have similar keys,
such as searching a dictionary for words beginning with ``detr''.
.ip nis
Support for NIS (a.k.a. YP) maps.
NIS+ is not supported in this version.
.ip host
Support for DNS lookups.
.ip dequote
A ``pseudo-map'' (that is, once that does not have any external data)
that allows a configuration file to break apart a quoted string
in the address.
This is necessary primarily for DECnet addresses,
which often have quoted addresses that need to be unwrapped on gateways.
.sh 2 "Multi-Word Classes & Macros in Classes"
.pp
Classes can now be multiple words. For example,
.(b
CShofmann.CS.Berkeley.EDU
.)b
allows you to match the entire string ``hofmann.CS.Berkeley.EDU''
using the single construct ``$=S''.
.pp
Class definitions are now allowed to include macros \*- for example:
.(b
Cw$k
.)b
is legal.
.sh 2 "IDENT Protocol Support"
.pp
The IDENT protocol as defined in RFC 1413 [RFC1413] is supported.
However, many systems have a TCP/IP bug that renders this useless,
and the feature must be turned off.
Roughly, if one of these system receives a
.q "No route to host"
message (ICMP message ICMP_UNREACH_HOST) on
.i any
connection, all connections to that host are closed.
Some firewalls return this error if you try to connect
to the IDENT port,
so you can't receive email from these hosts on these systems.
It's possible that if the firewall used a more specific message
(such as ICMP_UNREACH_PROTOCOL, ICMP_UNREACH_PORT or ICMP_UNREACH_NET_PROHIB)
it would work, but this hasn't been verified.
.pp
IDENT protocol support cannot be used on
4.3BSD,
Apollo DomainOS,
Apple A/UX,
ConvexOS,
Data General DG/UX,
HP-UX,
Sequent Dynix,
or
Ultrix 4.x, x \(<= 3.
It seems to work on
4.4BSD,
IBM AIX 3.x,
OSF/1,
SGI IRIX,
Solaris,
SunOS,
and Ultrix 4.4.
.sh 2 "Separate Envelope/Header Processing
.pp
Since the From: line is passed in separately from the envelope
sender, these have both been made visible; the $g macro is set to
the envelope sender during processing of mailer argument vectors
and the header sender during processing of headers.
.pp
It is also possible to specify separate per-mailer envelope and
header processing. The SenderRWSet and RecipientRWset arguments
for mailers can be specified as ``envelope/header'' to give different
rewritings for envelope versus header addresses.
.sh 2 "Owner-List Propagates to Envelope
.pp
When an alias has an associated owner-list name, that alias is used
to change the envelope sender address. This will cause downstream
errors to be returned to that owner.
.pp
Some people find this confusing
because the envelope sender is what appears in the first
``From_'' line in UNIX messages
(that is, the line beginning ``From<space>''
instead of ``From:'';
the latter is the header from, which
.i does
indicate the sender of the message).
In previous versions,
.i sendmail
has tried to avoid changing the envelope sender
for back compatibility with UNIX convention;
at this point that back compatibility is creating too many problems,
and it is necessary to move forward into the 1980s.
.sh 2 "Command Line Flags"
.pp
The
.b \-B
flag has been added to pass in body type information.
.pp
The
.b \-p
flag has been added to pass in protocol information
that was previously passed in by defining the
.b $r
and
.b $s
macros.
.pp
The
.b \-X
flag has been added to allow logging of all protocol in and
out of sendmail for debugging.
You can set
.q "\-X filename"
and a complete transcript will be logged in that file.
This gets big fast: the option is only for debugging.
.pp
The
.b \-q
flag can limit limit a queue run to specific recipients,
senders, or queue ids using \-qRsubstring, \-qSsubstring, or
\-qIsubstring respectively.
.sh 2 "New Configuration Line Types
.pp
The `T' (Trusted users) configuration line has been deleted. It
will still be accepted but will be ignored.
.pp
The `K' line has been added to declare database maps.
.pp
The `V' line has been added to declare the configuration version
level.
.pp
The `M' (mailer) line takes a D= field to specify execution
directory.
.sh 2 "New and Extended Options"
.pp
Several new options have been added, many to support new features,
others to allow tuning that was previously available only by
recompiling. Briefly:
.nr ii 0.5i
.ip A
The alias file specification can now be a list of alias files.
Also, the configuration can specify a class of file.
For example, to search the NIS aliases, use
.q OAnis:mail.aliases .
.ip b
Insist on a minimum number of disk blocks.
.ip C
Delivery checkpoint interval. Checkpoint the queue (to avoid
duplicate deliveries) every C addresses.
.ip E
Default error message. This message (or the contents of the
indicated file) are prepended to error messages.
.ip G
Enable GECOS matching. If you can't find a local user name
and this option is enabled, do a sequential scan of the passwd
file to match against full names. Previously a compile option.
.ip h
Maximum hop count. Previously this was compiled in.
.ip I
This option has been extended to allow setting of resolver parameters.
.ip j
Send errors in MIME-encapsulated format.
.ip J
Forward file path. Where to search for .forward files \*- defaults
to $HOME/.forward.
.ip k
Connection cache size. The total number of connections that will
be kept open at any time.
.ip K
Connection cache lifetime. The amount of time any connection
will be permitted to sit idle.
.ip l
Enable Errors-To: header. These headers violate RFC 1123;
this option is included to provide back compatibility with
old versions of sendmail.
.ip O
Incoming daemon options (e.g., use alternate SMTP port).
.ip p
Privacy options. These can be used to make your SMTP server
less friendly.
.ip r
This option has been extended to allow finer grained control
over timeouts.
For example, you can set the timeout for SMTP commands individually.
.ip R
Don't prune route-addrs. Normally, if version 8 sees an address
like "<@hostA,@hostB:user@hostC>, sendmail will try to strip off
as much as it can (up to user@hostC) as suggested by RFC 1123.
This option disables that behaviour.
.ip T
The
.q "Return To Sender"
timeout has been extended
to allow specification of a warning message interval,
typically something on the order of four hours.
If a message cannot be delivered in that interval,
a warning message is sent back to the sender
but the message continues to be tried.
.ip U
User database spec. This is still experimental.
.ip V
Fallback ``MX'' host. This can be thought of as an MX host
that applies to all addresses that has a very high preference
value (that is, use it only if everything else fails).
.ip w
If set, assume that if you are the best MX host for a host,
you should send directly to that host. This is intended
for compatibility with UIUC sendmail, and may have some
use on firewalls.
.ip 7
Do not run eight bit clean. Technically, you have to assert
this option to be RFC 821 compatible.
.sh 2 "New Mailer Definitions"
.ip L=
Set the allowable line length. In V5, the L mailer flag implied
a line length limit of 990 characters; this is now settable to
an arbitrary value.
.ip F=a
Try to use ESMTP. It will fall back to SMTP if the initial
EHLO packet is rejected.
.ip F=b
Ensure a blank line at the end of messages. Useful on the
*file* mailer.
.ip F=c
Strip all comments from addresses; this should only be used as
a last resort when dealing with cranky mailers.
.ip F=g
Never use the null sender as the envelope sender, even when
running SMTP. This violates RFC 1123.
.ip F=7
Strip all output to this mailer to 7 bits.
.ip F=L
Used to set the line limit to 990 bytes for SMTP compatibility.
It now does that only if the L= keyletter is not specified.
This flag is obsolete and should not be used.
.sh 2 "New or Changed Pre-Defined Macros"
.ip $k
UUCP node name from uname(2).
.ip $m
Domain part of our full hostname.
.ip $_
RFC 1413-provided sender address.
.ip $w
Previously was sometimes the full domain name, sometimes
just the first word. Now guaranteed to be the first word
of the domain name (i.e., the host name).
.ip $j
Previously had to be defined \*- it is now predefined to be
the full domain name, if that can be determined. That is,
it is equivalent to $w.$m.
.sh 2 "New and Changed Classes"
.ip $=k
Initialized to contain $k.
.ip $=w
Now includes
.q [1.2.3.4]
(where 1.2.3.4 is your IP address)
to allow the configuration file to recognize your own IP address.
.sh 2 "New Rewriting Tokens"
.pp
The
.b $&
construct has been adopted from IDA to defer macro evaluation.
Normally, macros in rulesets are bound when the rule is first parsed
during startup.
Some macros change during processing and are uninteresting during startup.
However, that macro can be referenced using
.q $&x
to defer the evaulation of
$x
until the rule is processed.
.pp
The tokens
.b $(
and
.b $)
have been added to allow specification of map rewriting.
.pp
Version 8 allows
.b $@
on the Left Hand Side of an `R' line to match
zero tokens.
This is intended to be used to match the null input.
.sh 2 "Bigger Defaults
.pp
Version 8 allows up to 100 rulesets instead of 30. It is recommended
that rulesets 0\-9 be reserved for sendmail's dedicated use in future
releases.
.pp
The total number of MX records that can be used has been raised to
20.
.pp
The number of queued messages that can be handled at one time has
been raised from 600 to 1000.
.sh 2 "Different Default Tuning Parameters
.pp
Version 8 has changed the default parameters for tuning queue costs
to make the number of recipients more important than the size of
the message (for small messages). This is reasonable if you are
connected with reasonably fast links.
.sh 2 "Auto-Quoting in Addresses
.pp
Previously, the ``Full Name <email address>'' syntax would generate
incorrect protocol output if ``Full Name'' had special characters
such as dot. This version puts quotes around such names.
.sh 2 "Symbolic Names On Error Mailer
.pp
Several names have been built in to the $@ portion of the $#error
mailer. For example:
.(b
$#error $@NOHOST $: Host unknown
.)b
Prints the indicated message
and sets the exit status of
.i sendmail
to
.sm EX_NOHOST .
.sh 2 "New Built-In Mailers"
.pp
Two new mailers, *file* and *include*, are included to define options
when mailing to a file or a :include: file respectively. Previously
these were overloaded on the local mailer.
.sh 2 "SMTP VRFY Doesn't Expand
.pp
Previous versions of sendmail treated VRFY and EXPN the same. In
this version, VRFY doesn't expand aliases or follow .forward files.
.pp
As an optimization, if you run with your default delivery mode
being queue-only, the RCPT command will also not chase aliases and
\&.forward files.
It will chase them when it processes the queue.
This speeds up RCPT processing.
.sh 2 "[IPC] Mailers Allow Multiple Hosts
.pp
When an address resolves to a mailer that has ``[IPC]'' as its
``Path'', the $@ part (host name) can be a colon-separated list of
hosts instead of a single hostname. This asks sendmail to search
the list for the first entry that is available exactly as though
it were an MX record. The intent is to route internal traffic
through internal networks without publishing an MX record to the
net. MX expansion is still done on the individual items.
.sh 2 "Aliases Extended"
.pp
The implementation has been merged with maps. Among other things,
this supports multiple alias files and NIS-based aliases. For
example:
.(b
OA/etc/aliases,nis:mail.aliases
.)b
will search first the local database
.q /etc/aliases
followed by the NIS map
.sh 2 "Portability and Security Enhancements
.pp
A number of internal changes have been made to enhance portability.
.pp
Several fixes have been made to increase the paranoia factor.
.pp
In particular, the permissions required for .forward and :include:
files have been tightened up considerably. V5 would pretty much
read any file it could get to as root, which exposed some security
holes. V8 insists that all directories leading up to the .forward
or :include: file be searchable ("x" permission) by the controlling
user" (defined below), that the file itself be readable by the
controlling user, and that .forward files be owned by the user
who is being forwarded to or root.
.pp
The "controlling user" is the user on whose behalf the mail is
being delivered. For example, if you mail to "user1" then the
controlling user for ~user1/.forward and any mailers invoked
by that .forward file, including :include: files.
.pp
Previously, anyone who had a home directory could create a .forward
could forward to a program. Now, sendmail checks to make sure
that they have an "approved shell", that is, a shell listed in
the /etc/shells file.
.sh 2 "Miscellaneous Fixes and Enhancements"
.pp
A number of small bugs having to do with things like backslash-escaped
quotes inside of comments have been fixed.
.pp
The fixed size limit on header lines
(such as
.q To:
and
.q Cc: )
has been eliminated;
those buffers are dynamically allocated now.
.pp
Sendmail writes a /etc/sendmail.pid file with the current process id
and the current invocation flags.
.pp
Two people using the same program (e.g., submit) are considered
"different" so that duplicate elimination doesn't delete one of
them. For example, two people forwarding their email to
|submit will be treated as two recipients.
.pp
The mailstats program prints mailer names and gets the location of
the sendmail.st file from /etc/sendmail.cf.
.pp
Many minor bugs have been fixed, such as handling of backslashes
inside of quotes.
.pp
A hook has been added to allow rewriting of local addresses after
aliasing.
.sh 1 "FUTURE WORK"
.pp
The previous section describes
.i sendmail
as of version 8.6.6.
There is still much to be done.
Some high points are described below.
This list is by no means exhaustive.
.sh 2 "Full MIME Support"
.pp
Currently
.i sendmail
only supports seven bit MIME messages.
Although it can pass eight bit MIME messages,
it cannot advertise that fact because the standards say
that the mail agent must be able to do 8- to 7-bit conversion
to have full 8-bit support.
This requires far more extensive modification of the message body
than is currently supported.
.pp
The best way to do this would be to support the general concept
of an external
``message filter''
that could do arbitrary modifications of the message.
This would allow MIME conversion as well as such things as
automatic encryption of messages sent over external links.
This is probably an extremely non-trivial change.
.sh 2 "Service Switch Abstraction"
.pp
Most modern systems include some concept of a
.q "service switch"
\*- for example, to look up host names you can try
DNS, NIS, NIS+, text tables, NetInfo,
or other services in some arbitrary order.
This is currently very clumsy in
.i sendmail ,
with only limited control of the services provided.
.sh 2 "More Control of Local Addresses"
.pp
Currently some addresses are declared as
.q local
and are handled specially \*-
for example, they may have .forward files,
may be translated into program calls or file deliveries,
and so forth.
These should be broken out into separate flags
to allow the local system administrator
to have more fine-grained control over operations.
.sh 2 "More Run-Time Configuration Options"
.pp
There are many options that are configured at compile time,
such as the method of file locking
and the use of the IDENT protocol
[RFC1413].
These should be transfered to run time
by adding new options.
.pp
Similarly, some options are currently overloaded,
that is, a single option controls more than one thing.
These should probably be broken out into separate options.
.pp
This implies that options will change from single characters
to words.
.sh 2 "More Configuration Control Over Errors"
.pp
Currently,
the configuration file can generate an error message during parsing.
However,
it cannot tweak other operations,
such as issuing a warning message to the system postmaster.
Similarly,
some errors should not be triggered if they are in aliases
during an alias file rebuild,
but should be triggered if that alias is actually used.
.sh 2 "Long Term Host State"
.pp
Currently,
.i sendmail
only remembers host status during a single queue run.
This should be converted to long term status
stored on disk
so it can be shared between instantiations of
.i sendmail .
Entries will have to be timestamped
so they can time out.
This will allow
.i sendmail
to implement exponential backoff on queue runs
on a per-host basis.
.sh 2 "Connection Control"
.pp
Modern networks have different types of connectivity
than the past.
In particular, the rising prominence of dialup IP
has created certain challenges for automated servers.
It is not uncommon to try to make a connection to a host
and have it fail, even though if you tried again it would succeed.
The connection management could be a bit cleverer
to try to adapt to such situations.
.sh 2 "Other Caching"
.pp
When you do an MX record lookup,
the name server automatically returns the IP addresses
of the associated MX servers.
This information is currently ignored,
and another query is done to get this information.
It should be cached to avoid excess name server traffic.
.sh 1 "REFERENCES"
.ip [Allman83a]
.q "Sendmail \*- An Internetwork Mail Router."
E. Allman.
In
.ul
Unix Programmers's Manual,
4.2 Berkeley Software Distribution,
volume 2C.
August 1983.
.ip [Allman83b]
.q "Mail Systems and Addressing in 4.2BSD."
E. Allman
In
.ul
UNICOM Conference Proceedings.
San Diego, California.
January 1983.
.ip [Allman&Amos85]
``Sendmail Revisited.''
E. Allman and M. Amos.
In
.ul
Usenix Summer 1985 Conference Proceedings.
Portland, Oregon.
June 1985.
.ip [IDA87]
.ul 3
Electronic Mail Addressing in Theory and Practice
with the IDA Sendmail Enhancement Kit
(or The Postmaster's Last Will and Testament).
Lennart Lo\*:vstrand.
Department of Computer and Information Science,
University of Linko\*:ping,
Sweden,
Report no. LiTH-IDA-Ex-8715.
May 1987.
.ip [RFC821]
.ul
Simple Mail Transport Protocol.
J. Postel.
August 1982.
.ip [RFC1123]
.ul
Requirements for Internet Hosts \*- Application and Support.
Internet Engineering Task Force,
R. Braden, Editor.
October 1989.
.ip [RFC1344]
.ul
Implications of MIME for Internet Mail Gateways.
N. Borenstein.
June 1992.
.ip [RFC1413]
.ul
Identification Protocol.
M. St. Johns.
February 1993.
.ip [RFC1425]
.ul
SMTP Service Extensions.
J. Klensin, N. Freed, M. Rose, E. Stefferud, and D. Crocker.
February 1993.
.ip [RFC1426]
.ul
SMTP Service Extension for 8bit-MIMEtransport.
J. Klensin, N. Freed, M. Rose, E. Stefferud, and D. Crocker.
February 1993.
.ip [RFC1427]
.ul
SMTP Service Extension for Message Size Declaration.
J. Klensin, N. Freed, and K. Moore.
February 1993.
.ip [RFC1521]
.ul 3
MIME (Multipurpose Internet Mail Extensions) Part One:
Mechanisms for Specifying and Describing
the Format of Internet Message Bodies.
N. Borenstein and N. Freed.
September 1993.

View File

@ -1,13 +0,0 @@
# @(#)Makefile 8.2 (Berkeley) 2/28/1994
DIR= smm/09.sendmail
SRCS= intro.me
MACROS= -me
all: intro.ps
intro.ps: ${SRCS}
rm -f ${.TARGET}
${PIC} ${SRCS} | ${ROFF} > ${.TARGET}
.include <bsd.doc.mk>

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
# @(#)Makefile 8.2 (Berkeley) 2/28/1994
SRCS= usenix.me
MACROS= -me
all: usenix.ps
usenix.ps: ${SRCS}
rm -f ${.TARGET}
${PIC} ${SRCS} | ${ROFF} > ${.TARGET}
.include <bsd.doc.mk>

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +0,0 @@
/*-
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*
* @(#)pathnames.h 8.5 (Berkeley) 5/19/1998
* $FreeBSD$
*/
#include <paths.h>
#define _PATH_LOCTMP "/var/tmp/local.XXXXXX"

View File

@ -1,123 +0,0 @@
/*
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Berkeley Software Design, Inc.
*
* 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.
*
* @(#)cdefs.h 8.8 (Berkeley) 1/9/95
*/
#ifndef _CDEFS_H_
#define _CDEFS_H_
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS };
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
/*
* The __CONCAT macro is used to concatenate parts of symbol names, e.g.
* with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
* The __CONCAT macro is a bit tricky -- make sure you don't put spaces
* in between its arguments. __CONCAT can also concatenate double-quoted
* strings produced by the __STRING macro, but this only works with ANSI C.
*/
#if defined(__STDC__) || defined(__cplusplus)
#define __P(protos) protos /* full-blown ANSI C */
#define __CONCAT(x,y) x ## y
#define __STRING(x) #x
#define __const const /* define reserved names to standard */
#define __signed signed
#define __volatile volatile
#if defined(__cplusplus)
#define __inline inline /* convert to C++ keyword */
#else
#ifndef __GNUC__
#define __inline /* delete GCC keyword */
#endif /* !__GNUC__ */
#endif /* !__cplusplus */
#else /* !(__STDC__ || __cplusplus) */
#define __P(protos) () /* traditional C preprocessor */
#define __CONCAT(x,y) x/**/y
#define __STRING(x) "x"
#ifndef __GNUC__
#define __const /* delete pseudo-ANSI C keywords */
#define __inline
#define __signed
#define __volatile
/*
* In non-ANSI C environments, new programs will want ANSI-only C keywords
* deleted from the program and old programs will want them left alone.
* When using a compiler other than gcc, programs using the ANSI C keywords
* const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
* When using "gcc -traditional", we assume that this is the intent; if
* __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
*/
#ifndef NO_ANSI_KEYWORDS
#define const /* delete ANSI C keywords */
#define inline
#define signed
#define volatile
#endif
#endif /* !__GNUC__ */
#endif /* !(__STDC__ || __cplusplus) */
/*
* GCC1 and some versions of GCC2 declare dead (non-returning) and
* pure (no side effects) functions using "volatile" and "const";
* unfortunately, these then cause warnings under "-ansi -pedantic".
* GCC2 uses a new, peculiar __attribute__((attrs)) style. All of
* these work for GNU C++ (modulo a slight glitch in the C++ grammar
* in the distribution version of 2.5.5).
*/
#if !defined(__GNUC__) || __GNUC__ < 2 || \
(__GNUC__ == 2 && __GNUC_MINOR__ < 5)
#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define __dead __volatile
#define __pure __const
#endif
#endif
/* Delete pseudo-keywords wherever they are not available or needed. */
#ifndef __dead
#define __dead
#define __pure
#endif
#endif /* !_CDEFS_H_ */

View File

@ -1,91 +0,0 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
/*
** Support for LDAP.
**
** Contributed by Booker C. Bense <bbense+ldap@stanford.edu>.
** Please go to him for support -- since I (Eric) don't run LDAP, I
** can't help you at all.
**
** @(#)ldap_map.h 8.12 (Berkeley) 2/2/1999
*/
#ifndef _LDAP_MAP_H
#define _LDAP_MAP_H
#include <sys/time.h>
struct ldap_map_struct
{
/* needed for ldap_open */
char *ldaphost;
int ldapport;
/* Options set in ld struct before ldap_bind_s */
int deref;
int timelimit;
int sizelimit;
int ldap_options;
/* args for ldap_bind_s */
LDAP *ld;
char *binddn;
char *passwd;
int method;
/* args for ldap_search_st */
char *base;
int scope;
char *filter;
char *attr[2];
int attrsonly;
struct timeval timeout;
LDAPMessage *res;
};
typedef struct ldap_map_struct LDAP_MAP_STRUCT;
#define DEFAULT_LDAP_MAP_PORT LDAP_PORT
#define DEFAULT_LDAP_MAP_SCOPE LDAP_SCOPE_SUBTREE
#define DEFAULT_LDAP_MAP_BINDDN NULL
#define DEFAULT_LDAP_MAP_PASSWD NULL
#define DEFAULT_LDAP_MAP_METHOD LDAP_AUTH_SIMPLE
#define DEFAULT_LDAP_MAP_TIMELIMIT 5
#define DEFAULT_LDAP_MAP_DEREF LDAP_DEREF_NEVER
#define DEFAULT_LDAP_MAP_SIZELIMIT 0
#define DEFAULT_LDAP_MAP_ATTRSONLY 0
#define LDAP_MAP_MAX_FILTER 1024
#ifdef LDAP_REFERRALS
# define DEFAULT_LDAP_MAP_LDAP_OPTIONS LDAP_OPT_REFERRALS
#else /* LDAP_REFERRALS */
# define DEFAULT_LDAP_MAP_LDAP_OPTIONS 0
#endif /* LDAP_REFERRALS */
/*
** ldap_init(3) is broken in Umich 3.x and OpenLDAP 1.0/1.1.
** Use the lack of LDAP_OPT_SIZELIMIT to detect old API implementations
** and assume (falsely) that all old API implementations are broken.
** (OpenLDAP 1.2 and later have a working ldap_init(), add -DUSE_LDAP_INIT)
*/
#if defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_INIT)
# define USE_LDAP_INIT 1
#endif
/*
** LDAP_OPT_SIZELIMIT is not defined under Umich 3.x nor OpenLDAP 1.x,
** hence ldap_set_option() must not exist.
*/
#if defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_SET_OPTION)
# define USE_LDAP_SET_OPTION 1
#endif
#endif /* _LDAP_MAP_H */

View File

@ -1,34 +0,0 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1983 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*
* @(#)mailstats.h 8.8 (Berkeley) 5/19/1998
*/
#define STAT_VERSION 2
#define STAT_MAGIC 0x1B1DE
/*
** Statistics structure.
*/
struct statistics
{
int stat_magic; /* magic number */
int stat_version; /* stat file version */
time_t stat_itime; /* file initialization time */
short stat_size; /* size of this structure */
long stat_nf[MAXMAILERS]; /* # msgs from each mailer */
long stat_bf[MAXMAILERS]; /* kbytes from each mailer */
long stat_nt[MAXMAILERS]; /* # msgs to each mailer */
long stat_bt[MAXMAILERS]; /* kbytes to each mailer */
long stat_nr[MAXMAILERS]; /* # rejects by each mailer */
long stat_nd[MAXMAILERS]; /* # discards by each mailer */
};

View File

@ -1,32 +0,0 @@
/*-
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*
* @(#)pathnames.h 8.8 (Berkeley) 5/19/1998
*/
#ifndef _PATH_SENDMAILCF
# if defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF)
# define _PATH_SENDMAILCF _PATH_VENDOR_CF
# else
# define _PATH_SENDMAILCF "/etc/sendmail.cf"
# endif
#endif
#ifndef _PATH_SENDMAILPID
# ifdef BSD4_4
# define _PATH_SENDMAILPID "/var/run/sendmail.pid"
# else
# define _PATH_SENDMAILPID "/etc/sendmail.pid"
# endif
#endif
#ifndef _PATH_HOSTS
# define _PATH_HOSTS "/etc/hosts"
#endif

View File

@ -1,751 +0,0 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
#ifndef lint
static char sccsid[] = "@(#)safefile.c 8.43 (Berkeley) 10/13/1998";
#endif /* not lint */
# include "sendmail.h"
/*
** SAFEFILE -- return true if a file exists and is safe for a user.
**
** Parameters:
** fn -- filename to check.
** uid -- user id to compare against.
** gid -- group id to compare against.
** uname -- user name to compare against (used for group
** sets).
** flags -- modifiers:
** SFF_MUSTOWN -- "uid" must own this file.
** SFF_NOSLINK -- file cannot be a symbolic link.
** mode -- mode bits that must match.
** st -- if set, points to a stat structure that will
** get the stat info for the file.
**
** Returns:
** 0 if fn exists, is owned by uid, and matches mode.
** An errno otherwise. The actual errno is cleared.
**
** Side Effects:
** none.
*/
#include <grp.h>
int
safefile(fn, uid, gid, uname, flags, mode, st)
char *fn;
UID_T uid;
GID_T gid;
char *uname;
int flags;
int mode;
struct stat *st;
{
register char *p;
register struct group *gr = NULL;
int file_errno = 0;
bool checkpath;
struct stat stbuf;
struct stat fstbuf;
char fbuf[MAXPATHLEN + 1];
if (tTd(44, 4))
printf("safefile(%s, uid=%d, gid=%d, flags=%x, mode=%o):\n",
fn, (int) uid, (int) gid, flags, mode);
errno = 0;
if (st == NULL)
st = &fstbuf;
if (strlen(fn) > sizeof fbuf - 1)
{
if (tTd(44, 4))
printf("\tpathname too long\n");
return ENAMETOOLONG;
}
strcpy(fbuf, fn);
fn = fbuf;
/* ignore SFF_SAFEDIRPATH if we are debugging */
if (RealUid != 0 && RunAsUid == RealUid)
flags &= ~SFF_SAFEDIRPATH;
/* first check to see if the file exists at all */
#ifdef HASLSTAT
if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, st)
: stat(fn, st)) < 0)
#else
if (stat(fn, st) < 0)
#endif
{
file_errno = errno;
}
else if (bitset(SFF_SETUIDOK, flags) &&
!bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode) &&
S_ISREG(st->st_mode))
{
/*
** If final file is setuid, run as the owner of that
** file. Gotta be careful not to reveal anything too
** soon here!
*/
#ifdef SUID_ROOT_FILES_OK
if (bitset(S_ISUID, st->st_mode))
#else
if (bitset(S_ISUID, st->st_mode) && st->st_uid != 0 &&
st->st_uid != TrustedUid)
#endif
{
uid = st->st_uid;
uname = NULL;
}
#ifdef SUID_ROOT_FILES_OK
if (bitset(S_ISGID, st->st_mode))
#else
if (bitset(S_ISGID, st->st_mode) && st->st_gid != 0)
#endif
gid = st->st_gid;
}
checkpath = !bitset(SFF_NOPATHCHECK, flags) ||
(uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags));
if (bitset(SFF_NOWLINK, flags) && !bitset(SFF_SAFEDIRPATH, flags))
{
int ret;
/* check the directory */
p = strrchr(fn, '/');
if (p == NULL)
{
ret = safedirpath(".", uid, gid, uname, flags|SFF_SAFEDIRPATH);
}
else
{
*p = '\0';
ret = safedirpath(fn, uid, gid, uname, flags|SFF_SAFEDIRPATH);
*p = '/';
}
if (ret == 0)
{
/* directory is safe */
checkpath = FALSE;
}
else
{
#ifdef HASLSTAT
/* Need lstat() information if called stat() before */
if (!bitset(SFF_NOSLINK, flags) && lstat(fn, st) < 0)
{
ret = errno;
if (tTd(44, 4))
printf("\t%s\n", errstring(ret));
return ret;
}
#endif
/* directory is writable: disallow links */
flags |= SFF_NOLINK;
}
}
if (checkpath)
{
int ret;
p = strrchr(fn, '/');
if (p == NULL)
{
ret = safedirpath(".", uid, gid, uname, flags);
}
else
{
*p = '\0';
ret = safedirpath(fn, uid, gid, uname, flags);
*p = '/';
}
if (ret != 0)
return ret;
}
/*
** If the target file doesn't exist, check the directory to
** ensure that it is writable by this user.
*/
if (file_errno != 0)
{
int ret = file_errno;
char *dir = fn;
if (tTd(44, 4))
printf("\t%s\n", errstring(ret));
errno = 0;
if (!bitset(SFF_CREAT, flags) || file_errno != ENOENT)
return ret;
/* check to see if legal to create the file */
p = strrchr(dir, '/');
if (p == NULL)
dir = ".";
else if (p == dir)
dir = "/";
else
*p = '\0';
if (stat(dir, &stbuf) >= 0)
{
int md = S_IWRITE|S_IEXEC;
if (stbuf.st_uid == uid)
;
else if (uid == 0 && stbuf.st_uid == TrustedUid)
;
else
{
md >>= 3;
if (stbuf.st_gid == gid)
;
#ifndef NO_GROUP_SET
else if (uname != NULL && !DontInitGroups &&
((gr != NULL &&
gr->gr_gid == stbuf.st_gid) ||
(gr = getgrgid(stbuf.st_gid)) != NULL))
{
register char **gp;
for (gp = gr->gr_mem; *gp != NULL; gp++)
if (strcmp(*gp, uname) == 0)
break;
if (*gp == NULL)
md >>= 3;
}
#endif
else
md >>= 3;
}
if ((stbuf.st_mode & md) != md)
errno = EACCES;
}
ret = errno;
if (tTd(44, 4))
printf("\t[final dir %s uid %d mode %lo] %s\n",
dir, (int) stbuf.st_uid, (u_long) stbuf.st_mode,
errstring(ret));
if (p != NULL)
*p = '/';
st->st_mode = ST_MODE_NOFILE;
return ret;
}
#ifdef S_ISLNK
if (bitset(SFF_NOSLINK, flags) && S_ISLNK(st->st_mode))
{
if (tTd(44, 4))
printf("\t[slink mode %lo]\tE_SM_NOSLINK\n",
(u_long) st->st_mode);
return E_SM_NOSLINK;
}
#endif
if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode))
{
if (tTd(44, 4))
printf("\t[non-reg mode %lo]\tE_SM_REGONLY\n",
(u_long) st->st_mode);
return E_SM_REGONLY;
}
if (bitset(SFF_NOGWFILES, flags) &&
bitset(S_IWGRP, st->st_mode))
{
if (tTd(44, 4))
printf("\t[write bits %lo]\tE_SM_GWFILE\n",
(u_long) st->st_mode);
return E_SM_GWFILE;
}
if (bitset(SFF_NOWWFILES, flags) &&
bitset(S_IWOTH, st->st_mode))
{
if (tTd(44, 4))
printf("\t[write bits %lo]\tE_SM_WWFILE\n",
(u_long) st->st_mode);
return E_SM_WWFILE;
}
if (bitset(S_IWUSR|S_IWGRP|S_IWOTH, mode) &&
bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode))
{
if (tTd(44, 4))
printf("\t[exec bits %lo]\tE_SM_ISEXEC]\n",
(u_long) st->st_mode);
return E_SM_ISEXEC;
}
if (bitset(SFF_NOHLINK, flags) && st->st_nlink != 1)
{
if (tTd(44, 4))
printf("\t[link count %d]\tE_SM_NOHLINK\n",
(int) st->st_nlink);
return E_SM_NOHLINK;
}
if (uid == 0 && bitset(SFF_OPENASROOT, flags))
;
else if (uid == 0 && !bitset(SFF_ROOTOK, flags))
mode >>= 6;
else if (st->st_uid == uid)
;
else if (uid == 0 && st->st_uid == TrustedUid)
;
else
{
mode >>= 3;
if (st->st_gid == gid)
;
#ifndef NO_GROUP_SET
else if (uname != NULL && !DontInitGroups &&
((gr != NULL && gr->gr_gid == st->st_gid) ||
(gr = getgrgid(st->st_gid)) != NULL))
{
register char **gp;
for (gp = gr->gr_mem; *gp != NULL; gp++)
if (strcmp(*gp, uname) == 0)
break;
if (*gp == NULL)
mode >>= 3;
}
#endif
else
mode >>= 3;
}
if (tTd(44, 4))
printf("\t[uid %d, nlink %d, stat %lo, mode %lo] ",
(int) st->st_uid, (int) st->st_nlink,
(u_long) st->st_mode, (u_long) mode);
if ((st->st_uid == uid || st->st_uid == 0 ||
st->st_uid == TrustedUid ||
!bitset(SFF_MUSTOWN, flags)) &&
(st->st_mode & mode) == mode)
{
if (tTd(44, 4))
printf("\tOK\n");
return 0;
}
if (tTd(44, 4))
printf("\tEACCES\n");
return EACCES;
}
/*
** SAFEDIRPATH -- check to make sure a path to a directory is safe
**
** Safe means not writable and owned by the right folks.
**
** Parameters:
** fn -- filename to check.
** uid -- user id to compare against.
** gid -- group id to compare against.
** uname -- user name to compare against (used for group
** sets).
** flags -- modifiers:
** SFF_ROOTOK -- ok to use root permissions to open.
** SFF_SAFEDIRPATH -- writable directories are considered
** to be fatal errors.
**
** Returns:
** 0 -- if the directory path is "safe".
** else -- an error number associated with the path.
*/
int
safedirpath(fn, uid, gid, uname, flags)
char *fn;
UID_T uid;
GID_T gid;
char *uname;
int flags;
{
char *p;
register struct group *gr = NULL;
int ret = 0;
int mode = S_IWOTH;
struct stat stbuf;
/* special case root directory */
if (*fn == '\0')
fn = "/";
if (tTd(44, 4))
printf("safedirpath(%s, uid=%ld, gid=%ld, flags=%x):\n",
fn, (long) uid, (long) gid, flags);
if (!bitset(DBS_GROUPWRITABLEDIRPATHSAFE, DontBlameSendmail))
mode |= S_IWGRP;
p = fn;
do
{
if (*p == '\0')
*p = '/';
p = strchr(++p, '/');
if (p != NULL)
*p = '\0';
if (stat(fn, &stbuf) < 0)
{
ret = errno;
break;
}
if ((uid == 0 || bitset(SFF_SAFEDIRPATH, flags)) &&
bitset(mode, stbuf.st_mode))
{
if (tTd(44, 4))
printf("\t[dir %s] mode %lo\n",
fn, (u_long) stbuf.st_mode);
if (bitset(SFF_SAFEDIRPATH, flags))
{
if (bitset(S_IWOTH, stbuf.st_mode))
ret = E_SM_WWDIR;
else
ret = E_SM_GWDIR;
break;
}
if (Verbose > 1)
message("051 WARNING: %s writable directory %s",
bitset(S_IWOTH, stbuf.st_mode)
? "World"
: "Group",
fn);
}
if (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags))
{
if (bitset(S_IXOTH, stbuf.st_mode))
continue;
ret = EACCES;
break;
}
/*
** Let OS determine access to file if we are not
** running as a privileged user. This allows ACLs
** to work.
*/
if (geteuid() != 0)
continue;
if (stbuf.st_uid == uid &&
bitset(S_IXUSR, stbuf.st_mode))
continue;
if (stbuf.st_gid == gid &&
bitset(S_IXGRP, stbuf.st_mode))
continue;
#ifndef NO_GROUP_SET
if (uname != NULL && !DontInitGroups &&
((gr != NULL && gr->gr_gid == stbuf.st_gid) ||
(gr = getgrgid(stbuf.st_gid)) != NULL))
{
register char **gp;
for (gp = gr->gr_mem; gp != NULL && *gp != NULL; gp++)
if (strcmp(*gp, uname) == 0)
break;
if (gp != NULL && *gp != NULL &&
bitset(S_IXGRP, stbuf.st_mode))
continue;
}
#endif
if (!bitset(S_IXOTH, stbuf.st_mode))
{
ret = EACCES;
break;
}
} while (p != NULL);
if (ret != 0 && tTd(44, 4))
printf("\t[dir %s] %s\n", fn, errstring(ret));
if (p != NULL)
*p = '/';
return ret;
}
/*
** SAFEOPEN -- do a file open with extra checking
**
** Parameters:
** fn -- the file name to open.
** omode -- the open-style mode flags.
** cmode -- the create-style mode flags.
** sff -- safefile flags.
**
** Returns:
** Same as open.
*/
#ifndef O_ACCMODE
# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
#endif
int
safeopen(fn, omode, cmode, sff)
char *fn;
int omode;
int cmode;
int sff;
{
int rval;
int fd;
int smode;
struct stat stb;
if (bitset(O_CREAT, omode))
sff |= SFF_CREAT;
omode &= ~O_CREAT;
smode = 0;
switch (omode & O_ACCMODE)
{
case O_RDONLY:
smode = S_IREAD;
break;
case O_WRONLY:
smode = S_IWRITE;
break;
case O_RDWR:
smode = S_IREAD|S_IWRITE;
break;
default:
smode = 0;
break;
}
if (bitset(SFF_OPENASROOT, sff))
rval = safefile(fn, RunAsUid, RunAsGid, RunAsUserName,
sff, smode, &stb);
else
rval = safefile(fn, RealUid, RealGid, RealUserName,
sff, smode, &stb);
if (rval != 0)
{
errno = rval;
return -1;
}
if (stb.st_mode == ST_MODE_NOFILE && bitset(SFF_CREAT, sff))
omode |= O_EXCL|O_CREAT;
fd = dfopen(fn, omode, cmode, sff);
if (fd < 0)
return fd;
if (filechanged(fn, fd, &stb))
{
syserr("554 cannot open: file %s changed after open", fn);
close(fd);
errno = E_SM_FILECHANGE;
return -1;
}
return fd;
}
/*
** SAFEFOPEN -- do a file open with extra checking
**
** Parameters:
** fn -- the file name to open.
** omode -- the open-style mode flags.
** cmode -- the create-style mode flags.
** sff -- safefile flags.
**
** Returns:
** Same as fopen.
*/
FILE *
safefopen(fn, omode, cmode, sff)
char *fn;
int omode;
int cmode;
int sff;
{
int fd;
FILE *fp;
char *fmode;
switch (omode & O_ACCMODE)
{
case O_RDONLY:
fmode = "r";
break;
case O_WRONLY:
if (bitset(O_APPEND, omode))
fmode = "a";
else
fmode = "w";
break;
case O_RDWR:
if (bitset(O_TRUNC, omode))
fmode = "w+";
else if (bitset(O_APPEND, omode))
fmode = "a+";
else
fmode = "r+";
break;
default:
syserr("safefopen: unknown omode %o", omode);
fmode = "x";
}
fd = safeopen(fn, omode, cmode, sff);
if (fd < 0)
{
if (tTd(44, 10))
printf("safefopen: safeopen failed: %s\n",
errstring(errno));
return NULL;
}
fp = fdopen(fd, fmode);
if (fp != NULL)
return fp;
if (tTd(44, 10))
{
printf("safefopen: fdopen(%s, %s) failed: omode=%x, sff=%x, err=%s\n",
fn, fmode, omode, sff, errstring(errno));
#ifndef NOT_SENDMAIL
dumpfd(fd, TRUE, FALSE);
#endif
}
(void) close(fd);
return NULL;
}
/*
** FILECHANGED -- check to see if file changed after being opened
**
** Parameters:
** fn -- pathname of file to check.
** fd -- file descriptor to check.
** stb -- stat structure from before open.
**
** Returns:
** TRUE -- if a problem was detected.
** FALSE -- if this file is still the same.
*/
bool
filechanged(fn, fd, stb)
char *fn;
int fd;
struct stat *stb;
{
struct stat sta;
if (stb->st_mode == ST_MODE_NOFILE)
{
#if HASLSTAT && BOGUS_O_EXCL
/* only necessary if exclusive open follows symbolic links */
if (lstat(fn, stb) < 0 || stb->st_nlink != 1)
return TRUE;
#else
return FALSE;
#endif
}
if (fstat(fd, &sta) < 0)
return TRUE;
if (sta.st_nlink != stb->st_nlink ||
sta.st_dev != stb->st_dev ||
sta.st_ino != stb->st_ino ||
#if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */
sta.st_gen != stb->st_gen ||
#endif
sta.st_uid != stb->st_uid ||
sta.st_gid != stb->st_gid)
{
if (tTd(44, 8))
{
printf("File changed after opening:\n");
printf(" nlink = %ld/%ld\n",
(long) stb->st_nlink, (long) sta.st_nlink);
printf(" dev = %ld/%ld\n",
(long) stb->st_dev, (long) sta.st_dev);
if (sizeof sta.st_ino > sizeof (long))
{
printf(" ino = %s/",
quad_to_string(stb->st_ino));
printf("%s\n",
quad_to_string(sta.st_ino));
}
else
printf(" ino = %lu/%lu\n",
(unsigned long) stb->st_ino,
(unsigned long) sta.st_ino);
#if HAS_ST_GEN
printf(" gen = %ld/%ld\n",
(long) stb->st_gen, (long) sta.st_gen);
#endif
printf(" uid = %ld/%ld\n",
(long) stb->st_uid, (long) sta.st_uid);
printf(" gid = %ld/%ld\n",
(long) stb->st_gid, (long) sta.st_gid);
}
return TRUE;
}
return FALSE;
}
/*
** DFOPEN -- determined file open
**
** This routine has the semantics of open, except that it will
** keep trying a few times to make this happen. The idea is that
** on very loaded systems, we may run out of resources (inodes,
** whatever), so this tries to get around it.
*/
int
dfopen(filename, omode, cmode, sff)
char *filename;
int omode;
int cmode;
int sff;
{
register int tries;
int fd;
struct stat st;
for (tries = 0; tries < 10; tries++)
{
sleep((unsigned) (10 * tries));
errno = 0;
fd = open(filename, omode, cmode);
if (fd >= 0)
break;
switch (errno)
{
case ENFILE: /* system file table full */
case EINTR: /* interrupted syscall */
#ifdef ETXTBSY
case ETXTBSY: /* Apollo: net file locked */
#endif
continue;
}
break;
}
if (!bitset(SFF_NOLOCK, sff) &&
fd >= 0 &&
fstat(fd, &st) >= 0 &&
S_ISREG(st.st_mode))
{
int locktype;
/* lock the file to avoid accidental conflicts */
if ((omode & O_ACCMODE) != O_RDONLY)
locktype = LOCK_EX;
else
locktype = LOCK_SH;
(void) lockfile(fd, filename, NULL, locktype);
errno = 0;
}
return fd;
}

View File

@ -1,124 +0,0 @@
cpyr
cpyr Copyright (c) 1998 Sendmail, Inc. All rights reserved.
cpyr Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
cpyr Copyright (c) 1988, 1993
cpyr The Regents of the University of California. All rights reserved.
cpyr
cpyr
cpyr By using this file, you agree to the terms and conditions set
cpyr forth in the LICENSE file which can be found at the top level of
cpyr the sendmail distribution.
cpyr
cpyr @(#)sendmail.hf 8.18 (Berkeley) 11/19/1998
cpyr
smtp Topics:
smtp HELO EHLO MAIL RCPT DATA
smtp RSET NOOP QUIT HELP VRFY
smtp EXPN VERB ETRN DSN
smtp For more info use "HELP <topic>".
smtp To report bugs in the implementation send email to
smtp sendmail-bugs@sendmail.org.
smtp For local information send email to Postmaster at your site.
help HELP [ <topic> ]
help The HELP command gives help info.
helo HELO <hostname>
helo Introduce yourself.
ehlo EHLO <hostname>
ehlo Introduce yourself, and request extended SMTP mode.
ehlo Possible replies include:
ehlo SEND Send as mail [RFC821]
ehlo SOML Send as mail or terminal [RFC821]
ehlo SAML Send as mail and terminal [RFC821]
ehlo EXPN Expand the mailing list [RFC821]
ehlo HELP Supply helpful information [RFC821]
ehlo TURN Turn the operation around [RFC821]
ehlo 8BITMIME Use 8-bit data [RFC1652]
ehlo SIZE Message size declaration [RFC1870]
ehlo VERB Verbose [Allman]
ehlo ONEX One message transaction only [Allman]
ehlo CHUNKING Chunking [RFC1830]
ehlo BINARYMIME Binary MIME [RFC1830]
ehlo PIPELINING Command Pipelining [RFC1854]
ehlo DSN Delivery Status Notification [RFC1891]
ehlo ETRN Remote Message Queue Starting [RFC1985]
ehlo XUSR Initial (user) submission [Allman]
mail MAIL FROM: <sender> [ <parameters> ]
mail Specifies the sender. Parameters are ESMTP extensions.
mail See "HELP DSN" for details.
rcpt RCPT TO: <recipient> [ <parameters> ]
rcpt Specifies the recipient. Can be used any number of times.
rcpt Parameters are ESMTP extensions. See "HELP DSN" for details.
data DATA
data Following text is collected as the message.
data End with a single dot.
rset RSET
rset Resets the system.
quit QUIT
quit Exit sendmail (SMTP).
verb VERB
verb Go into verbose mode. This sends 0xy responses that are
verb not RFC821 standard (but should be) They are recognized
verb by humans and other sendmail implementations.
vrfy VRFY <recipient>
vrfy Verify an address. If you want to see what it aliases
vrfy to, use EXPN instead.
expn EXPN <recipient>
expn Expand an address. If the address indicates a mailing
expn list, return the contents of that list.
noop NOOP
noop Do nothing.
send SEND FROM: <sender>
send replaces the MAIL command, and can be used to send
send directly to a users terminal. Not supported in this
send implementation.
soml SOML FROM: <sender>
soml Send or mail. If the user is logged in, send directly,
soml otherwise mail. Not supported in this implementation.
saml SAML FROM: <sender>
saml Send and mail. Send directly to the user's terminal,
saml and also mail a letter. Not supported in this
saml implementation.
turn TURN
turn Reverses the direction of the connection. Not currently
turn implemented.
etrn ETRN [ <hostname> | @<domain> | #<queuename> ]
etrn Run the queue for the specified <hostname>, or
etrn all hosts within a given <domain>, or a specially-named
etrn <queuename> (implementation-specific).
dsn MAIL FROM: <sender> [ RET={ FULL | HDRS} ] [ ENVID=<envid> ]
dsn RCPT TO: <recipient> [ NOTIFY={NEVER,SUCCESS,FAILURE,DELAY} ]
dsn [ ORCPT=<recipient> ]
dsn SMTP Delivery Status Notifications.
dsn Descriptions:
dsn RET Return either the full message or only headers.
dsn ENVID Sender's "envelope identifier" for tracking.
dsn NOTIFY When to send a DSN. Multiple options are OK, comma-
dsn delimited. NEVER must appear by itself.
dsn ORCPT Original recipient.
-bt Help for test mode:
-bt ? :this help message.
-bt .Dmvalue :define macro `m' to `value'.
-bt .Ccvalue :add `value' to class `c'.
-bt =Sruleset :dump the contents of the indicated ruleset.
-bt =M :display the known mailers.
-bt -ddebug-spec :equivalent to the command-line -d debug flag.
-bt $m :print the value of macro $m.
-bt $=c :print the contents of class $=c.
-bt /mx host :returns the MX records for `host'.
-bt /parse address :parse address, returning the value of crackaddr, and
-bt the parsed address (same as -bv).
-bt /try mailer addr :rewrite address into the form it will have when
-bt presented to the indicated mailer.
-bt /tryflags flags :set flags used by parsing. The flags can be `H' for
-bt Header or `E' for Envelope, and `S' for Sender or `R'
-bt for Recipient. These can be combined, `HR' sets
-bt flags for header recipients.
-bt /canon hostname :try to canonify hostname.
-bt /map mapname key :look up `key' in the indicated `mapname'.
-bt rules addr :run the indicated address through the named rules.
-bt Rules can be a comma separated list of rules.
control Help for smcontrol:
control help This message.
control restart Restart sendmail.
control shutdown Shutdown sendmail.
control status Show sendmail status.

View File

@ -1,428 +0,0 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
#ifndef lint
static char sccsid[] = "@(#)snprintf.c 8.12 (Berkeley) 10/13/1998";
#endif /* not lint */
#include "sendmail.h"
/*
** SNPRINTF, VSNPRINT -- counted versions of printf
**
** These versions have been grabbed off the net. They have been
** cleaned up to compile properly and support for .precision and
** %lx has been added.
*/
/**************************************************************
* Original:
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (sm_dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
* snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole.
*
* The other functions are there to prevent NULL pointers from
* causing nast effects.
**************************************************************/
/*static char _id[] = "$Id: snprintf.c,v 1.2 1995/10/09 11:19:47 roberto Exp $";*/
void sm_dopr();
char *DoprEnd;
int SnprfOverflow;
#if !HASSNPRINTF
/* VARARGS3 */
int
# ifdef __STDC__
snprintf(char *str, size_t count, const char *fmt, ...)
# else
snprintf(str, count, fmt, va_alist)
char *str;
size_t count;
const char *fmt;
va_dcl
#endif
{
int len;
VA_LOCAL_DECL
VA_START(fmt);
len = vsnprintf(str, count, fmt, ap);
VA_END;
return len;
}
# ifndef luna2
int
vsnprintf(str, count, fmt, args)
char *str;
size_t count;
const char *fmt;
va_list args;
{
str[0] = 0;
DoprEnd = str + count - 1;
SnprfOverflow = 0;
sm_dopr( str, fmt, args );
if (count > 0)
DoprEnd[0] = 0;
if (SnprfOverflow && tTd(57, 2))
printf("\nvsnprintf overflow, len = %ld, str = %s",
(long) count, shortenstring(str, MAXSHORTSTR));
return strlen(str);
}
# endif /* !luna2 */
#endif /* !HASSNPRINTF */
/*
* sm_dopr(): poor man's version of doprintf
*/
void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth));
void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad));
void dostr __P(( char * , int ));
char *output;
void dopr_outch __P(( int c ));
int SyslogErrno;
void
sm_dopr( buffer, format, args )
char *buffer;
const char *format;
va_list args;
{
int ch;
long value;
int longflag = 0;
int pointflag = 0;
int maxwidth = 0;
char *strvalue;
int ljust;
int len;
int zpad;
# if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
extern char *sys_errlist[];
extern int sys_nerr;
# endif
output = buffer;
while( (ch = *format++) != '\0' ){
switch( ch ){
case '%':
ljust = len = zpad = maxwidth = 0;
longflag = pointflag = 0;
nextch:
ch = *format++;
switch( ch ){
case 0:
dostr( "**end of format**" , 0);
return;
case '-': ljust = 1; goto nextch;
case '0': /* set zero padding if len not set */
if(len==0 && !pointflag) zpad = '0';
case '1': case '2': case '3':
case '4': case '5': case '6':
case '7': case '8': case '9':
if (pointflag)
maxwidth = maxwidth*10 + ch - '0';
else
len = len*10 + ch - '0';
goto nextch;
case '*':
if (pointflag)
maxwidth = va_arg( args, int );
else
len = va_arg( args, int );
goto nextch;
case '.': pointflag = 1; goto nextch;
case 'l': longflag = 1; goto nextch;
case 'u': case 'U':
/*fmtnum(value,base,dosign,ljust,len,zpad) */
if( longflag ){
value = va_arg( args, long );
} else {
value = va_arg( args, int );
}
fmtnum( value, 10,0, ljust, len, zpad ); break;
case 'o': case 'O':
/*fmtnum(value,base,dosign,ljust,len,zpad) */
if( longflag ){
value = va_arg( args, long );
} else {
value = va_arg( args, int );
}
fmtnum( value, 8,0, ljust, len, zpad ); break;
case 'd': case 'D':
if( longflag ){
value = va_arg( args, long );
} else {
value = va_arg( args, int );
}
fmtnum( value, 10,1, ljust, len, zpad ); break;
case 'x':
if( longflag ){
value = va_arg( args, long );
} else {
value = va_arg( args, int );
}
fmtnum( value, 16,0, ljust, len, zpad ); break;
case 'X':
if( longflag ){
value = va_arg( args, long );
} else {
value = va_arg( args, int );
}
fmtnum( value,-16,0, ljust, len, zpad ); break;
case 's':
strvalue = va_arg( args, char *);
if (maxwidth > 0 || !pointflag) {
if (pointflag && len > maxwidth)
len = maxwidth; /* Adjust padding */
fmtstr( strvalue,ljust,len,zpad, maxwidth);
}
break;
case 'c':
ch = va_arg( args, int );
dopr_outch( ch ); break;
case 'm':
#if HASSTRERROR
dostr(strerror(SyslogErrno), 0);
#else
if (SyslogErrno < 0 || SyslogErrno >= sys_nerr)
{
dostr("Error ", 0);
fmtnum(SyslogErrno, 10, 0, 0, 0, 0);
}
else
dostr((char *)sys_errlist[SyslogErrno], 0);
#endif
break;
case '%': dopr_outch( ch ); continue;
default:
dostr( "???????" , 0);
}
break;
default:
dopr_outch( ch );
break;
}
}
*output = 0;
}
void
fmtstr( value, ljust, len, zpad, maxwidth )
char *value;
int ljust, len, zpad, maxwidth;
{
int padlen, strlen; /* amount to pad */
if( value == 0 ){
value = "<NULL>";
}
for( strlen = 0; value[strlen]; ++ strlen ); /* strlen */
if (strlen > maxwidth && maxwidth)
strlen = maxwidth;
padlen = len - strlen;
if( padlen < 0 ) padlen = 0;
if( ljust ) padlen = -padlen;
while( padlen > 0 ) {
dopr_outch( ' ' );
--padlen;
}
dostr( value, maxwidth );
while( padlen < 0 ) {
dopr_outch( ' ' );
++padlen;
}
}
void
fmtnum( value, base, dosign, ljust, len, zpad )
long value;
int base, dosign, ljust, len, zpad;
{
int signvalue = 0;
unsigned long uvalue;
char convert[20];
int place = 0;
int padlen = 0; /* amount to pad */
int caps = 0;
/* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
value, base, dosign, ljust, len, zpad )); */
uvalue = value;
if( dosign ){
if( value < 0 ) {
signvalue = '-';
uvalue = -value;
}
}
if( base < 0 ){
caps = 1;
base = -base;
}
do{
convert[place++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")
[uvalue % (unsigned)base ];
uvalue = (uvalue / (unsigned)base );
}while(uvalue);
convert[place] = 0;
padlen = len - place;
if( padlen < 0 ) padlen = 0;
if( ljust ) padlen = -padlen;
/* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
convert,place,signvalue,padlen)); */
if( zpad && padlen > 0 ){
if( signvalue ){
dopr_outch( signvalue );
--padlen;
signvalue = 0;
}
while( padlen > 0 ){
dopr_outch( zpad );
--padlen;
}
}
while( padlen > 0 ) {
dopr_outch( ' ' );
--padlen;
}
if( signvalue ) dopr_outch( signvalue );
while( place > 0 ) dopr_outch( convert[--place] );
while( padlen < 0 ){
dopr_outch( ' ' );
++padlen;
}
}
void
dostr( str , cut)
char *str;
int cut;
{
if (cut) {
while(*str && cut-- > 0) dopr_outch(*str++);
} else {
while(*str) dopr_outch(*str++);
}
}
void
dopr_outch( c )
int c;
{
#if 0
if( iscntrl(c) && c != '\n' && c != '\t' ){
c = '@' + (c & 0x1F);
if( DoprEnd == 0 || output < DoprEnd )
*output++ = '^';
}
#endif
if( DoprEnd == 0 || output < DoprEnd )
*output++ = c;
else
SnprfOverflow++;
}
/*
** QUAD_TO_STRING -- Convert a quad type to a string.
**
** Convert a quad type to a string. This must be done
** separately as %lld/%qd are not supported by snprint()
** and adding support would slow down systems which only
** emulate the data type.
**
** Parameters:
** value -- number to convert to a string.
**
** Returns:
** pointer to a string.
*/
char *
quad_to_string(value)
QUAD_T value;
{
char *fmtstr;
static char buf[64];
/*
** Use sprintf() instead of snprintf() since snprintf()
** does not support %qu or %llu. The buffer is large enough
** to hold the string so there is no danger of buffer
** overflow.
*/
#if NEED_PERCENTQ
fmtstr = "%qu";
#else
fmtstr = "%llu";
#endif
sprintf(buf, fmtstr, value);
return buf;
}
/*
** SHORTENSTRING -- return short version of a string
**
** If the string is already short, just return it. If it is too
** long, return the head and tail of the string.
**
** Parameters:
** s -- the string to shorten.
** m -- the max length of the string.
**
** Returns:
** Either s or a short version of s.
*/
char *
shortenstring(s, m)
register const char *s;
int m;
{
int l;
static char buf[MAXSHORTSTR + 1];
l = strlen(s);
if (l < m)
return (char *) s;
if (m > MAXSHORTSTR)
m = MAXSHORTSTR;
else if (m < 10)
{
if (m < 5)
{
strncpy(buf, s, m);
buf[m] = '\0';
return buf;
}
strncpy(buf, s, m - 3);
strcpy(buf + m - 3, "...");
return buf;
}
m = (m - 3) / 2;
strncpy(buf, s, m);
strcpy(buf + m, "...");
strcpy(buf + m + 3, s + l - m);
return buf;
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 1998 Sendmail, Inc. All rights reserved.
* Copyright (c) 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*
* @(#)useful.h 8.12 (Berkeley) 5/19/1998
*/
# include <sys/types.h>
/* support for bool type */
typedef int bool;
#ifndef TRUE
# define TRUE 1
# define FALSE 0
#endif
# ifndef NULL
# define NULL 0
# endif /* NULL */
/* bit hacking */
# define bitset(bit, word) (((word) & (bit)) != 0)
/* some simple functions */
# ifndef max
# define max(a, b) ((a) > (b) ? (a) : (b))
# define min(a, b) ((a) < (b) ? (a) : (b))
# endif
/* assertions */
# ifndef NASSERT
# define ASSERT(expr, msg, parm)\
if (!(expr))\
{\
fprintf(stderr, "assertion botch: %s:%d: ", __FILE__, __LINE__);\
fprintf(stderr, msg, parm);\
}
# else /* NASSERT */
# define ASSERT(expr, msg, parm)
# endif /* NASSERT */
/* sccs id's */
# ifndef lint
# ifdef __STDC__
# define SCCSID(arg) static char SccsId[] = #arg;
# else
# define SCCSID(arg) static char SccsId[] = "arg";
# endif
# else
# define SCCSID(arg)
# endif