Upgrade to sendmail 8.1C from NetBSD
authorRod Grimes <rgrimes@FreeBSD.org>
Tue, 29 Jun 1993 01:03:47 +0000 (01:03 +0000)
committerRod Grimes <rgrimes@FreeBSD.org>
Tue, 29 Jun 1993 01:03:47 +0000 (01:03 +0000)
143 files changed:
usr.sbin/sendmail/Makefile
usr.sbin/sendmail/READ_ME
usr.sbin/sendmail/RELEASE_NOTES [new file with mode: 0644]
usr.sbin/sendmail/cf/README
usr.sbin/sendmail/cf/cf/Makefile
usr.sbin/sendmail/cf/cf/alpha.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/auspex.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/boat-anchor.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/chez.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/cogsci.mc
usr.sbin/sendmail/cf/cf/cs-exposed.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/cs-hidden.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/hpux-cs-exposed.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/hpux-cs-hidden.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/knecht.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/mail.cs.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/mail.eecs.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/python.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/s2k.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/sun-lamp.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/sunos3.5-cs-exposed.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/sunos3.5-cs-hidden.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/sunos4.1-cs-exposed.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/sunos4.1-cs-hidden.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/tcpproto.mc
usr.sbin/sendmail/cf/cf/ucbarpa.mc
usr.sbin/sendmail/cf/cf/ucbvax.mc
usr.sbin/sendmail/cf/cf/udb.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/ultrix4.1-cs-exposed.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/ultrix4.1-cs-hidden.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/cf/uucpproto.mc
usr.sbin/sendmail/cf/cf/vangogh.mc [new file with mode: 0644]
usr.sbin/sendmail/cf/domain/Berkeley.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/domain/cs.exposed.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/domain/cs.hidden.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/domain/eecs.hidden.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/domain/s2k.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/feature/always_add_domain.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/feature/bitdomain.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/feature/mailertable.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/feature/nocanonify.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/feature/notsticky.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/feature/nouucp.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/feature/redirect.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/feature/use_cw_file.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/feature/uucpdomain.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/hack/cssubdomain.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/m4/cf.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/m4/proto.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/m4/version.m4
usr.sbin/sendmail/cf/mailer/fax.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/mailer/local.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/mailer/smtp.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/mailer/usenet.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/mailer/uucp.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/ostype/bsd4.3.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/ostype/bsd4.4.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/ostype/hpux.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/ostype/irix.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/ostype/osf1.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/ostype/riscos4.5.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/ostype/sunos3.5.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/ostype/sunos4.1.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/ostype/ultrix4.1.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/sh/makeinfo.sh [new file with mode: 0644]
usr.sbin/sendmail/cf/siteconfig/uucp.cogsci.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/siteconfig/uucp.old.arpa.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/siteconfig/uucp.ucbarpa.m4 [new file with mode: 0644]
usr.sbin/sendmail/cf/siteconfig/uucp.ucbvax.m4 [new file with mode: 0644]
usr.sbin/sendmail/contrib/README [new file with mode: 0644]
usr.sbin/sendmail/contrib/bitdomain.c [new file with mode: 0644]
usr.sbin/sendmail/contrib/expn.pl [new file with mode: 0644]
usr.sbin/sendmail/contrib/mmuegel [new file with mode: 0644]
usr.sbin/sendmail/contrib/rcpt-streaming [new file with mode: 0644]
usr.sbin/sendmail/contrib/xla/README [new file with mode: 0644]
usr.sbin/sendmail/contrib/xla/xla.c [new file with mode: 0644]
usr.sbin/sendmail/doc/intro/intro.me [new file with mode: 0644]
usr.sbin/sendmail/doc/intro/intro.ps [new file with mode: 0644]
usr.sbin/sendmail/doc/op/op.me [new file with mode: 0644]
usr.sbin/sendmail/doc/op/op.ps [new file with mode: 0644]
usr.sbin/sendmail/doc/usenix/usenix.me [new file with mode: 0644]
usr.sbin/sendmail/doc/usenix/usenix.ps [new file with mode: 0644]
usr.sbin/sendmail/mailstats/Makefile
usr.sbin/sendmail/mailstats/mailstats.c
usr.sbin/sendmail/makemap/Makefile [new file with mode: 0644]
usr.sbin/sendmail/makemap/makemap.8 [new file with mode: 0644]
usr.sbin/sendmail/makemap/makemap.c [new file with mode: 0644]
usr.sbin/sendmail/praliases/Makefile
usr.sbin/sendmail/praliases/praliases.c
usr.sbin/sendmail/rmail/Makefile [new file with mode: 0644]
usr.sbin/sendmail/rmail/rmail.8 [new file with mode: 0644]
usr.sbin/sendmail/rmail/rmail.c [new file with mode: 0644]
usr.sbin/sendmail/src/Makefile
usr.sbin/sendmail/src/Makefile.AIX [new file with mode: 0644]
usr.sbin/sendmail/src/Makefile.HPUX [new file with mode: 0644]
usr.sbin/sendmail/src/Makefile.OSF1 [new file with mode: 0644]
usr.sbin/sendmail/src/Makefile.SunOS [new file with mode: 0644]
usr.sbin/sendmail/src/Makefile.ULTRIX [new file with mode: 0644]
usr.sbin/sendmail/src/Makefile.dist [new file with mode: 0644]
usr.sbin/sendmail/src/READ_ME
usr.sbin/sendmail/src/TRACEFLAGS [new file with mode: 0644]
usr.sbin/sendmail/src/alias.c
usr.sbin/sendmail/src/aliases [new file with mode: 0644]
usr.sbin/sendmail/src/aliases.5
usr.sbin/sendmail/src/arpadate.c
usr.sbin/sendmail/src/cdefs.h [new file with mode: 0644]
usr.sbin/sendmail/src/clock.c
usr.sbin/sendmail/src/collect.c
usr.sbin/sendmail/src/conf.c
usr.sbin/sendmail/src/conf.h
usr.sbin/sendmail/src/convtime.c
usr.sbin/sendmail/src/daemon.c
usr.sbin/sendmail/src/deliver.c
usr.sbin/sendmail/src/domain.c
usr.sbin/sendmail/src/envelope.c
usr.sbin/sendmail/src/err.c
usr.sbin/sendmail/src/headers.c
usr.sbin/sendmail/src/macro.c
usr.sbin/sendmail/src/mailstats.h
usr.sbin/sendmail/src/main.c
usr.sbin/sendmail/src/map.c [new file with mode: 0644]
usr.sbin/sendmail/src/mci.c [new file with mode: 0644]
usr.sbin/sendmail/src/newaliases.1
usr.sbin/sendmail/src/parseaddr.c
usr.sbin/sendmail/src/pathnames.h
usr.sbin/sendmail/src/queue.c
usr.sbin/sendmail/src/readcf.c
usr.sbin/sendmail/src/recipient.c
usr.sbin/sendmail/src/savemail.c
usr.sbin/sendmail/src/sendmail.8
usr.sbin/sendmail/src/sendmail.h
usr.sbin/sendmail/src/sendmail.hf
usr.sbin/sendmail/src/srvrsmtp.c
usr.sbin/sendmail/src/stab.c
usr.sbin/sendmail/src/stats.c
usr.sbin/sendmail/src/sysexits.c
usr.sbin/sendmail/src/sysexits.h [new file with mode: 0644]
usr.sbin/sendmail/src/trace.c
usr.sbin/sendmail/src/udb.c [new file with mode: 0644]
usr.sbin/sendmail/src/useful.h
usr.sbin/sendmail/src/usersmtp.c
usr.sbin/sendmail/src/util.c
usr.sbin/sendmail/src/version.c

index 8bdeac2..d75173b 100644 (file)
@@ -1,10 +1,27 @@
-#       @(#)Makefile   4.16 (Berkeley) 5/11/90
+#       @(#)Makefile   8.1 (Berkeley) 6/7/93
 
 
-SUBDIR= mailstats # praliases
+SUBDIR= mailstats makemap praliases
+VER=   XX
 
 # don't trivially install sendmail
 .if !make(install)
 SUBDIR+=src
 .endif
 
 
 # don't trivially install sendmail
 .if !make(install)
 SUBDIR+=src
 .endif
 
+tar: Files.base Files.cf Files.misc Files.xdoc
+       (cd src; ${MAKE})
+       (cd doc; PRINTER=ps ${MAKE})
+       (cd cf/cf; ${MAKE})
+       pax -w -x tar -L -f sendmail.${VER}.base.tar `cat Files.base`
+       compress sendmail.${VER}.base.tar
+       pax -w -x tar -L -f sendmail.${VER}.cf.tar `cat Files.cf`
+       compress sendmail.${VER}.cf.tar
+       pax -w -x tar -L -f sendmail.${VER}.misc.tar `cat Files.misc`
+       compress sendmail.${VER}.misc.tar
+       pax -w -x tar -L -f sendmail.${VER}.xdoc.tar `cat Files.xdoc`
+       compress sendmail.${VER}.xdoc.tar
+
+ftp: sendmail.${VER}.base.tar.Z sendmail.${VER}.cf.tar.Z sendmail.${VER}.misc.tar.Z sendmail.${VER}.xdoc.tar.Z
+       rcp sendmail.${VER}.*.tar.Z RELEASE_NOTES barad-dur:/disks/barad-dur/ftp/sendmail/.
+
 .include <bsd.subdir.mk>
 .include <bsd.subdir.mk>
index b2f7ac5..de494f0 100644 (file)
@@ -1,9 +1,94 @@
 /*-
 /*-
- *     @(#)READ_ME     4.4 (Berkeley) 4/20/91
+ *     @(#)READ_ME     8.1 (Berkeley) 6/7/93
  */
 
  */
 
-aux            Auxiliary programs, probably all out-of-date.
-mail.local     Source for mail.local(8) (the old /bin/mail).
-doc            Documentation.
-rmail          Source for rmail(8).
+                       SENDMAIL RELEASE 8
+
+This directory has the latest sendmail software from Berkeley.  See
+doc/op/op.me for a summary of changes since 5.67.
+
+Report any bugs to sendmail@CS.Berkeley.EDU.
+
+The latest version of sendmail is kept on FTP.CS.Berkeley.EDU, directory
+/ucb/sendmail; check there for the latest revision.
+
+There are several related RFCs that you may wish to read -- they are
+available via anonymous FTP to several sites, including nic.ddn.mil
+(directory rfc), ftp.nisc.sri.com (rfc), nis.nsf.net (RFC),
+nisc.jvnc.net (rfc), venera.isi.edu (in-notes), and wuarchive.wustl.edu
+(info/rfc).  They can also be retrieved via electronic mail by sending
+email to one of:
+
+       mail-server@nisc.sri.com
+               Put "send rfcNNN" in message body
+       nis-info@nis.nsf.net
+               Put "send RFCnnn.TXT-1" in message body
+       sendrfc@jvnc.net
+               Put "RFCnnn" as Subject: line
+
+Important RFCs for electronic mail are:
+
+       RFC821  SMTP protocol
+       RFC822  Mail header format
+       RFC974  MX routing
+       RFC976  UUCP mail format
+       RFC1123 Host requirements (modifies 821, 822, and 974)
+       RFC1413 Identification server
+       RFC1341 MIME: Multipurpose Internet Mail Extensions
+       RFC1344 Implications of MIME for Internet Mail Gateways
+
+Other standards that may be of interest (but which are less directly
+relevant to sendmail) are:
+
+       RFC987  Mapping between RFC822 and X.400
+       RFC1049 Content-Type header field (extension to RFC822)
+
+Unfortunately, for a variety of reasons the Makefiles are for the new
+Berkeley "make" and will not work on the old, traditional make.  I urge
+you to get this make from Net2 (available on many public FTP archives).
+Failing that, some directories have a "Makefile.dist" that will work on
+older versions of make (but don't have the niceties included).
+
+Similar comments apply to the man pages -- they use the new Berkeley
+-mandoc macros instead of the -man macros.  You can get these from
+Net2 as well.
+
+IF YOU WANT TO RUN THE NEW BERKELEY DB SOFTWARE:  ****  DO NOT  ****
+use the version that was on the Net2 tape -- it has a number of
+nefarious bugs that were bad enough when I got them; you shouldn't have
+to go through the same thing.  Instead, get a new version via public
+FTP from ftp.CS.Berkeley.EDU, file ucb/4bsd/db.tar.Z.  This software
+is highly recommended; it gets rid of several stupid limits, it's much
+faster, and the interface is nicer to animals and plants.  You will
+also probably find that you have to add -I/where/you/put/db/include
+to the sendmail makefile to get db.h to work properly.
+
+The structure of this directory tree is:
+
+cf             Source for Berkeley configuration files.  These are
+               different than what you've seen before.  They are a
+               fairly dramatic rewrite, requiring the new sendmail
+               (since they use new features).
+contrib                Some contributed tools to help with sendmail.  THESE
+               ARE NOT SUPPORTED by Berkeley -- contact the original
+               authors if you have problems.  (This directory is not
+               on the 4.4BSD tape.)
+doc            Documentation.  If you are getting source, read
+               op.me -- it's long, but worth it.
+mailstats      Statistics printing program.  It has the pathname of
+               sendmail.st compiled in, so if you've changed that,
+               beware.  This isn't all that useful.
+makemap                A program that creates the keyed maps used by the $( ... $)
+               construct in sendmail.  It is primitive but effective.
+               It takes a very simple input format, so you will probably
+               expect to preprocess must human-convenient formats
+               using sed scripts before this program will like them.
+               But it should be functionally complete.
+praliases      A program to print the DBM version of the aliases file.
+               It hasn't been converted to understand the new Berkeley
+               DB format (which we are using).
+rmail          Source for rmail(8).  This is used as a delivery
+               agent for for UUCP, and could presumably be used by
+               other non-socket oriented mailers.  Older versions of
+               rmail are probably deficient.
 src            Source for the sendmail program itself.
 src            Source for the sendmail program itself.
diff --git a/usr.sbin/sendmail/RELEASE_NOTES b/usr.sbin/sendmail/RELEASE_NOTES
new file mode 100644 (file)
index 0000000..f49daa2
--- /dev/null
@@ -0,0 +1,1154 @@
+8.1C/8.1B      93/06/27
+       Serious security bug fix: it was possible to read any file on
+               the system, regardless of ownership and permissions.
+       If a subroutine returns a fully qualified address, return it
+               immediately instead of feeding it back into rewriting.
+               This fixes a problem with mailertable lookups.
+       CONFIG: fix some M4 frotz (concat => CONCAT)
+
+8.1B/8.1A      93/06/12
+       Serious bug fix: pattern matching backup algorithm stepped by
+               two tokens in classes instead of one.  Found by Claus
+               Assmann at University of Kiel, Germany.
+
+8.1A/8.1A      93/06/08
+       Another mailertable fix....
+
+8.1/8.1                93/06/07
+       4.4BSD freeze.  No semantic changes.
+
+6.65/6.34      93/06/06
+       Fix some lintish problems.
+       Fix some cases where server SMTP behaved poorly when handed bogus
+               input, pointed out by Eric Wassenaar.
+       CONFIG: fix some more (sigh) mailertable bugs -- thanks to
+               Motonori Nakamura of Kyoto University (again).
+
+6.64/6.33      93/06/05
+       Don't send 050 (-v) information after the 250 response to a QUIT
+               command in srvrsmtp -- clients usually close the connection
+               at this point, and it causes bogus error messages.
+       Don't send messages that have errors on input (such as unbalanced
+               parentheses) during SMTP transactions, since a return
+               message has (probably) already been sent.
+       Give better diagnostics on timeouts during network reads, including
+               information similar to the SMTP phase.
+       Fix bug that caused SMTP messages to deliver synchronously; this
+               happened after the DATA 250, and hence caused reading the
+               next command to be delayed.
+       Ignore Errors-To: header unless 'l' (lower case el) header is
+               specified.  The Errors-To: header violates RFC 1123.
+               Errors-To: was only needed to take the place of the
+               envelope sender in the days when most Unix mailers
+               didn't understand about the two kinds of senders.
+       Don't send warning messages in response to automatically generated
+               messages (that is, those From:<>).
+       CONFIG: fix some rather stupid typos in the mailertable code
+               pointed out by Motonori Nakamura of Kyoto University.
+       CONFIG: add confUSE_ERRORS_TO configuration option.
+       CONFIG: if ALWAYS_ADD_DOMAIN is selected, try to use $M
+               (masquerade name) instead of $j.
+       CONFIG: don't add dots to relay names (added in 6.29); it breaks
+               several things, and can be simulated by dot terminating
+               the names of relays.  For example, use:
+                       DBbit.net.relay.
+               (note the trailing dot).
+
+6.63/6.32      93/06/01
+       Fix prototypes to eliminate chars in argument lists -- some
+               compilers are pissy about this.
+       Log protocol ($r) and body type if set so we can determine if
+               the adaptive algorithms are working.
+       Pessimize on locking of database files (particularly for NEWDB
+               databases) during opens.  There were problems with
+               processes opening the file while it was rebuilt; since
+               NEWDB caches heavily, the reader opened an empty file,
+               which is an error.  If your system has the ability to
+               lock atomically on open, this works properly; otherwise,
+               there are race conditions.
+       Check mod time on .pag file instead of .dir in NDBM aliases
+               because the .dir file doesn't get updated for small
+               alias files.  From John Gardiner Myers of CMU.
+       More Solaris portability -- it now compiles on Solaris, but
+               hangs up in gethostbyname().
+       Move setting of RES_DEBUG flag before first myhostname() call
+               so we can see name server traffic on that call.
+       Fsync() queue files.
+       Fix a problem that causes -bi to try to rebuild maps other than
+               the alias file(s).
+       Fix a problem that caused udb to reject entries from any but
+               the first database listed.
+       Rearrange doc subdirectory for 4.4BSD release tape.
+       CONFIG: put $r into the Received line.  This was an oversight.
+       CONFIG: fix typo (call to ruleset 99 should have been rulset 90).
+       CONFIG: move "auxiliary" subroutines to be in ruleset 90-99
+               range -- in the long run, single digit rulesets may
+               become reserved for builtin use by sendmail.
+       CONFIG: fix major problem that causes host aliases (that is,
+               anything in $=w != $j) to not be recognized.  This has
+               been around since 6.30.
+
+6.62/6.31      93/05/28
+       BETA RELEASE
+       Fix recursive syserr (if there is an error printing a syserr
+               message).  This makes the code much less eager to consider
+               a write error as serious.  This also includes some
+               heuristics to be clever about closed connections.
+       Lock NEWDB files during gets.  This requires version 1.5 or later
+               of the db library.  If you have an older version, you
+               can use -DOLD_NEWDB.  This will go away in a few weeks.
+       Fix problem causing aliases that use host maps to get overwritten.
+       Do appropriate byte swapping on port numbers in ident protocol
+               code.  Fix from Allan Johannesen of WPI.
+       Defer opening of map files to the same time as alias files so that
+               the daemon will tend to pick up new versions more promptly.
+       Prototype a bunch more functions.
+       Some Solaris 2.1 changes (still doesn't link though).
+       Try to simplify Makefiles by including more subordinate #defines
+               in conf.h (based on OS type).
+       CONFIG: check for domains if FEATURE(mailertable) is defined.
+               For example, if the host name is "knecht.cs.berkeley.edu"
+               it will search the following mailertable keys:
+                       knecht.cs.berkeley.edu
+                       .cs.berkeley.edu
+                       .berkeley.edu
+                       .edu
+               This could be used to replace the special relays for bitnet
+               and similar nets.
+
+6.61/6.30      93/05/24
+       Fix problem that prevented appending dots on canonified host
+               names.  This breaks tons of config files -- very
+               important fix.
+       Fix improper pointer dereference in response to HELO command.
+       Fix core dump if debugging set in map_rewrite.
+       CONFIG: add FEATURE(always_add_domain) to always attach the
+               local domain (only impacts local mail).
+       CONFIG: try to avoid turning names into $j -- although
+               technically a host can only have one "canonical name",
+               it seems to be common practice to have several.
+
+6.60/6.29      93/05/22
+       Major change: merge alias databases with maps.  This expands and
+               changes the map class interface but fixes a bunch of bugs.
+               The important user-visible change is that the file name
+               in a K line now does not include the ".db" extension; this
+               is added automatically.  Also, the -d (NIS domain) flag is
+               missing from the K config line; use @domain instead.
+               When compiling, the *_MAP names are gone -- just compile
+               in NDBM, NEWDB, and/or NIS support.
+       Announce mailer/host/user triple on -bv flag -- from Brian
+               Bullen of Stirling University.
+       Don't send more than one line in response to HELO -- it confuses
+               Pony Express, which then behaves very badly.  However,
+               this change does send two line 220 greetings, with the
+               second line reading "ESMTP spoken here".  The usersmtp
+               module recognizes this and goes into ESMTP mode regardless
+               of the setting of the "a" mailer flag.  Thus, "a" means
+               "always try EHLO".
+       AIX portability changes (thanks to Christophe Wolfhugel of
+               Herve Schauer Consultants (Paris) for providing me with
+               an INSA account for this purpose).  Lightly tested.  Use
+               -D_AIX3.  This probably breaks compatibility with some
+               older systems (e.g., 4.2bsd) but still works on SunOS
+               4.1.2, Ultrix 4.2A, HP-UX 8.07, OSF/1 T1.3, and AIX 3.2.3.
+       Fix a problem causing an error message loop if the output channel
+               is hosed.
+       Add the Makefiles that I use for various environments -- some are
+               Berkeley make versions and some are old make versions.
+               My makefile for the NeXT box has gotten lost, alas!
+       PRALIASES: support for printing NEWDB databases.  From
+               Michael J. Corrigan of U.C. San Diego.
+       CONFIG: don't pass pseudo-domains to $[ ... $] (if you have
+               a wildcard MX it can have wierd results).  From
+               Christophe Wolfhugel.
+       CONFIG: dot terminate relay hostnames in S0.  From Christophe
+               Wolfhugel.
+
+6.59/6.28      93/05/13
+       Log version with SMTP daemon startup message.
+       Adjust setproctitle to work on NetBSD and BSD/386.
+       Fix null pointer reference in MX fallback code.
+       A bunch of minor fixes from Eric Wassenaar:
+               If deliver cannot execv the mailer, return EX_OSERR
+                       instead of EX_TEMPFAIL (to give better
+                       error messages).
+               Consistently malloc e_message.
+               Catch degenerate case of calling returntosender()
+                       with an empty returnq.
+               MIME reformatting.
+
+6.58/6.28      93/05/13
+       Fix bug that can cause incorrect verbose display of user smtp
+               messages.
+       Disable SMTP VERB command if PRIV_NOEXPN is set (since this
+               could reveal the same information.
+       Allow failure when reading SMTP greeting message to go on to
+               next MX host.
+       Add "MIME-Version: 1.0" header if using MIME (this was NOT
+               included in RFC 1344, but Bill King of Allan-Bradley
+               Company forwarded me email from Nathaniel Borenstein
+               claiming that it was an inadvertent omission).
+       Don't use Content-Type: X-message-header.  According to John
+               Myers of CMU, many MIME readers will completely ignore
+               the data if they don't recognize it.  Instead, just
+               add a blank line to make it a legal (empty) message.
+       Fix problem causing dots to keep getting appended to cached
+               hostnames.  This can cause buffer overrun conditions.
+               The problem was found by Erik Forsberg of Retix,
+               although I used a different bug fix than he provided.
+       Fix parsing of split header/envelope rewriting specs -- from
+               Eric Forsberg.
+       Fix from Eric Wassenaar to correct To: lists in error messages.
+
+6.57/6.28      93/05/11
+       Fix minor glitch causing extra ctladdrs to be output to queue
+               file.  Just an annoyance.
+       Cache results of name server canonification lookups to avoid
+               backed up queue runs.
+       Major rewrite of alias.c: considerable cleanup, plus sample
+               (untested) support for NIS aliases.  The "A" option
+               can now be a comma separated list (or be repeated) --
+               that is, you can have multiple alias databases.  Each
+               database can have the syntax ``class:file''; if no class
+               is specified, the "implicit" class is assumed.  Implicit
+               searches through a list of compiled in types -- hash,
+               dbm, nis, and stab.  Alias files are searched in the
+               order they are listed.  For example:
+                       OAhash:/etc/aliases.local,/etc/aliases
+                       OAnis:mail.aliases@my.nis.domain
+               first searches the hash database /etc/aliases.local,
+               then the regular /etc/aliases database, then the NIS
+               map "mail.aliases" in the NIS domain "my.nis.domain".
+       If in Verbose mode (probably from VERB command) run SMTP job
+               in foreground and don't do RCPT optimizations.
+       Add udb :mailsender as equivalent to owner- for regular aliases.
+       Delete option 8; add option 7 that means the opposite.  That is,
+               default to 8-bit mode; a special option is needed to
+               force sendmail into 7 bit mode.
+       Send error messages in encapsulated MIME format.
+       New compile flag "NIS" that turns on NIS alias and NIS map
+               support.
+       Add "j" option to send error messages in MIME (RFC 1341)
+               encapsulated message format per RFC 1344.  The
+               syntax is pretty ugly if you don't have MIME-aware
+               user agents.
+       Clean up message handling (for display in mailq output).
+       New setproctitle implementation for 4.4bsd.
+       Create files (such as ~/dead.letter) using mode FileMode (the
+               F option value) instead of 0666.
+       Fix bug causing output of EXPN command to not be fully qualified.
+               This may cause some problems with UUCP addresses that
+               will require some config file assistance -- specifically,
+               the $: part has to include the host name for this output
+               to make sense.
+       Fix a problem that sometimes diagnosed errors and still sent the
+               message if the header syntax was bad.
+       Fix a bug that caused an error message to be emailed when sendmail
+               was operating in -bv mode.
+       Add "ListenQueueSize" keyword to daemon options option (OO) to
+               set the queue size parameter passed to listen().  You
+               will normally have to tweak your kernel to up this.
+       Strip spaces off of beginning of message-id before logging (in
+               case it was folded across lines).
+       Tweak compile flags in daemon.c -- there were some cases where
+               it wouldn't work without NETINET.
+       Change *file* mailer to output all the usual default headers
+               (From, Date, Message-Id).  It gets used when sending
+               back error messages.
+       CONFIG: explicitly catch and diagnose list:; syntax in ruleset
+               zero -- this is not a valid recipient syntax according
+               to RFC 821.
+       CONFIG: add confMIME_FORMAT_ERRORS to send error messages in
+               MIME format.  Defaults to on.
+       CONFIG: add SMTP_MAILER_FLAGS and UUCP_MAILER_FLAGS to augment
+               the flags for those mailers.
+
+6.56/6.27      93/05/01
+       Fix problem that causes the fallback mail to postmaster
+               (case ESM_POSTMASTER in savemail()) to not look at
+               aliases (ugh).
+       Some more HPUX tweaking (compile flag hpux => __hpux so it
+               still works in ANSI mode).
+       Don't try to flock non-regular files when mailing to a file.
+               In particular, this was a problem if you tried to
+               send to /dev/null.
+       Fix a wierd bug that can cause senders to be queued as
+               recipients if the name server is down when the mail
+               is initially sent.  This hack just ignores sender
+               deletion (essentially, it sets the MeToo flag) if there
+               is a TEMPFAIL during processing of the sender address.
+               Obscure.
+       Fix a dangling else problem -- from Brian Bullen from University
+               of Stirling, UK.
+       Add the "b" mailer flag to force a blank line on the end of
+               messages.  Some brilliant versions of /bin/mail insist
+               on this but do not add it themselves.
+       Add the "g" mailer flag to prevent user SMTP from sending
+               "MAIL From:<>".  This is only intended to be a
+               transitional gesture, and should not be used if at
+               all possible.  It appears that Berkeley and IDA
+               config files have always handled this properly; the
+               UK config kit apparently does not.
+       Don't lowercase and then capitalize header field names -- leave
+               them with original capitalization.  Fixes from Bill
+               King of Allen-Bradley Company.
+       Further cleanup and improved reporting of error messages,
+               particularly conditions that cause messages to be
+               requeued for future delivery.
+       Tweak syslog priorities in some cases.
+       CONFIG: clean up route-addr on UUCP addresses.
+
+6.55/6.25      93/04/27
+       HPUX 8.07 compatibility changes in getla() -- I had to make
+               these changes to get it to work at Berkeley, although
+               others seem to have been working before (???).
+       Various patches to XLA code.
+       Fix problem that causes setuid bit on files to be ignored from
+               SMTP or in queue runs.  Problem noted by Jason Ornstein
+               of Under The Wire, Inc.
+       Fix problem that can cause CNAMEs to be ignored.
+       Generalize getmxrr to match local host in $=w instead of a
+               single name passed in.
+       Some cleanup from Eric Wassenaar:
+               Use FileMailer instead of ProgMailer in two places.
+               Eliminate duplicate 8th-bit stripping in commaize.
+               Fix a problem with mis-parsing of backslash escapes
+                       under some circumstances.
+       NIS map fix (was always including trailing null character)
+               from Mike Glendinning of Ingres UK.
+       Add "a" mailer flag to try using ESMTP.  It tries the EHLO
+               command and if that fails falls back to regular SMTP.
+               Also parses EHLO option keywords.  If host supports
+               SIZE extension, this is added to the MAIL FROM:
+               command.
+       Extend "b" option to include a second value which is the
+               maximum message size this server is willing to accept.
+               For example, a value of "10/1000000" says that there
+               must be ten blocks free, and sendmail will reject
+               any message larger than one megabyte.
+       Some portability hooks for NeXT (this could be applicable
+               to Mach in general).  You have to create an empty
+               file called "unistd.h" to get it to compile.
+       Adjust config values (MAXLINE, MAXATOM, and PSBUFSIZE) to
+               be more generous.
+       Add X400-Received: to the list of headers tagged with H_TRACE
+               in conf.c.  From Bill King, Allen-Bradley Co.
+
+6.54/6.25      93/04/19
+       Fix problem that caused redefinition of SMTP and QUEUE compile
+               flags.  Pointed out by Jon Forrest of the Sequoia 2000
+               project at Berkeley.
+       Properly handle \! hack -- it was treating host\!user as one
+               token (host!user) instead of three (host, !, user).
+               Fix from Eric Wassenaar of NIKHEF-H.
+       Fix compilation problem in getauthinfo() if IDENTPROTO is off.
+       Turn off DEFNAMES and DNSRCH when getting the hostsignature
+               (i.e., MX records) in level 1 configuration files; this
+               matches the old behaviour.  From Nakamura Motonori of
+               Kyoto University.
+       Improve error message printing -- if sent through an alias,
+               error messages include the name of the alias in the
+               message.  Unfortunately, in order to make this work
+               properly in queue runs, this changes the format of the
+               C line in the qf file.  The relatively uselessness of
+               the previous information was pointed out to me by
+               Allan E Johannesen of WPI.
+       Add XLA compile flag to add hooks to Christophe Wolfhugel's
+               extended load average code.  This is still in very early
+               form.  For information regarding the guts of the xla
+               code, contact Christophe.Wolfhugel@grasp.insa-lyon.fr.
+       Additional hooks for detecting tempfails in rewriting rules
+               (that is, in map lookups).
+
+6.53/6.25      93/04/15
+       Properly diagnose ruleset zero returning null (instead of a mailer
+               triple).  From Nakamura Motonori of Kyoto University.
+       More generalization of socket code for other protocols.
+       Shorten timeouts on reverse name lookups -- since they are done
+               during connection establishment, long timeouts here can
+               cause higher level timeouts.  This mainly serves to accept
+               mail from hosts that do not have proper reverse (PTR) DNS
+               records set up.
+       Reset e_statmsg before each mailer invocation to avoid bogus
+               messages in the log.
+       Redefine $r, $s, and $_ in error envelopes so you don't get
+               incorrect cruft in the error message.  Problem noted by
+               Nakamura Motonori of Kyoto University.
+       Fix a problem that can cause failure to return errors to Postmaster
+               in certain cases.  From Nakamura Motonori.
+       Fix a problem that can cause some systems to give duplicate error
+               messages when a bad syntax address such as "<a" is presented
+               to an SMTP server.   It doesn't seem to occur on all
+               machines.  From Nakamura Motonori.
+       Default IDENTPROTO off for Ultrix and HPUX, which apparently have
+               the interesting "feature" that when they receive a "Host
+               unreachable" message they closes all open connections to
+               that host.  However, some firewall gateways send this message
+               if you try to connect to an unauthorized port, such as the
+               IDENT port (113).  Thus, no email can be received from such
+               hosts.  There is some evidence that versions of Ultrix before
+               4.3 do not have this problem.  Thanks to Tom Ivar Helbekkmo
+               for pointing out this behaviour to me and to Michael Corrigan
+               of U.C. San Diego for informing me about the HPUX problem.
+       Allow IPC mailers to return a colon-separated list of hosts in the
+               $@ clause; these are searched in order as though they were
+               MX records.
+       When sending an error report, print the list of addresses tagged
+               as bad.  Requested by Allan E Johannesen of WPI.
+       Change map function calls to return a status code.  This gets
+               passed back as the result of rewrite.  Parseaddr marks
+               the address as a QUEUEUP address if the return code is
+               EX_TEMPFAIL.  All this to queue properly if the name
+               server is down.  This code is not well tested.  This code
+               changes the interface to map lookup functions (a fifth
+               parameter, int *statp, is added).  Feature requested by
+               Dan Oscarsson.
+       Don't delete quotes (in the dequote map) if there are spaces in
+               the string, since this would cause them to be replaced by
+               the SpaceSub character.
+       Accept BODY=8BITMIME on SMTP MAIL command.  This isn't advertised
+               because the 8BIT to 7BIT translation doesn't exist yet.
+               This does add a "bodytype" field to both envelope and
+               queue file and a -B command line flag to pass the type in
+               during direct invocations.
+       Discard return error messages only on responses to responses to
+               responses, not on responses to responses.  That is, the
+               algorithm is to try return to sender, then return to
+               postmaster, then discard.  Previously it discarded
+               immediately if the return to sender pass failed.
+       CONFIG: back out change to hide unqualified hostnames behind %-hack.
+               This screws up local aliases and .forward files.
+       CONFIG: add FEATURE(nocanonify) to turn off calls to $[ ... $];
+               some sites only handle completely canonified names.
+               Requested by John Gardiner Myers of CMU.
+       CONFIG: some UUCP code was still included even if FEATURE(nouucp)
+               was specified.
+
+6.52/6.24      93/04/10
+       Clean up some minor glitches on error return messages pointed out
+               by Nakamura Motonori of Kyoto University.
+       Fix reply() to not reset SmtpReplyBuffer on fatal errors; this
+               was supposed to reset SmtpMsg Buffer.  This makes the
+               client side code virtually useless.  Reported by Allan
+               E Johannesen of WPI and Phil Brandenberger of Swarthmore.
+       Better debug messages if fuzzy is disabled, suggested by Allan
+               E Johannesen of WPI.
+       Offset SmtpReplyBuffer by four in usersmtp when checking for
+               loopback.  From Eric Wassenaar.
+       Don't set $s until after runinchild in srvrsmtp -- otherwise
+               it gets cleared.  From Eric Wassenaar.
+       Implement IDA-style $&x for deferred macro expansion.
+       More POSIX compatibility.
+       CONFIG: Hide unqualified hostnames behind %-hack using $s as the
+               actual sender.  This is only done if $r is non-null, that
+               is, if this is not locally submitted mail.
+       CONFIG: Add FEATURE(bitdomain) allowing mapping of BITNET host
+               names to internet domains.  A program contributed by
+               John Gardiner Myers of CMU to create the maps is included
+               in the contrib directory (in the "misc" tar file).
+       CONFIG: Add FEATURE(uucpdomain) for a similar mapping for UUCP
+               hosts.  There is currently no tool to create this map.
+
+6.51/6.23      93/04/04
+       Add D= mailer flag to specify a path of possible working directories
+               in which to execute the mailer.  This is intended for the
+               prog mailer; some shells can get upset if they don't have
+               access to the current directory.
+       Add RFC 1413 (IDENT) protocol support.  This is only very loosely
+               tested.  This adds a $_ macro to be the authenticated
+               info (in ``user@domain [address]'' form) and debug flag
+               9 to trace the protocol.
+       Check for loopbacks in usersmtp instead of srvrsmtp -- there is no
+               reason for a local agent to not be talking to the localhost
+               (although the inverse is not true).
+       Add a few hooks for automated map rebuilding.  This is certainly
+               not done yet.
+       CONFIG: Have prog mailer specify a path of ``D=$z:/'' -- that is,
+               user's home directory then the root.
+       CONFIG: Log RFC 1413 identification in Received: line.
+
+6.50/6.22      93/04/01
+       Fixes to requeueing code to make it compute priority, nrcpts,
+               and the like properly.
+
+6.49/6.22      93/04/01
+       Diagnose incorrect privacy flags.  Suggested by Bryan Costales
+               of ICSI.
+       Some ANSI C fixes.
+       Arrange to quote backslashes as well as other special characters
+               in the phrase part of a route-addr.
+       Some fixes to FallBackMX code suggested by Nakamura Motonori of
+               Kyoto University.
+       More vigorous zeroing of CurHostAddr to avoid logging of bogus
+               host addresses when you are actually just printing
+               information from the MCI structure; problem noted by
+               Michael Corrigan of U.C. San Diego.
+       Don't ignore rest of queue if any job is not runnable.  This can
+               also cause an incorrect job to be lost.  Fix from
+               Eric Wassenaar.
+       Always respond "quickly" to RCPT command; do alias expansion and
+               the like later.  This also means that mail for lists that
+               have errors will be acccepted, and an error sent back
+               later.  This is done by instantiating the queue file
+               and then immediately running and requeueing it.
+
+6.48/6.22      93/03/30
+       Fix incorrect diagnosis of infinite loop in ruleset.  Problem noted
+               by several people.
+       Improve information printed when infinite loops are discovered.
+       Zero CurHostAddr to fix erroneous internet addresses in log when no
+               addresses can be bound.  Pointed out by Nakamura Motonori
+               of Kyoto University.
+       "Probe" SMTP connections using RSET instead of NOOP "just in case".
+               Suggested by John Gardiner Myers of CMU.
+       Don't warn about -f if you are setting sender to yourself.
+
+6.47/6.22      93/03/29
+       Fix incompatible call to endmailer in smtpquit which causes core
+               dumps.  Noted by Allan E Johannesen of WPI.
+       HPUX portability changes from Michael J. Corrigan of UC San Diego.
+       Require MAIL before RCPT command in srvrsmtp.c.  This had been
+               intentional from the 821 draft days when the order wasn't
+               clear, but is silly now.
+       Fix bug in nis_magic routine that was initializing parameters
+               incorrectly.  Fix from Takahiro Kanbe of Fuji Xerox
+               Information Systems Co., Ltd.
+       Change default for PrivacyFlags in conf.c to 0 -- since it always
+               "or"s in new values, there was no way to turn off the
+               AuthWarning stuff.
+       Add O option to set SMTP daemon options.
+       Add V option to set fallback MX host.  This always sorts at lower
+               priority than anything it gets from the name server.  It
+               should only be used for environments with very bad network
+               connectivity.  Requested by several people.
+       Log sending info.  It's not clear this is a good idea.
+       CONFIG: fix typo in mailertable code.  Noted by Phil Brandenberger
+               of Swarthmore.
+       CONFIG: add confDAEMON_OPTIONS and confFALLBACK_MX to set options
+               O and V, respectively.
+
+6.46/6.21      93/03/26
+       Fix botch in server SMTP that broke transactions that did not
+               use HELO first (like MH).  Fix from Michael Corrigan
+               of U.C. San Diego.
+       Fall back to other MX records if there is an error anywhere
+               in delivery (actually on MAIL or DATA -- RCPT is harder).
+               Suggested by John Gardiner Myers and Nakamura Motonori.
+       Revert to non-prototypes -- it turns out that our ANSI C
+               compiler is more forgiving than most others about
+               mixing prototyped extern declarations with non-prototyped
+               function definitions.
+       Fix a problem with multi-word class matching pointed out by
+               Neil Rickert.  Given:
+                       CX b a.b.c
+                       R$+ $=X $+      $: $1 < $2 > $3
+               the input "user@a.b.c" failed instead of being properly
+               rewritten as "user@a.<b>.c".
+       Neil also convinced me that it was correct that $~ should match
+               only one token -- the problem is that it's always possible
+               to add another token, so $~ matches far too eagerly.
+
+6.45/6.21      93/03/25
+       Implement multi-word classes (properly!).
+
+6.44/6.21      93/03/25
+       Add X-Authentication-Warning: headers to clue users into possible
+               attempts to forge mail.  This is on the authwarnings
+               privacy flag, but is the default.  Suggested by Bryan
+               Costales of ICSI.
+       Pass default units for convtime in so they can be more reasonable.
+       Allow config files to always add a new Comments: header (i.e.,
+               they will be added even if an old one already exists).
+               Suggested by Bryan Costales of ICSI.
+       Allow config files to delete an existing Return-Path: header.
+               These should only be added at final delivery.  Suggested
+               by Bryan Costales of ICSI.
+       Some debugging additions.  Suggested by Bryan Costales of ICSI.
+       Clean up logging of Family 0 addresses.  Noted by David Muir
+               Sharnoff and others.
+       Add a "dequote" map class.  This allows config files to strip
+               quotes off of addresses.  Note that this is not a builtin
+               map, just a class -- so you have to define the map
+               using the K line.
+       Fix a bug in the queueup() loop getting a locked tf where in
+               very odd cases it can fall off the bottom and core dump.
+               Of course, it was P{r Emanuelsson who found it....
+       Open a new transcript when splitting an envelope.  Problem found
+               by Allan E Johannesen of WPI.
+       Improved error output in endmailer if the mailer core dumps.
+       CONFIG: Fix typo in UUCP mailer definition.
+       CONFIG: Default several of the new options on: eight bit input,
+               privacy flags set to "authwarnings", and message warning
+               set to 4h.
+       CONFIG: Use dequote map.
+
+6.43/6.20      93/03/23
+       Fix problem with assumption of an sa_len field in a generic
+               sockaddr -- it turns out that most vendors haven't
+               picked up this (very important) fix.
+       Change compilation flags for daemon code -- select one or both
+               of NETINET or NETISO, but don't ever set DAEMON manually.
+       CONFIG: add FEATURE(mailertable) to do IDA-style mailertables.
+
+6.42/6.19      93/03/19
+       Use Postmaster as default fallback return address, not root.
+       POSIX changes for file descriptor handling.
+       Diagnose errors writing new queue file.
+       If you change the owner using an owner- alias, also change the
+               error mode to EM_MAIL so that errors don't get dropped
+               into an inappropriate directory.  Problem noted by
+               Allan E Johannesen of WPI.
+       If you are su'ed to root, send email as who you really are, not
+               as root.  From Brian Kantor of U.C. San Diego.
+       Allow warning messages to be sent after a configurable interval
+               has passed without delivery.  The message is sent only
+               once per envelope.  This changes the format of the qf
+               file to have an F line, and the format of the T option
+               to accept take the format "return/warn" (both intervals).
+       Don't force all local names to lower case -- this was left over
+               from the wierd handling of case mapping on aliases.  It
+               is now driven (as expected) by the "u" mailer flag.
+               Problem noted by P{r Emanuelsson.
+       Fix problem that caused headers on returned email to be trashed;
+               they were getting freed, but are still accessible via
+               BlankEnvelope.
+       Fix problem that caused bogus ids to be created on returned
+               mail.
+       Add support for ISO and other non-INET networking.  This is by
+               no means finished yet.  This does assume a lot of other
+               system support, like a version of gethostbyname that
+               returns non-AF_INET addresses.
+       CONFIG: change default on prog mailer to keep upper case in
+               user names (i.e., in the program command line).
+       CONFIG: strip trailing dots off of hosts in uucp mailer before
+               convert to bang format.
+       CONFIG: create new "relay" mailer for $R (LOCAL_RELAY) and $H
+               (MAIL_HUB) delivery that doesn't add local domain.  Note
+               that this violates 821, but is probably "more correct"
+               for what we are trying to do.  Problem pointed out by
+               Michael Graff of Iowa State.
+
+6.41/6.18      93/03/18
+       Clean up unnecessary creates of queue ids (i.e., empty qf files)
+               when not needed, such as when starting up an SMTP
+               connection.
+       Fix problem where split envelopes aren't instantiated in the queue.
+               This is quite a serious bug.
+       Owner- aliases had problems with leading spaces causing a
+               premature delimitation.
+
+6.40/6.18      93/03/18
+       Have ending 250 (after DATA) include the id; suggested by
+               Brian Kantor of UC San Diego.
+       Add logging on envelope splitting.
+       Change queue ids to have one more letter encoding the hour of
+               the day so that during a single day there is a greater
+               likelihood of uniqueness; requested by Brian Kantor.
+
+6.39/6.18      93/03/18
+       Fix minor compile problem if LOCKF is defined.
+       Define size of tobuf in conf.h.  Observed by Toshinari Takahashi
+               of Toshiba.
+       Restore e_sender -- this is equivalent to e_from.q_paddr without
+               decorations such as angle brackets and comments.
+       OSF/1 on Alpha changes from Allan E Johannesen of WPI.
+       CONFIG: fix typo in S3 for list syntax (;: => :;).  Thanks to
+               Christopher Hoover for noting the problem.
+
+6.38/6.17      93/03/17
+       Pass envelope to disconnect to avoid another use of CurEnv, which
+               can apparently end up being null at inopportune times.
+       Log "received from" as "relay=" for consistency (suggested by
+               John Gardiner Myers).
+       Fix major bug in header handling:  if no From: line existed in
+               the header (so sendmail inserts one), and the sender is
+               an alias that has an owner, the From: line shows the
+               owner (as well as the envelope).  Fixed by early binding
+               the headers (which will change debugging output).
+       HPUX portability patches from Michael J. Corrigan of UC San Diego.
+       Some attempts to adapt better to out of open file conditions.
+       Some changes to ctladdr handling in queue files.
+
+6.37/6.17      93/03/16
+       MAJOR CHANGE:  delete e_sender and e_returnpath (why are these
+               different from e_from?) and $< macro.
+       Log correct IP address in relay= field even if the connection
+               times out.
+       Log "received from [RESPONSE]" on EF_RESPONSE messages (from
+               John Gardiner Myers).
+       Fixes to SysExMsg logging (sometimes just got "message: %s"
+               instead of "message: error message"), noted by Eric
+               Wassenaar.  Also reported by Nakamura Motonori.
+       Improvements to MX piggybacking code, from Nakamura Motonori.
+       Fix case where CurHostName points to an auto variable that has
+               been deallocated (from Nakamura Motonori).
+       Fix bug causing newlines to be included in aliases if option
+               "n" (check alias RHS) is set; bug noted by David Muir
+               Sharnoff.
+       Fix problem causing user names that should be mapped to lower
+               case to not be mapped if they are sent during a queue
+               run.  This greatly simplifies the case mapping code.
+               Problem noted by Allan E Johannesen of WPI.
+       Don't do recipient address rewriting in buildaddr.  This
+               improperly did recipient rewriting on sender addresses,
+               and just seems bogus in general -- but the change could
+               break some .cf files.
+       Pass TZ envariable to child processes for System V.
+       CONFIG: allow LOCAL_RULE_1 and LOCAL_RULE_2 if you want to
+               define those rulesets.
+       KNOWN PROBLEM:  I have seen some problems on SunOS that causes
+               the User Data Base to give errors on some addresses.  I
+               have tracked the problem back at least as far as 93.02.15
+               (version 6.22).  Running with debugging on makes it
+               go away, so I conclude that it is referencing uninitialized
+               stack data.  I haven't been able to track this down yet.
+
+6.36/6.16      93/03/08
+       Allow local mailer to specify $@host -- this lets you assign the
+               "foo" part of jgm+foo to $h for passing in to the local
+               mailer.
+       Additional debug printing in getcanonname (show query type).
+       Don't add the e_fromdomain on sender addresses -- this interacts
+               wierdly with the owner- code.
+       Improve delivery logging to not log obvious or meaningless stuff.
+       Include numeric IP address in Received: lines per RFC 1123 section
+               5.2.8.
+       Fixed a bug in checking stat() return value if restrictmailq is
+               set.  Also, check the entire group set instead of just the
+               primary group.  Both from John Gardiner Myers.
+       Don't have usrerr automatically print errno, since this is often
+               misleading.
+       Use transienterror() in makeconnection after connect() fails and
+               in openmailer after execve() fails (from Eric Wassenaar).
+               Also moved transienterror() from util.c to conf.c.
+       Clean up from= logging on response messages.
+       Undo patch allowing prescan to return a null vector -- it breaks
+               too many things.
+       Config: FEATURE(notsticky) lets you use UDB for everything coming
+               in to the machine, even if it is specifically targetted
+               to this machine.  Without it, UDB is bypassed if the user
+               name is fully qualified.
+       Config: fix another minor botch with <> (local mailer wasn't
+               mapping them properly).
+
+6.35/6.15      93/03/05
+       Fix getrealhostname to return null if sinlen <= 0 -- this can
+               occur if stdin is a pipe.
+       Avoid infinite loop in getcanonname if name server return
+               NO_DATA (for example).
+       Config: avoid having C flag qualify list syntax and error syntax.
+
+6.34/6.14      93/03/05
+       Fix logging in deliver to not pass too many parameters to Ultrix
+               versions of syslog.
+       Don't write the pid file until after the daemon has actually
+               opened and conditioned the connection.
+       Consider addresses "different" if their q_uids differ (so that
+               two users forwarding to the same program will be seen
+               as different, rather than the same).
+       Fix problem with bad parameters in main() -- they set ExitStat
+               but don't exit.
+       Fix null pointer references through RealHostName -- painfully
+               discovered by Allan E Johannesen of WPI.
+       Fix bug causing user@@localhost to core dump (yuch).
+       Config: don't put two @host.dom.ain on users in $=E in SMTP
+               mailer.  Also, catch user@ (no host) in ruleset 0.
+
+6.33/6.13      93/03/03
+       Config: add confCW_FILE as the name of the cw configuration file
+               (defaults to /etc/sendmail.cw).  From P{r Emanuelsson.
+       Allow prescan to return a pointer to an empty list -- this is
+               not an error.  Also, clean up error reporting to avoid
+               double errors (prescan reports once, then the caller
+               reports again).
+       Changes to avoid trusting T_ANY queries -- run them, but if you
+               don't get the info you expected, do T_A and T_MX queries
+               anyhow.  This also fixes an oversight where _res.options
+               bits were being ignored.
+       If PRIV_NOVRFY is set, use 252 response code instead of 502 per
+               RFC 1123 section 5.2.3.  It's not 100% clear that this
+               is correct, but it probably works better with stupid
+               mailers that do a VRFY and only check the first digit.
+
+6.32/6.12      93/03/02
+       Fix uninitialized variable "protocol" in smtp code.
+       Include <unistd.h> in sendmail.h -- move towards POSIX/ANSI.
+       Additional hooks for RFC 1427 (ESMTP SIZE extension).  This
+               includes requiring that enoughspace() know the system
+               block size, which will undoubtedly break most ports.
+       Trace flag 19 in use for srvrsmtp.c.
+       Additional logging -- notably the sending mailer name.  This
+               also changes the delivery logging to strict field=value
+               syntax.
+       Fix some problems with messages getting sent even to addresses
+               that had been marked bad -- from Eric Wassenaar.
+       More WIDE changes: accept host name inside [...] as non-MXed
+               host.  This is intended ONLY for use inside firewalled
+               environments, where the MX points at the gateway.
+       Change .cf file conventions so that mapping for <> addresses
+               don't have an @ in them (to avoid confusing the C mailer
+               flag).  Pointed out by Neil Rickert.
+       Config extensions for Sam Leffler's FlexFAX software.
+
+6.31/6.10      93/02/28
+       Fix some more bugs in alias owner code -- there were some wierd
+               cases where an error in a non-aliased name would override
+               the return info in an aliased name with an owner.
+       Changes from WIDE Project, forwarded to me by Nakamura Motonori:
+               Log actual delivery host (after MX et al); from
+                       yasuhiro@dcl.co.jp.
+               Log daemon startup.
+               Deliver Postmaster copies without a body.
+               Better logging of SMTP senders.
+               Send all program email as daemon even when local.
+       As requested in various forms from many people, accept -qIstring
+               to limit queue runs to jobs with queue-id matching string.
+               Similarly for -qRstring for recipients, -qSstring for
+               senders.
+       Initial hooks for ESMTP support (see RFC 1425).
+       Fixed a syntax error in the UUCP mailer specification that caused
+               core dumps on startup.
+       Check for missing A= or P= arguments in mailer definitions.
+
+6.30/6.10      93/02/27
+       Require FROZENCONFIG compilation flag to include frozen
+               configuration code.  Frozen configuration is really
+               not a very good idea any more, particularly in shared
+               library environments.
+       Do better checking of errno after opens of :include: and .forward
+               files to defer delivery on network and other transient
+               errors.  Suggestion from Craig Everhart.
+       Fix minor botch in read timeout macro processing.
+       Add FEATURE(nouucp) to config files for sites that know absolutely
+               nothing about UUCP.
+       Add built cf files to distribution tape and clarify how to build
+               them if you don't have the Berkeley make.
+       Some sizeof(long) portability changes for the Alpha, from Allan
+               E Johannesen.
+       Add "restrictmailq" privacy flag -- if set, only people in the same
+               group as your queue directory can print the queue.  If you
+               set this, be sure you also restrict access to log files....
+       Fix another bug in owner-list stuff that can cause data files to
+               be "lost".
+       Fix a bug with queue runs that cause forwards to yourself to go
+               into alias/forwarding loops.  I'm still iffy about this
+               fix.
+       Fix from Eric Wassenaar for suppression of return message code.
+
+6.29/6.9       93/02/24
+       Fix yet another problem in alias owner code -- put the wrong return
+               address on the enclosed return-to-sender letter.
+
+6.28/6.9       93/02/24
+       Fix botch in alias owner code that caused it to not operate if the
+               error was detected locally.
+
+6.27/6.9       93/02/24
+       M_LOCAL => M_LOCALMAILER to avoid conflict with Ultrix include
+               file <sys/mount.h>.
+       Miscellaneous bug fixes from Eric Wassenaar:
+               sendmail -bv -t logs the from line even though in verify
+                       mode only.
+               sendmail -v can go into queue mode if shouldqueue returns
+                       TRUE.
+       Add route-addr pruning per RFC 1123 section 5.3.3.  This can be
+               disabled using the "R" option.
+       Delete (always undocumented) -R flag (save original recipients);
+               there are ways to syslog(3) these now.
+       Clean up SMTP reply codes -- specify them as needed in the code,
+               instead of in conf.c -- this was needed during the NCP to
+               TCP transition, but seems silly now.  This also changes
+               parameters to message and nmessage.
+       Have mailstats read the .cf file to find the sendmail.st file and
+               get text versions of mailer names.  An initial version of
+               this code was provided by Tuominen Keijo (although the
+               comments indicate the good bits were written by "E.V.").
+       Add yet more System V compatibility hacks.
+       Fix bug in VRFY code (assumes everything must be a local user).
+       Allow specification of any of the hard-wired pathnames in the
+               Makefile.
+       Delete concept of "trusted users" -- this really didn't provide
+               any security anyway, and caused some problems.
+       Delete last vestige of support for the word "at" as an equivalent
+               to the character "@".
+       Propagate owner-foo alias information into the envelope sender.
+               Based on code from John Gardiner Myers.  This is a major
+               semantic change -- beware!
+       Allow $@ on LHS to indicate "match zero" -- this is used to match
+               the null expression.
+
+6.26/6.8       93/02/21
+       Don't "lose" queue runs.  Very important fix from (who else?)
+               Eric Wassenaar.
+       Completely reset state on RSET command -- from Eric Wassenaar.
+       Send error messages and return receipts using an envelope sender
+               of <> regardless of the setting of $n.  Rewriting rules
+               can undo this if they feel the necessity, as might be
+               needed for networks that don't understand the syntax.
+               This is permitted by RFC 821 section 3.6 and required by
+               RFC 1123 section 5.3.3.  THIS REQUIRES VERSION 4 CONFIG
+               FILES because the rulesets must be able to parse <>
+               properly.
+       Don't ever send error messages to "<>" -- they will get sent to
+               the local postmaster or dumped in /usr/tmp/dead.letter
+               instead.  Per RFC 1123 section 5.3.3.
+       Explicitly check for email to yourself as a dotted quad.  You
+               have to call $[ [ ... ] $] to get this.
+       Up the message timeout to five days per RFC 1123 section 5.3.1.1.
+       Make all read timeouts individually configurable, as strongly
+               recommended by RFC 1123 section 5.3.2.
+       Use f_bavail (blocks available to regular users) instead of f_bfree
+               (blocks available to superuser) in free block checks.
+       Change $d macro to be the current time, not the origination time,
+               since this is consistent with how it is used now.
+       Generalization of enoughspace from Eric Wassenaar covering
+               SGI, Apollo, HPUX, Ultrix, and SunOS.
+       Ignore process group signals -- some front ends can do this if
+               you kill a window too quickly.  From Eric Wassenaar.
+       Change umask to 022.
+
+6.25/6.8       93/02/20
+       Close all cached connections before calling mailers and after
+               forking for delivery (caused double closes which resulted
+               in false errors).
+       Add FEATURE(redirect) in config files -- this allows you to alias
+               old addresses to a pointer to the new address that will
+               give a 551 error message, but not deliver the mail.
+       Some code changes to make the 551 errors look pretty.
+       Names of M4 program paths in config files have changed -- they
+               are all XXX_MAILER_PATH now, to match XXX_MAILER_FLAGS.
+       Fix a bug in the QSELFREF code having to do with empty .forward
+               files, reported by Eric Wassenaar.
+       Add option "p" (privacy flags); this allows you to tune how
+               picky the SMTP server will be.  This also adds the
+               confPRIVACY_FLAGS M4 macro in the config files.
+       Add option "b" (minimum blocks free).  If there are fewer than
+               this number of blocks free on the filesystem containing
+               the queue directory, the SMTP MAIL command will return
+               a 452 response and ask you to try again later.  This
+               also adds the confMIN_FREE_BLOCKS M4 macro in the config
+               files.
+       Made VRFY just verify (doesn't expand aliases and .forward files);
+               EXPN does full expansion.  RCPT in queue-only mode also
+               doesn't chase aliases and .forward.
+
+6.24/6.7       93/02/19
+       Increase the number of domain search entries in domain.c to allow
+               for the extra "" entry indicating the root domain.
+               Reported by Nakamura Motonori of Kyoto U.
+       Add a "SMART_HOST" in the configs for UUCP-connected sites that
+               want to forward all mail with extra "@"s to that site.
+               Also allows SMART_HOST, LOCAL_RELAY, and MAIL_HUB to
+               be specified as ``mailer:hostname'' to use an alternate
+               mailer.
+       Clarified and updated some wording in the Operations Guide.
+       Add the "c" mailer flag -- this suppresses all comment parts of
+               addresses (requested by John Curran of NEARnet).
+       Have -v print prompts in -bt mode even if stdin is not a terminal
+               (default behaviour is to be silent if not reading from
+               a terminal).  Suggested by Bryan Costales, ICSI.
+       Move the metacharacters from C0 space (\001-\037) into C1 space
+               (\201-\237).  This also fixes a bunch of potential bugs
+               with G1 characters (\240-\276) in headers relating to
+               negative numbers passed to isspace() et al.
+       Add YP_LAST_MODIFIED and YP_MASTER_NAME to DBM version of alias
+               database if YPCOMPAT is #defined.  Enhancement from
+               Takahiro Kanbe of Fuji Xerox Information Systems Co., Ltd.
+       Add "list" Precedence (-30); this can be used with old sendmails
+               which will map to precedence 0 (which will return error
+               messages).  Suggested by Stephen R. van den Berg.
+       Many bug fixes from Eric Wassenaar of the National Institute for
+                       Nuclear and High-Energy Physics, Amsterdam:
+               Clear timeouts properly on open failures in include().
+               Don't dereference through NULL if no home directory found.
+               Re-establish SIGCHLD signal on System 5 in reapchild().
+               Avoid NULL pointer reference on -pFOO flag.
+               Properly handle backslash escapes in comments.
+               Correctly check reply status on SMTP NOOP command.
+               Properly save SMTP error message if peer gives
+                       "Service Shutting Down" message.
+               Avoid writing to the transcript if it couldn't be opened.
+               Signal errors in SMTP children to parent properly.
+       Handle self references in a list more globally (include a
+               QSELFREF bit in the address flags).  This enhancement
+               was suggested by Eric Wassenaar.
+       Use initgroups() in hpux, even though it's System-V based.  The
+               HASINITGROUPS compile flag can set this on other systems.
+               This HPUX behaviour was pointed out by Eric Wassenaar.
+
+6.23/6.6       93/02/16
+       Clean up handling of LogLevel to make it easier to figure out
+               what's on what level.
+       Change log levels to have some consistency:
+               1    serious system failures, security problems
+               2    lost communications, protocol failures
+               3    other serious failures
+               4    minor errors
+               5    message collection
+               6    vrfy logging, creation of return-to-sender
+               7    delivery failures
+               8    delivery successes
+               9    delivery tempfails (queue ups)
+               10   database expansion
+               >64  debugging
+       Allow IDA-style separated processing on S= and R= in Mailer
+               definition lines.  Note that rulesets 1 and 2 are
+               still used for both addresses as before.  Bruce Lilly
+               gave a convincing argument that RFC976 insists on
+               this behaviour.
+       Added some time zones to arpatounix -- they may not be in the
+               standards, but they are in use.  However, I may delete
+               arpatounix entirely -- there appears to be no reason
+               for it to exist.
+       Change to UUCP mailer (in cf directory) to try to do a saner job.
+               I'm still not certain about this mailer in general.
+
+6.22/6.5       93/02/15
+       Fix bug that prevents saving letters in ~/dead.letter.
+       Don't add angle brackets in VRFY command if angle brackets already
+               exist in the address.
+       Fix bogus error message in udbexpand.
+       Null terminate host buffers in buildaddr (broken in 6.21) --
+               IMPORTANT FIX!!
+
+6.21/6.5       93/02/15
+       Fix another incorrect error message in alias.c, found by Azuma
+               Okamoto.
+       Fix a couple of problems in the more-configurable config files,
+               found by Tom Ivar Helbekkmo.
+       Fix problem with quoted :include: entries.
+       Don't duplicate the filename on verbose printing of .forward and
+               :include: contents.
+       Extend size of prescan buffer (to allow bigger addresses).  Also,
+               detect some buffer overflows.
+       Log user SMTP protocol errors (log level 4).
+
+6.20/6.4       93/02/14
+       Fix another problem in the MCI state machine caused when there
+               were errors generated from the other end to commands
+               other than RCPT.
+
+6.19/6.4       93/02/14
+       Include load average support for DEC Alpha running OSF/1.
+       Fix multiple-response problem with errors in MAIL From: line.
+       Fix SMTP reply codes for invalid address syntaxes (give 501;
+               never give multiple error messages for a single message).
+       Fix problem where a cached connection timeout rejects all
+               later connects to that host.
+       Fix incorrect error message if alias.c is compiled with DBM only.
+       Additional changes to fix nested conditionals (from Bruce Lilly).
+       Recover more gracefully from operating system failures, particularly
+               NULL returns from openmailer (from Noritoshi Demizu,
+               OMRON Corporation).
+       Log forward, alias, and userdb expand operations on log level 10;
+               concept suggested by P{r (Pell) Emanuelsson.
+       Changes for HPUX 8.07 compatibility.
+
+6.18/6.4       93/02/12
+       Allow any config option to be set using an M4 define.
+       Change UNAME compile flag to HASUNAME for IDA compatibility
+               (besides, it's a better name).
+       Note in README that on SunOS it must be linked -Bstatic.
+       Fairly major change in domain.c to handle wildcard MX records
+               more rationally.  NOTE: the "w" option (no wildcard MX
+               records match local domain) has been eliminated.
+       Fix some unset variable references pointed out by Bruce Lilly.
+       Fix host name in process titles when using cached connection.
+
+6.17/6.3       93/01/28
+       Fix System 5 compatibility changes to be compatible with the rest
+               of the world.
+
+6.16/6.3       93/01/28
+       Experimental fix for problem handling errors in the SMTP
+               protocol in conjunction with connection caching.
+       System 5 compatibility changes.
+
+6.15/6.3       93/01/26
+       Fix a bug that causes local mail delivered using -odq to be
+               eliminated as a duplicate (because it matched the
+               ctladdr, now passed in as a C line).  These changes
+               are pretty tricky......
+
+6.14/6.3       93/01/25
+       Add debugging for some MCI errors.
+
+6.13/6.3       93/01/22
+       Fix -e compatibility flag to take a value.
+       Fix a couple of minor compilation warnings on Sun cc.
+       Improve error messages in a few cases to be more self-explanatory.
+
+6.12/6.3       93/01/21
+       Fix yet-another problem with environment handling, pointed out
+               by Yoshitaka Tokugawa and Tom Ivar Helbekkmo.
+       Some heuristics to try to limit resource exhaustion problems
+               if a downstream host has been down for a long time.
+       Fix problem with incorrect host name being logged in "Connection
+               timed out" messages (from Tom Ivar Helbekkmo).
+       Fix some ANSI C problems (from Takahiro Kanbe).
+       Properly log message sender on returned mail during queue run.
+       Count number of recipients properly.
+       Fix a problem in yp map code.
+       Diagnose "message timed out" (from Nakamura Motonori).
+
+6.11/6.3       93/01/20
+       Fix problem with address delimitor inside quotes.
+       Define $k and $=k to be the UUCP name (from the uname call)
+               based on code from Bruce Lilly.
+
+6.10/6.2       93/01/18
+       Implement arpatounix (largely code from Bruce Lilly).
+       Log more info (suggested by John Myers).
+       Allow nested $?...$|...$. (inspired by code from Bruce Lilly of
+               Sony US).
+       POSIX compatibility (noted by Keith Bostic).
+       Handle SMTP MAIL command errors properly (urged by several people,
+               notably John Myers of CMU).
+       Do early diagnosis of .cf errors (notably referencing a RHS
+               substitution that isn't on the LHS).
+       Adjust checkpointing to better handle batched recipients, suggested
+               by John Myers.
+       Fix miscellaneous bugs.
+       (config files:)  Implement MAIL_HUB for all local mail (to handle
+               NFS-mounted directories) as urged by Tom Ivar Helbekkmo
+               of the Norwegian School of Economics.
+
+6.9/6.1        93/01/13
+       Environment handling simplification/bug fix -- child processes
+               get a minimal, fixed environment.  This avoids different
+               behaviour in queue runs.
+       Handle commas inside comments properly.
+       Properly limit large messages submitted in -obq mode.
+
+6.8/6.1                93/01/10
+       Check mtime of thaw file against .cf and sendmail binary, based on
+               code from John Myers.
+
+6.7/6.1                93/01/10
+       MX piggybacking, based on code from John Myers@CMU.
+       Allow checkcompat to return -1 to mean tempfail.
+       Bug fix in m_mno computation.
+
+6.6/6.1                93/01/09
+       Tuning of queueing functions as recommended by John Gardiner Myers.
+       Return mail headers (no body) on messages with negative precedence.
+       Minor other bug fixes.
+
+6.5/6.1                93/01/03
+       Fix botch causing queued headers to have ?XX? prefixes.
+
+6.4/6.1                93/01/02
+       Changes to recognize special mailer types (e.g., file) early.
+
+6.3/6.1                93/01/01
+       Pass timeouts to sfgets.
+       Check for control characters in addresses.
+       Fixed deferred error reporting.
+       Report duplicate aliases.
+       Handle mixed case recursive aliases.
+       Misc bug fixes.
+
+6.2/6.1                92/12/30
+       Put return-receipt-to on a conf.c flag (but don't set it).
+       Fix minor syslog problem.
index cda1a6e..1948bd2 100644 (file)
-INTRODUCTION:
--------------
 
 
-This document describes (in some detail, though undoubtedly not enough!)
-the sendmail configuration files currently in use at Berkeley as distributed
-with version 5.61 of sendmail.  It discusses the configuration file
-directory hierarchy, how the files are processed by m4(1), what functionality
-the files provide, what m4(1) options can be used to produce specific
-results, and goes through an example or two.  It concludes with a list
-of things that will change in the next release of the configuration files.
 
 
-This is a working draft; your comments are appreciated.  Please send your
-suggestions to Phil Lapsley, phil@ucbvax.berkeley.edu, ...!ucbvax!phil.
+               NEW SENDMAIL CONFIGURATION FILES
+
+               Eric Allman <eric@CS.Berkeley.EDU>
+
+               @(#)README      8.1 (Berkeley) 6/27/93
+
+
+This document describes the sendmail configuration files being used
+at Berkeley.  These use features in the new (R6) sendmail, and although
+there is an ``OLDSENDMAIL'' mode, they haven't really been tested on
+old versions of sendmail and cannot be expected to work well.
+
+These configuration files are probably not as general as previous
+versions, and don't handle as many of the wierd cases automagically.
+I was able to simplify by them for two reasons.  First, the network
+has become more consistent -- for example, at this point, everyone
+on the internet is supposed to be running a name server, so hacks to
+handle NIC-registered hosts can go away.  Second, I assumed that a
+subdomain would be running SMTP internally -- UUCP is presumed to be
+a long-haul protocol.  I realize that this is not universal, but it
+does describe the vast majority of sites with which I am familiar,
+including those outside the US.
+
+Of course, the downside of this is that if you do live in a wierd
+world, things are going to get wierder for you.  I'm sorry about that,
+but at the time we at Berkeley had a problem, and it seemed like the
+right thing to do.
+
+This package requires a post-V7 version of m4; if you are running the
+4.2bsd, SysV.2, or 7th Edition version, I suggest finding a friend with
+a newer version.  You can m4-expand on their system, then run locally.
+SunOS's /usr/5bin/m4 or BSD-Net/2's m4 both work.  GNU m4 (which is a
+language unto itself) also works, but I don't intend to work so hard
+to keep this up in the future.  [Note to GNU folks:  the construct
+"define(`FOO')" should work without my having to add a null value.]
+
+IF YOU DON'T HAVE A BERKELEY MAKE, don't despair!  Just run
+"m4 foo.mc > foo.cf" -- that should be all you need.
+
+To get started, you may want to look at tcpproto.mc (for TCP-only
+sites) and uucpproto.m4 (for UUCP-only sites).  Others are versions
+that we use at Berkeley, although not all are in current use.  For
+example, ucbarpa has gone away, but I've left ucbarpa.mc in because
+it demonstrates some interesting techniques.
+
+I'm not pretending that this README describes everything that these
+configuration files can do; clever people can probably tweak them
+to great effect.  But it should get you started.
+
+
++--------------------------+
+| INTRODUCTION AND EXAMPLE |
++--------------------------+
+
+Configuration files are contained in the subdirectory "cf", with a
+suffix ".mc".  They must be run through "m4" to produce a ".cf" file.
+
+Let's examine a typical .mc file (cf/cs-exposed.mc):
+
+       divert(-1)
+       #
+       # Copyright (c) 1983 Eric P. Allman
+       # Copyright (c) 1988 The Regents of the University of California.
+       # All rights reserved.
+       #
+       # Redistribution and use in source and binary forms are permitted
+       # provided that the above copyright notice and this paragraph are
+       # duplicated in all such forms and that any documentation,
+       # advertising materials, and other materials related to such
+       # distribution and use acknowledge that the software was developed
+       # by the University of California, Berkeley.  The name of the
+       # University may not be used to endorse or promote products derived
+       # from this software without specific prior written permission.
+       # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+       # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+       # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+       #
+
+The divert(-1) will delete the crud in the resulting output file.
+The copyright notice is what your lawyers require.  Our lawyers require
+the one that I've included in my files. A copyleft is a copyright by
+another name.
+
+The next line MUST be
+
+       include(`../m4/cf.m4')
+
+This will pull in the M4 macros you will need to make sense of
+everything else.  As the saying goes, don't think about it, just
+do it.  If you don't do it, don't bother reading the rest of this
+file.
+
+       VERSIONID(`<SCCS or RCS version id>')
+
+VERSIONID is a macro that stuffs the version information into the
+resulting file.  We use SCCS; you could use RCS, something else, or
+omit it completely.  This is not the same as the version id included
+in SMTP greeting messages -- this is defined in m4/version.m4.
+
+       DOMAIN(cs.exposed)
+
+This example exposes the host inside of the CS subdomain -- that is,
+it doesn't try to hide the name of the workstation to the outside
+world.  Changing this to DOMAIN(cs.hidden) would have made outgoing
+messages refer to "<username>@CS.Berkeley.EDU" instead of using the
+local hostname.  Internaly this is effected by using
+"MASQUERADE_AS(CS.Berkeley.EDU)".
+
+       MAILER(smtp)
+
+These describe the mailers used at the default CS site site.  The
+local mailer is always included automatically.
+
+
++--------+
+| OSTYPE |
++--------+
+
+Note that cf/cs-exposed.mc omits an OSTYPE macro -- this assumes
+default Computer Science Division environment.  There are several
+explicit environments available: bsd4.3, bsd4.4, hpux, irix, osf1,
+riscos4.5, sunos3.5, sunos4.1, and ultrix4.1.  These change things
+like the location of the alias file and queue directory.  Some of
+these files are identical to one another.
+
+Operating system definitions are easy to write.  They may define
+the following variables (everything defaults, so an ostype file
+may be empty).
+
+ALIAS_FILE             [/etc/aliases] The location of the text version
+                       of the alias file(s).  It can be a comma-separated
+                       list of names.
+HELP_FILE              [/usr/lib/sendmail.hf] The name of the file
+                       containing information printed in response to
+                       the SMTP HELP command.
+QUEUE_DIR              [/var/spool/mqueue] The directory containing
+                       queue files.
+STATUS_FILE            [/etc/sendmail.st] The file containing status
+                       information.
+LOCAL_MAILER_PATH      [/bin/mail] The program used to deliver local mail.
+LOCAL_MAILER_FLAGS     [rn] The flags used by the local mailer.  The
+                       flags lsDFMm are always included.
+LOCAL_SHELL_PATH       [/bin/sh] The shell used to deliver piped email.
+USENET_MAILER_PATH     [/usr/lib/news/inews] The name of the program
+                       used to submit news.
+USENET_MAILER_FLAGS    [rlsDFMmn] The mailer flags for the usenet mailer.
+USENET_MAILER_ARGS     [-m -h -n] The command line arguments for the
+                       usenet mailer.
+SMTP_MAILER_FLAGS      [undefined] Flags added to SMTP mailer.
+UUCP_MAILER_FLAGS      [undefined] Flags added to UUCP mailer.
+HOSTMAP_SPEC           [dbm -o /etc/hostmap] The value for the builtin
+                       hostmap key definition.  You can redefine this
+                       to change the class, flags, and filename of
+                       the hostmap.  The default flag (-o) makes this
+                       map optional.
+
+In addition, the following boolean flags may be defined -- the value
+is ignored.
+
+NEED_DOMAIN            If set, the $j macro is defined as $w.$D.
+                       If not set, $j is defined as $w.  If this is
+                       set, the domain must be defined using the line
+                       DD<domainname> (probably in the domain file,
+                       but possibly in the .mc file).  You will only
+                       need this if you define your system hostname
+                       without a domain (type "hostname" -- if it
+                       has no dots in the output, you qualify) AND
+                       if you are not running the nameserver AND if
+                       the first (canonical) name in /etc/hosts for
+                       your machine has no domain -- OR if you are
+                       running Ultrix or OSF/1 sendmail.  Either of
+                       these is probably a mistake.
+
++---------+
+| DOMAINS |
++---------+
+
+You will probably want to collect domain-dependent defines into one
+file, referenced by the DOMAIN macro.  For example, our Berkeley
+domain file includes definitions for several internal distinguished
+hosts:
+
+UUCP_RELAY     The host that will forward UUCP-addressed email.
+               If not defined, all UUCP sites must be directly
+               connected.
+BITNET_RELAY   The host that will forward BITNET-addressed email.
+               If not defined, the .BITNET pseudo-domain won't work.
+CSNET_RELAY    The host that will forward CSNET-addressed email.
+               If not defined, the .CSNET pseudo-domain won't work.
+LOCAL_RELAY    The site that will handle unqualified names -- that
+               is, names with out an @domain extension.  If not set,
+               they are assumed to belong on this machine.  This
+               allows you to have a central site to store a
+               company- or department-wide alias database.  This
+               only works at small sites, and there are better
+               methods.
+
+The domain file can also be used to define a domain name, if needed
+(using "DD<domain>") and set certain site-wide features.  If all hosts
+at your site masquerade behind one email name, you could also use
+MASQUERADE_AS here.
+
+You do not have to define a domain -- in particular, if you are a
+single machine sitting off somewhere, it is probably more work than
+it's worth.  This is just a mechanism for combining "domain dependent
+knowledge" into one place.
+
++---------+
+| MAILERS |
++---------+
+
+There are fewer mailers supported in this version than the previous
+version, owing mostly to a simpler world.
+
+local          The local and prog mailers.  You will almost always
+               need these; the only exception is if you relay ALL
+               your mail to another site.  This mailer is included
+               automatically.
+
+smtp           The Simple Mail Transport Protocol mailer.  This does
+               not hide hosts behind a gateway or another other
+               such hack; it assumes a world where everyone is
+               running the name server.
+
+uucp           The Unix-to-Unix Copy Program mailer.  Actually, this
+               defines two mailers, "uucp" and "suucp".  The latter
+               is for when you know that the UUCP mailer at the other
+               end can handle multiple recipients in one transfer.
+               When you invoke this, sendmail looks for all names in
+               the $=U class and sends them to the uucp mailer; all
+               names in the $=Y class are sent to suucp.  Note that
+               this is a function of what version of rmail runs on
+               the receiving end, and hence may be out of your control.
+
+usenet         Usenet (network news) delivery.  If this is specified,
+               an extra rule is added to ruleset 0 that forwards all
+               local email for users named ``group.usenet'' to the
+               ``inews'' program.  Note that this works for all groups,
+               and may be considered a security problem.
+
+fax            Facsimile transmission.  This is experimental and based
+               on Sam Leffler's FlexFAX software.  For more information,
+               see below.
+
+
++----------+
+| FEATURES |
++----------+
+
+Special features can be requested using the "FEATURE" macro.  For
+example, the .mc line:
+
+       FEATURE(use_cw_file)
+
+tells sendmail that you want to have it read an /etc/sendmail.cw
+file to get values for class $=w.  The FEATURE may contain a single
+optional parameter -- for example:
+
+       FEATURE(mailertable, dbm /usr/lib/mailertable)
+
+Available features are:
+
+use_cw_file    Read the file /etc/sendmail.cw file to get alternate
+               names for this host.  This might be used if you were
+               on a host that MXed for a dynamic set of other
+               hosts.  If the set is static, just including the line
+               "Cw<name1> <name2> ..." is probably superior.
+               The actual filename can be overridden by redefining
+               confCW_FILE.
+redirect       Reject all mail addressed to "address.REDIRECT" with
+               a ``551 User not local; please try <address>'' message.
+               If this is set, you can alias people who have left
+               to their new address with ".REDIRECT" appended.
+nouucp         Don't do anything special with UUCP addresses at all.
+nocanonify     Don't pass addresses to $[ ... $] for canonification.
+               This would generally only be used by sites that only
+               act as mail gateways or which have user agents that do
+               full canonification themselves.
+notsticky      By default, email sent to "user@local.host" are marked
+               as "sticky" -- that is, the local addresses aren't
+               matched against UDB and don't go through ruleset 5.
+               This features disables this treatment.  It would
+               normally be used on network gateway machines.
+mailertable    Include a "mailer table" which can be used to override
+               routing for particular domains.  The argument of the
+               FEATURE may be the key definition.  If none is specified,
+               the definition used is:
+                       hash /etc/mailertable.db -o
+               Keys in this database must be of the form:
+                       mailer:domain
+bitdomain      Look up bitnet hosts in a table to try to turn them into
+               internet addresses.  The table can be built using the
+               bitdomain program contributed by John Gardiner Meyers.
+               The argument of the FEATURE may be the key definition; if
+               none is specified, the definition used is:
+                       hash /etc/bitdomain.db -o
+               Keys are the bitnet hostname; values are the corresponding
+               internet hostname.
+uucpdomain     Similar feature for UUCP hosts.  The default map definition
+               is:
+                       hash /etc/uudomain.db -o
+               At the moment there is no automagic tool to build this
+               database.
+always_add_domain
+               Include the local host domain even on locally delivered
+               mail.  Normally it is not added unless it is already
+               present.
+
+Other FEATUREs should be defined, but I was trying to keep these
+config files fairly lean and mean.
+
+
++-------+
+| HACKS |
++-------+
+
+Some things just can't be called features.  To make this clear,
+they go in the hack subdirectory and are referenced using the HACK
+macro.  These will tend to be site-dependent.  The release
+includes the Berkeley-dependent "cssubdomain" hack (that makes
+sendmail accept local names in either Berkeley.EDU or CS.Berkeley.EDU;
+this is intended as a short-term aid while we move hosts into
+subdomains.
+
+
++--------------------+
+| SITE CONFIGURATION |
++--------------------+
+
+Complex sites will need more local configuration information, such as
+lists of UUCP hosts they speak with directly.  This can get a bit more
+tricky.  For an example of a "complex" site, see cf/ucbvax.mc.
+
+The SITECONFIG macro allows you to indirectly reference site-dependent
+configuration information stored in the siteconfig subdirectory.  For
+example, the line
+
+       SITECONFIG(uucp.ucbvax, ucbvax, U)
+
+reads the file uucp.ucbvax for local connection information.  The
+second parameter is the local name (in this case just "ucbvax" since
+it is locally connected, and hence a UUCP hostname) and the name of
+the class in which to store the host information.  Another SITECONFIG
+line reads
+
+       SITECONFIG(uucp.ucbarpa, ucbarpa.Berkeley.EDU, W)
+
+This says that the file uucp.ucbarpa contains the list of UUCP sites
+connected to ucbarpa.Berkeley.EDU.  The $=W class will be used to
+store this list.  [The machine ucbarpa is gone now, but I've left
+this out-of-date configuration file around to demonstrate how you
+might do this.]
+
+The siteconfig file (e.g., siteconfig/uucp.ucbvax.m4) contains nothing
+more than a sequence of SITE macros describing connectivity.  For
+example:
+
+       SITE(cnmat)
+       SITE(sgi olympus)
 
 
+The second example demonstrates that you can use two names on the
+same line; these are usually aliases for the same host (or are at
+least in the same company).
+
+
++-------------------+
+| TWEAKING RULESETS |
++-------------------+
 
 
-HIERARCHY:
-----------
+For more complex configurations, you can define special rules.
+The macro LOCAL_RULE_3 introduces rules that are used in canonicalizing
+the names.  Any modifications made here are reflected in the header.
 
 
-The "cf" subdirectory is organized as follows:
+A common use is to convert old UUCP addreses to SMTP addresses using
+the UUCPSMTP macro.  For example:
 
 
-                                       cf
-                                       |
-                       +---------------+---------------+
-                       |               |               |
-                     sitedep           m4              cf
-                       |               |             /    \
-                       *.m4            *.m4        *.mc   *.cf
+       LOCAL_RULE_3
+       UUCPSMTP(decvax,        decvax.dec.com)
+       UUCPSMTP(research,      research.att.com)
 
 
-where the directories contain the following:
+will cause addresses of the form "decvax!user" and "research!user"
+to be converted to "user@decvax.dec.com" and "user@research.att.com"
+respectively.
 
 
-       sitedep         Site dependent parts of configuration files
-                       in m4(1) include files.
+This could also be used to look hosts in a database map:
 
 
-       m4              Site independent parts of configuration files
-                       in m4(1) include files.
+       LOCAL_RULE_3
+       R$* < @ $+ > $*         $: $1 < @ $(hostmap $2 $) > $3
 
 
-       cf              Includes "master configuration" (.mc) files
-                       that include m4 files from ../m4 and ../sitedep.
-                       .mc files are processed by m4(1) and result in
-                       configuration files (.cf).
+This map would be defined in the LOCAL_CONFIG portion, as shown below.
 
 
-In the remainder of this document, all path names are referenced
-relative to the top level "cf" directory.  Hence, the m4 subdirectory
-is called "cf/m4".
+Similarly, LOCAL_RULE_0 can be used to introduce new parsing rules.
+For example, new rules are needed to parse hostnames that you accept
+via MX records.  For example, you might have:
 
 
+       LOCAL_RULE_0
+       R$+ < @ cnmat.Berkeley.EDU >    $#uucp $@ cnmat $: $1
 
 
-WHERE m4(1) FITS INTO ALL OF THIS:
-----------------------------------
+You would use this if you had installed an MX record for cnmat.Berkeley.EDU
+pointing at this host; this rule catches the message and forwards it on
+using UUCP.
 
 
-Configuration files are built by typing "make" in cf/cf.  This
-runs m4(1) on the .mc files in cf/cf and produces .cf files.
+You can also tweak rulesets 1 and 2 using LOCAL_RULE_1 and LOCAL_RULE_2.
+These rulesets are normally empty.
 
 
-The philosophy at Berkeley is to place as much information into
-one .mc file as possible, and then use m4 conditional substitution
-(ifdef, for example) to produce other configuration files from it.
-This results in a substantial reduction of duplicated code that must
-be maintained separately.
+A similar macro is LOCAL_CONFIG.  This introduces lines added after the
+boilerplate option setting but before rulesets, and can be used to
+declare local database maps or whatever.  For example:
 
 
-The main master configuration file that contains all this information
-is "cf/proto.mc".  This file has a number of m4 conditional substitutions
-that can be controlled by other .mc files that include "cf/proto.mc".
+       LOCAL_CONFIG
+       Khostmap hash /etc/hostmap.db
+       Kyplocal nis -m hosts.byname
 
 
-For example, most hosts at Berkeley have only SMTP (TCP) connections
-to other hosts.  A file called "ucbproto.cf" takes care of these
-machines by defining the m4 flags needed to produce only SMTP mailer
-definitions from "cf/proto.mc".  Since this is default behavior, very
-little needs to be defined.
 
 
-But some hosts at Berkeley (e.g., cad.Berkeley.EDU) have both SMTP
-connections and UUCP connections as well.  Thus, they need to
-produce a configuration file that contains both SMTP and UUCP mailer
-definitions, and they need to include a list of directly connected
-UUCP neighbors.  The file "cf/cad.mc" does this by setting the m4
-flags for "cf/proto.mc" that say "(1) I am a UUCP host with hostname "ucbcad",
-(2) a list of my UUCP neighbors can be found in ../sitedep/uucp.cad.m4".
++---------------------------+
+| MASQUERADING AND RELAYING |
++---------------------------+
 
 
-Thus, there are many .mc files in cf/cf that simply define m4 flags and
-then include "cf/proto.mc" to produce a specific configuration file.
+You can have your host masquerade as another using
 
 
-Note:
+       MASQUERADE_AS(host.domain)
 
 
-       IT IS STRONGLY SUGGESTED THAT YOU, THE SYSTEM MANAGER,
-       CONTINUE TO MAINTAIN CONFIGURATION FILES BY USING THIS
-       m4(1) METHOD.  TRYING TO MAINTAIN MULTIPLE .CF FILES
-       ON SEPARATE MACHINES WILL LEAD TO INSANITY.
+This causes outgoing SMTP mail to be labelled as coming from the
+indicated domain, rather than $j.  One normally masquerades as one
+of your own subdomains (for example, it's unlikely that I would
+choose to masquerade as an MIT site).
 
 
+there are always users that need to be "exposed" -- that is, their
+internal site name should be displayed instead of the masquerade name.
+Root is an example.  You can add users to this list using
 
 
-With that out of the way, we should now examine the functionality
-provided by the supplied sendmail configuration files, and then
-talk in detail about the m4(1) options that control this.
+       EXPOSED_USER(usernames)
 
 
-FUNCTIONALITY PROVIDED BY THE SUPPLIED SENDMAIL CONFIGURATIONS:
----------------------------------------------------------------
-
-Mailers:
---------
-
-The sendmail configuration files come with the following mailers:
+This adds users to class E; you could also use something like
 
 
-       local           For delivery of messages to users on the
-                       local machine.
+       FE/etc/sendmail.cE
 
 
-       tcp             For SMTP delivery of messages across the
-                       the Internet.
-
-       tcpld           For SMTP delivery of messages within the
-                       local domain.
+You can also arrange to relay all unqualified names (that is, names
+without @host) to a relay host.  For example, if you have a central
+email server, you might relay to that host so that users don't have
+to have .forward files or aliases.  You can do this using
 
 
-       uucp            For delivery of messages to a UUCP neighbor.
+       define(`LOCAL_RELAY', mailer:hostname)
 
 
-       smtpuucp        For delivery of messages to a UUCP neighbor
-                       with whom we also share Internet connectivity.
+The ``mailer:'' can be omitted, in which case the mailer defaults to
+"smtp".  There are some user names that you don't want relayed, perhaps
+because of local aliases.  A common example is root, which may be
+locally aliased.  You can add entries to this list using
 
 
-The tcp/tcpld mailers and the smtpuucp mailers deserve a little more
-explanation.
+       LOCAL_USER(usernames)
 
 
-The "tcp" and "tcpld" mailers:
-------------------------------
+This adds users to class L; you could also use something like
 
 
-As regards tcp and tcpld: in theory, there should be only one mailer
-here, called "smtp", that deals with addresses in the form "user@host.domain".  
-Everyone on the Internet would use this, regardless of what domain
-they were in.  Host name lookups would be performed via the domain naming
-system (DNS), and no central registry of machine names would be necessary.
+       FL/etc/sendmail.cL
 
 
-Unfortunately, this is not the case.  The MILNET community is still
-in transition towards the DNS, and until this transition is complete,
-they do not have to use the nameserver.  Rather, they can "legally"
-still use the host table supplied by SRI-NIC to translate names to
-addresses.  This means that to be strictly legal, we must send out
-messages in the form "user@host.domain" ONLY FOR machines that are
-registered with SRI NIC.  Machines that are not registered with the
-NIC must be "hidden" behind a relay machine, e.g.,
-user%unregistered_host@registered_host.domain.  This, when MILNET folks
-reply to this, the mail passes through "registered_host.domain" first.
+If you want all mail sent to a centralized hub, as for a shared
+/var/spool/mail scheme, use
 
 
-Currently this "hiding" behind NIC registered hosts is performed by
-the "tcp" mailer.
+       define(`MAIL_HUB', mailer:hostname)
 
 
-Since you don't want to register all the hosts at your site with
-the NIC (and they don't want you to!), the "tcpld" mailer was created.
-The idea here is that you KNOW all the hosts in your local domain
-use the nameserver, so there is no need to hide mail behind a NIC
-registered relay -- that would only slow things down.  So the "tcpld"
-does not do any hiding of unregistered hosts behind a registered relay.
+Again, ``mailer:'' defaults to "smtp".  If you define both LOCAL_RELAY
+and MAIL_HUB, unqualified names and names in class L will be sent to
+the LOCAL_RELAY and other local names will be sent to MAIL_HUB.  For
+example, if are on machine mastodon.CS.Berkeley.EDU, the following
+combinations of settings will have the indicated effects:
 
 
-Eventually the "tcpld" mailer will become the "smtp" mailer mentioned above.
+email sent to....      eric                      eric@mastodon.CS.Berkeley.EDU
 
 
-The "smtpuucp" mailer:
-----------------------
+LOCAL_RELAY set to     mail.CS.Berkeley.EDU      (delivered locally)
+mail.CS.Berkeley.EDU
 
 
-The "smtpuucp" mailer is another fun one.  As time progresses, many
-hosts with whom one has UUCP connections join the Internet.  Unfortunately,
-if the UUCP connection existed for any length of time, people are
-probably used to using it, complete with the bangist syntax that comes
-with UUCP.  As a result, many sites elect to keep their
-UUCP connections even though they have TCP/IP connectivity to the sites
-in question.  This turns out not be such a good idea because of the
-double-queuing incurred by UUCP, explained in the following example.
+MAIL_HUB set to                mammoth.CS.Berkeley.EDU   mammoth.CS.Berkeley.EDU
+mammoth.CS.Berkeley.EDU
 
 
-For concreteness, consider the following scenario: ucbvax.Berkeley.EDU
-(UUCP host "ucbvax") and decvax.dec.com (UUCP host "decvax") have shared
-a cross county UUCP link that is heavily used by many people.  Let's say
-that a piece of mail is routed through the ucbvax-decvax link via UUCP.
-The queueing process is:
+Both LOCAL_RELAY and   mail.CS.Berkeley.EDU      mammoth.CS.Berkeley.EDU
+MAIL_HUB set as above
 
 
 
 
-step   host    action
------  -----   ------
-1      ucbvax  incoming mail is accepted via UUCP
-2      ucbvax  uuxqt is queued to invoke sendmail.
-3      ucbvax  sendmail parses the message.
-4      ucbvax  sendmail passes the message to the UUCP
-               mailer for delivery to decvax.
-5      ucbvax  message is placed in the outgoing UUCP queue for decvax
++-------------------------------+
+| NON-SMTP BASED CONFIGURATIONS |
++-------------------------------+
 
 
-6      decvax  uucico takes the message from ucbvax
-7      decvax  uuxqt is queued to invoke sendmail
-8      decvax  sendmail parses the message
-9      decvax  sendmail passes the message to someplace else.
+These configuration files are designed primarily for use by SMTP-based
+sites.  I don't pretend that they are well tuned for UUCP-only or
+UUCP-primarily nodes (the latter is defined as a small local net
+connected to the rest of the world via UUCP).  However, there is one
+hook to handle some special cases.
 
 
-Note that the message transited the inbound UUCP queue on ucbvax, the sendmail
-queue on ucbvax, the outbound UUCP queue on ucbvax, the inbound UUCP queue
-on decvax, etc.
+You can define a ``smart host'' that understands a richer address syntax
+using:
 
 
-Now, if decvax and ucbvax have SMTP connectivity, the session is more
-manageable:
+       define(`SMART_HOST', mailer:hostname)
 
 
-step   host    action
------  -----   ------
-1      ucbvax  incoming mail is accepted via UUCP
-2      ucbvax  uuxqt is queued to invoke sendmail.
-3      ucbvax  sendmail parses the message
-4a     ucbvax  sendmail delivers it to decvax.dec.com via SMTP.
+In this case, the ``mailer:'' defaults to "suucp".  Any messages that
+can't be handled using the usual UUCP rules are passed to this host.
 
 
-a      decvax  sendmail accepts the message from ucbvax via SMTP.
-8      decvax  sendmail parses the message.
-9      decvax  sendmail passes it to someplace else.
+If you are on a local SMTP-based net that connects to the outside
+world via UUCP, you can use LOCAL_NET_CONFIG to add appropriate rules.
+For example:
 
 
-Note that old steps (5) and (7), the UUCP queueing, are avoided entirely.
+       define(`SMART_HOST', suucp:uunet)
+       LOCAL_NET_CONFIG
+       R$* < @ $* .$m > $*     $#smtp $@ $2.$m $: $1 < @ $2.$m > $3
 
 
-The only trick to the "smtpuucp" mailer is that even though it uses
-SMTP to communicate with its neighbors, it must use the UUCP syntax
-and rewriting rulesets so that the operation is transparent to the
-outside world.  This is easy enough to do.
+This will cause all names that end in your domain name ($m) via
+SMTP; anything else will be sent via suucp (smart UUCP) to uunet.
 
 
-Other functionality:
--------------------
 
 
-Aside from the mailers supplied, the basic configuration files
-support the following features:
++------------------+
+| FlexFAX SOFTWARE |
++------------------+
 
 
-       * Domains.  Addresses of the form "user@host.domain" are
-         considered to be the basic type of address we deal with.
+Sam Leffler's FlexFAX software is still in beta test -- but he expects a
+public version out "later this week" [as of 3/1/93].  The following
+blurb is direct from Sam:
 
 
-       * Fake domains.  Addresses of the form:
+       $Header: /b/source/CVS/src/usr.sbin/sendmail/cf/README,v 1.3 1993/06/28 22:32:56 glass Exp $
 
 
-               user@host.BITNET
-       and
-               user@host.CSNET
+       How To Obtain This Software (in case all you get is this file)
 
 
-         are forwarded to a CSNET relay host and a BITNET relay host,
-         respectively.
+       The source code is available for public ftp on
+           sgi.com                     sgi/fax/v2.1beta.tar.Z
+               (192.48.153.1)
 
 
-         Note: this feature exists for convenience.  As CSNET and
-         BITNET convert to domains, it will go away.  In particular,
-         "user@host.CSNET" is slated to get the axe in the next release.
+       You can also obtain inst'able images for Silicon Graphics machines from
+           sgi.com                     sgi/fax/v2.1beta.inst.tar
+               (192.48.153.1)
 
 
-m4(1) OPTIONS USED IN THE .MC FILES:
-------------------------------------
+       For example,
+           % ftp -n sgi.com
+           ....
+           ftp> user anonymous
+           ... <type in password>
+           ftp> cd sgi/fax
+           ftp> binary
+           ftp> get v2.1beta.tar.Z
 
 
-The following options, from "most important" to "trivial", can be
-used to control what configuration file you get from running m4(1)
-on "cf/proto.mc".  As explained earlier, the standard practice is to
-create an ".mc" file for a particular configuration that contains
-all the m4(1) macro definitions/flags you want, and then have
-that .mc file include "mc/proto.mc".
+       If you cannot use FTP at all, there is a service called "ftpmail"
+       available from gateekeeper.dec.com:  you can send e-mail to this
+       machine and it will use FTP to retrieve files for you and send you the
+       files back again via e-mail.  To find out more about the ftpmail
+       service, send a message to "ftpmail@gatekeeper.dec.com" whose body
+       consists of the single line "help".
 
 
-Macro name             Example (you must include the ` and ')!
-----------             ---------------------------------------
-
-DOMAIN                 `DDBerkeley.EDU'
-
-     This MUST be defined to be your Internet domain.
-
-INTERNET_RELAY         `DAcad.Berkeley.EDU'
-
-     If defined, this will be the machine behind which non-NIC registered
-hosts are hidden, resulting in addresses of the form
-
-       user%host@internet_relay.domain
-
-e.g.,
-
-       moore%prefect@cad.Berkeley.EDU
-
-     If not defined, outgoing addresses will always be of the form
-
-       user@host.domain
-
-regardless of whether "host.domain" is registered with the NIC.
-
-UUCP_NAME              `DUucbcad'
-
-     If defined, includes the UUCP mailer and assumes you have local
-UUCP connections.  The UUCP_NAME macro is used to define your
-canonical UUCP hostname.  See also: UUCP_ALIASES and UUCP_HOSTS_FILE.
-
-UUCP_ALIASES           `CUucbcad cad'
-
-     Used only if UUCP_NAME is defined, this macro lists any UUCP
-aliases for your machine.  See also: UUCP_NAME and UUCP_HOSTS_FILE.
-
-UUCP_HOSTS_FILE                `../sitedep/uucp.cad.m4'
-
-     Used only if UUCP_NAME is defined.  Defines class V of
-local UUCP hosts by including the appropriate m4 file.  See also:
-UUCP_NAME and UUCP_ALIASES.
-
-UUCP_RELAY             `DRcad.Berkeley.EDU'
-
-     If defined, this will be the machine to which non-local UUCP traffic
-is forwarded.  That is, any address that ends in ".UUCP" that is
-not listed in the V class (as defined by UUCP_HOSTS_FILE) will be
-forwarded to the UUCP_RELAY host via the "tcpld" mailer.
-
-UUCP_ONLY              1
-
-     If defined, makes sure that no TCP/IP based mailers will be
-put in the resulting configuration file.  Normally undefined.
-
-SMTPUUCP               `../sitedep/smtpuucp.cad.m4'
-
-     If defined, use SMTP to resolve certain UUCP connections (while
-keeping UUCP syntax).  Should be defined to be a file that
-contains the list of pairs of UUCP names and their corresponding
-Internet names.  See "machdep/smtpuucp.ucbvax.m4" for an example
-of what this should look like.
-
-BITNET_RELAY           `DBjade.Berkeley.EDU'
-
-     If defined, this will be the machine to which BITNET traffic
-(i.e., mail to user@host.bitnet) is forwarded.  If not defined,
-addresses of the form "user@host.bitnet" will bounce.
-
-CSNET_RELAY            `DCrelay.cs.net'
-
-     If defined, this will be the machine to which CSNET traffic
-(i.e., mail to user@host.csnet) is forwarded.  If not defined, addresses
-of that form will bounce.
-
-ARPAKLUDGE             `1'
-
-     If defined, this turns on a kludge to reduce mail load on your
-INTERNET_GATEWAY.  What is done is the following: if mail is outgoing
-to a machine in the ".arpa" domain and we're not registered with the
-NIC, we hide ourselves behind our INTERNET_GATEWAY.  If the machine
-to which mail is being delivered is NOT in the ".arpa" domain, we
-assume they use the domain name system and can reply to our address --
-hence, we don't hide anywhere.
-
-AN EXAMPLE OR TWO:
-------------------
-
-Let's consider a hypothetical system at Foo, Inc.  Foo, Inc. is on the
-ARPA Internet and is the proud owner of the domain "foo.com".  Machines
-in "foo.com" exchange mail with other hosts on the Internet via SMTP.
-Foo, Inc. also has customers with whom they have UUCP links -- these
-links are all on the machine "uucp-gw.foo.com".  Mail to any address
-that ends in ".UUCP" should be forwarded to "uucp-gw.foo.com".  They
-also have a gateway to the bitnet through their local machine
-"bitnet-gw.foo.com"; mail to any address ending in ".bitnet" should go
-there.  They intend to take advantage of the kind folks at CSNET by
-forwarding mail to "host.csnet" to the machine "relay.cs.net".
-
-The master configuration file for a generic machine on the corporate
-ethernet might look like this:
-
-define(DOMAIN, `DDfoo.com')
-define(UUCP_RELAY, `DRuucp-gw.foo.com')
-define(BITNET_RELAY, `DBbitnet-gw.foo.com')
-define(CSNET_RELAY, `DCrelay.cs.net')
-include(proto.mc)
-
-And that's it!  The system manager at "foo.com" would simply install
-this in the "cf" subdirectory, add a production to the make file,
-and type "make foo.cf".  This would run m4(1) on the .mc file and
-we're done.
-
-Now let's turn to the machine "uucp-gw.foo.com".  It obviously needs
-to have the UUCP mailer compiled in, and it needs a list of UUCP
-neighbors with whom it is connected.  Of course, it also needs a TCP/IP
-(SMTP) based mailer so it can talk to the rest of the company.
-On the UUCP network, "uucp-gw.foo.com" is known as "foo".
-The master configuration file might be:
-
-define(DOMAIN, `DDfoo.com')
-define(UUCP_NAME, `DUfoo')
-define(UUCP_ALIASES, `CUfoo')
-define(UUCP_HOSTS_FILE, `../sitedep/uucp.foo.m4')
-define(BITNET_RELAY, `DBbitnet-gw.foo.com')
-define(CSNET_RELAY, `DCrelay.cs.net')
-include(proto.mc)
-
-Note that we didn't define UUCP_RELAY here, since we ARE the UUCP relay.
-
-The file "../sitedep/uucp.foo.m4" contains a list of our UUCP neighbors:
-
-CV     oink
-CV     bletch
-CV     spam
-
-indicating that "uucp-gw.foo.com" is directly connected to three other
-machines via UUCP: "oink", "bletch", and "spam."
-
-
-WHAT WILL BE CHANGING IN THE NEXT RELEASE:
-------------------------------------------
-
-In the next release, the following things should change:
-
-1. The MILNET should have gotten its act together.  This means
-   that the "tcp" mailer goes away.  The "tcpld" mailer will
-   be renamed "smtp".  The "N" class (NIC registered hosts)
-   gets axed.  The ARPAKLUDGE and INTERNET_RELAY  m4(1) options
-   will disappear as well.
-
-2. The CSNET "fake domain" (i.e., user@host.csnet) will cease
-   to be supported.
-
-3. The "smtp" mailer rulesets (currently 17/27) will be rewritten,
-   along with much of rulesets 0 and 3.
+       Internal to Silicon Graphics there are inst'able images on the host
+       flake.asd in the directory /d/dist.  Thus you can do something like:
+
+           % inst -f flake.asd.sgi.com:/d/dist/flexfax
+
+       to install the software on your machine.
+
+       The external distributions come in a compressed or uncompressed tar
+       file.  To extract the source distribution:
+
+           % zcat v2.1beta.tar.Z | tar xf -
+
+       (uncompress and extract individual files in current directory).  To
+       unpack and install the client portion of the inst'able distribution:
+
+           % mkdir dist
+           % cd dist; tar xf ../v2.1beta.inst.tar; cd ..
+           % inst -f dist/flexfax
+           ...
+           inst> go
+
+       (Note, the dist subdirectory is because some versions of inst fail if
+       the files are in the current directory.) Server binaries is also
+       included in the inst'able images as flexfax.server.*.  It is not
+       installed by default, so to get it also you need to extract the do:
+
+           % inst -f flexfax
+           ...
+           inst> install flexfax.server.*
+           inst> go
+
+       The SGI binaries were built for Version 4.0.5 of the IRIX operating
+       system.  They should work w/o problem on earlier versions of the
+       system, but I have not fully tested this.  Also, note that to install a
+       server on an SGI machine, you need to have installed the Display
+       PostScript execution environment product (dps_eoe).  Otherwise, the fax
+       server will not be able to convert PostScript to facsimile for
+       transmission.
+
+       If you are working from the source distribution, look at the file README
+       in the top of the source tree.  If you are working from the inst images,
+       you need to run faxaddmodem to setup and configure your fax modem.  Do
+       man faxaddmodem for more information.
+
+Also from Sam:
+
+       A mailing list for users of this software is located on sgi.com.
+       If you want to join this mailing list or have a list-related request
+       such as getting your name removed from it, send a request to
+
+           flexfax-request@sgi.com
+
+       Submissions (including bug reports) should be directed to:
+
+           flexfax@sgi.com
+
+
++--------------------------------+
+| TWEAKING CONFIGURATION OPTIONS |
++--------------------------------+
+
+There are a large number of configuration options that don't normally
+need to be changed.  However, if you feel you need to tweak them, you
+can define the following M4 variables.  This list is shown in four
+columns:  the name you define, the default value for that definition,
+the option or macro that is affected (either Ox for an option or Dx
+for a macro), and a brief description.  Greater detail of the semantics
+can be found in the Installation and Operations Guide.
+
+Some options are likely to be deprecated in future versions -- that is,
+the option is only included to provide back-compatibility.  These are
+marked with "*".
+
+M4 Variable Name       Default         Mac/Opt Description
+confMAILER_NAME                MAILER-DAEMON   Dn      The sender name used for
+                                               internally generated
+                                               outgoing messages.
+confFROM_LINE          From $g  $d     Dl      The From_ line used when
+                                               sending to files or programs.
+confFROM_HEADER                $?x$x <$g>$|$g$.        The format of an internally
+                                       Dq      generated From: address.
+confOPERATORS          .:%@!^/[]       Do      Address operator characters.
+confSTMP_LOGIN_MSG     $j Sendmail $v/$Z ready at $b
+                                       De      The initial (spontaneous)
+                                               SMTP greeting message.
+confSEVEN_BIT_INPUT    False           O7      Force input to seven bits?
+confALIAS_WAIT         10              Oa      Wait (in minutes) for alias
+                                               file rebuild.
+confMIN_FREE_BLOCKS    4               Ob      Minimum number of free blocks
+                                               on queue filesystem to accept
+                                               SMTP mail.
+confBLANK_SUB          .               OB      Blank (space) substitution
+                                               character.
+confCON_EXPENSIVE      False           Oc      Connect immediately to
+                                               mailers marked expensive?
+confCHECKPOINT_INTERVAL        10              OC      Checkpoint queue files
+                                               every N recipients.
+confDELIVERY_MODE      background      Od      Default delivery mode.
+confAUTO_REBUILD       False           OD      Automatically rebuild
+                                               alias file if needed.
+confERROR_MODE         (undefined)     Oe      Error message mode.
+confERROR_MESSAGE      (undefined)     OE      Error message header/file.
+confSAVE_FROM_LINES    False           Of      Save extra leading
+                                               From_ lines.
+confTEMP_FILE_MODE     0600            OF      Temporary file mode.
+confDEF_GROUP_ID       1               Og      Default group id.
+confMATCH_GECOS                False           OG      Match GECOS field.
+confMAX_HOP            17              Oh      Maximum hop count.
+confIGNORE_DOTS                False           Oi *    Ignore dot as terminator
+                                               for incoming messages?
+confBIND_OPTS          (empty)         OI      Default options for BIND.
+confMIME_FORMAT_ERRORS True            Oj *    Send error messages as MIME-
+                                               encapsulated messages per
+                                               RFC 1344.
+confMCI_CACHE_SIZE     2               Ok      Size of open connection cache.
+confMCI_CACHE_TIMEOUT  5m              OK      Open connection cache timeout.
+confUSE_ERRORS_TO      False           Ol *    Use the Errors-To: header to
+                                               deliver error messages.  This
+                                               should not be necessary because
+                                               of general acceptance of the
+                                               envelope/header distinction.
+confLOG_LEVEL          9               OL      Log level.
+confME_TOO             False           Om      Include sender in group
+                                               expansions.
+confCHECK_ALIASES      True            On      Check RHS of aliases when
+                                               running newaliases.
+confOLD_STYLE_HEADERS  True            Oo *    Assume that headers without
+                                               special chars are old style.
+confDAEMON_OPTIONS     (undefined)     OO      SMTP daemon options.
+confPRIVACY_FLAGS      authwarnings    Op      Privacy flags.
+confCOPY_ERRORS_TO     (undefined)     OP      Address for additional copies
+                                               of all error messages.
+confQUEUE_FACTOR       (undefined)     Oq      Slope of queue-only function
+confREAD_TIMEOUT       (undefined)     Or      SMTP read timeouts.
+confSAFE_QUEUE         True            Os *    Commit all messages to disk
+                                               before forking.
+confMESSAGE_TIMEOUT    5d/4h           OT      Timeout for messages before
+                                               sending error/warning message.
+confTIME_ZONE          USE_SYSTEM      Ot      Time zone info -- can be
+                                               USE_SYSTEM to use the system's
+                                               idea, USE_TZ to use the user's
+                                               TZ envariable, or something
+                                               else to force that value.
+confDEF_USER_ID                1               Ou      Default user id.
+confUSERDB_SPEC                (undefined)     OU      User database specification.
+confFALLBACK_MX                (undefined)     OV      Fallback MX host.
+confQUEUE_LA           8               Ox      Load average at which queue-only
+                                               function kicks in.
+confREFUSE_LA          12              OX      Load average at which incoming
+                                               SMTP connections are refused.
+confWORK_RECIPIENT_FACTOR
+                       (undefined)     Oy      Cost of each recipient.
+confSEPARATE_PROC      False           OY      Run all deliveries in a
+                                               separate process.
+confWORK_CLASS_FACTOR  (undefined)     Oz      Priority multiplier for class.
+confWORK_TIME_FACTOR   (undefined)     OZ      Cost of each delivery attempt.
+confCW_FILE            /etc/sendmail.cw        Name of file used to get the
+                                       Fw      local additions to the $=w
+                                               class.
+
+
++-----------+
+| HIERARCHY |
++-----------+
+
+Within this directory are several subdirectories, to wit:
+
+m4             General support routines.  These are typically
+               very important and should not be changed without
+               very careful consideration.
+
+cf             The configuration files themselves.  They have
+               ".mc" suffixes, and must be run through m4 to
+               become complete.  The resulting output should
+               have a ".cf" suffix.
+
+ostype         Definitions describing a particular operating
+               system type.  These should always be referenced
+               using the OSTYPE macro in the .mc file.  Examples
+               include "bsd4.3", "bsd4.4", "sunos3.5", and
+               "sunos4.1".
+
+domain         Definitions describing a particular domain, referenced
+               using the DOMAIN macro in the .mc file.  These are
+               site dependent; for example, we contribute "cs.exposed.m4"
+               and "cs.hidden.m4" which both describe hosts in the
+               CS.Berkeley.EDU subdomain; the former displays the local
+               hostname (e.g., mammoth.CS.Berkeley.EDU), whereas the
+               latter does its best to hide the identity of the local
+               workstation inside the CS subdomain.
+
+mailer         Descriptions of mailers.   These are referenced using
+               the MAILER macro in the .mc file.
+
+sh             Shell files used when building the .cf file from the
+               .mc file in the cf subdirectory.
+
+feature                These hold special orthogonal features that you might
+               want to include.  They should be referenced using
+               the FEATURE macro.
+
+hack           Local hacks.  These can be referenced using the HACK
+               macro.  They shouldn't be of more than voyeuristic
+               interest outside the .Berkeley.EDU domain, but who knows?
+               We've all got our own peccadilloes.
+
+siteconfig     Site configuration -- e.g., tables of locally connected
+               UUCP sites.
+
+
++------------------------+
+| ADMINISTRATIVE DETAILS |
++------------------------+
+
+The following sections detail usage of certain internal parts of the
+sendmail.cf file.  Read them carefully if you are trying to modify
+the current model.  If you find the above descriptions adequate, these
+should be {boring, confusing, tedious, ridiculous} (pick one or more).
+
+RULESETS (* means built in to sendmail)
+
+   0 * Parsing
+   1 * Sender rewriting
+   2 * Recipient rewriting
+   3 * Canonicalization
+   4 * Post cleanup
+   5 * Local address rewrite (after aliasing)
+  1x   mailer rules (sender qualification)
+  2x   mailer rules (recipient qualification)
+  90   Mailertable host stripping
+  96   Bottom half of Ruleset 3 (ruleset 6 in old sendmail)
+  97   Hook for recursive ruleset 0 call (ruleset 7 in old sendmail)
+
+
+MAILERS
+
+   0   local, prog     local and program mailers
+   1   smtp            SMTP channel
+   2   uucp            UNIX-to-UNIX Copy Program
+   3   netnews         Network News delivery
+   4   fax             Sam Leffler's FlexFAX software
+
+
+MACROS
+
+   A
+   B   Bitnet Relay
+   C   CSNET Relay
+   D   The local domain -- usually not needed
+   E
+   F   FAX Relay
+   G
+   H   mail Hub (for mail clusters)
+   I
+   J
+   K
+   L
+   M   Masquerade (who I claim to be)
+   N
+   O
+   P
+   Q
+   R   Relay (for unqualified names)
+   S   Smart Host
+   T
+   U   my UUCP name (if I have a UUCP connection)
+   V   UUCP Relay (class V hosts)
+   W   UUCP Relay (class W hosts)
+   X   UUCP Relay (class X hosts)
+   Y   UUCP Relay (all other hosts)
+   Z   Version number
+
+
+CLASSES
+
+   A
+   B
+   C
+   D
+   E   addresses that should not seem to come from $M
+   F   hosts we forward for
+   G
+   H
+   I
+   J
+   K
+   L   addresses that should not be forwarded to $R
+   M
+   N
+   O   operators that indicate network operations (cannot be in local names)
+   P   top level pseudo-domains: BITNET, FAX, UUCP, etc.
+   Q
+   R
+   S
+   T
+   U   locally connected UUCP hosts
+   V   UUCP hosts connected to relay $V
+   W   UUCP hosts connected to relay $W
+   X   UUCP hosts connected to relay $X
+   Y   locally connected smart UUCP hosts
+   Z
+   .   the class containing only a dot
+
+
+M4 DIVERSIONS
+
+   1   Local host detection and resolution
+   2   Local Ruleset 3 additions
+   3   Local Ruleset 0 additions
+   4   UUCP Ruleset 0 additions
+   5   locally interpreted names (overrides $R)
+   6   local configuration (at top of file)
+   7   mailer definitions
+   8   special local name recognition (late in ruleset 3)
+   9   special local rulesets (1 and 2)
index 1c5f367..37ca97b 100644 (file)
@@ -1,79 +1,54 @@
-#
-#  Sendmail
-#  Copyright (c) 1983  Eric P. Allman
-#  Berkeley, California
-#
-#  Copyright (c) 1983 Regents of the University of California.
-#  All rights reserved.  The Berkeley software License Agreement
-#  specifies the terms and conditions for redistribution.
-#
-######################################################################
-#
-#      Makefile for Sendmail UCB configuration files
-#
-######################################################################
+#      @(#)Makefile    8.1 (Berkeley) 6/7/93
 
 
+M4=    m4
+#M4=   /usr/src/usr.bin/m4/obj/m4
+CHMOD= chmod
+ROMODE=        444
+RM=    rm -f
 
 
-NSSRCS =       cad.mc cadgroup.mc cogsci.mc okeeffe.mc ucbarpa.mc ucbvax.mc \
-               cc.mc cchem.mc ic.mc id.mc
-
-GENSRCS        =       proto.mc
-
-NSALL  =       cad.cf cadgroup.cf cogsci.cf okeeffe.cf ucbarpa.cf ucbvax.cf \
-               cc.cf cchem.cf ic.cf id.cf
-
-PROTOS =       ucbtcp.cf uucpproto.cf tcpproto.cf tcpuucpproto.cf
-
-EXP    =       x-ucbtcp_fw.cf
-
-UUCP   =       ../m4/uucpm.m4 ../m4/suucpm.m4 ../m4/rule5.m4 \
-               ../m4/smtpuucpm.m4
-
-ALL    =       $(NSALL) $(PROTOS) $(EXP)
-
-GET    =       sccs get
-
-BLDFILE        =       buildinfo
-
-.SUFFIXES: .mc .cf
+.SUFFIXES:  .mc .cf
 
 .mc.cf:
 
 .mc.cf:
-       rm -f $(BLDFILE)
-       echo "# built by `whoami` on `date`" > $(BLDFILE)
-       echo "# in `pwd` on `hostname`" >> $(BLDFILE)
-       m4 < $*.mc > $*.cf
-       rm -f $(BLDFILE)
+       $(RM) $@
+       (cd ${.CURDIR} && $(M4) ${@:R}.mc) > $@
+       $(CHMOD) $(ROMODE) $@
+
+ALL=   cs-hidden.cf cs-exposed.cf \
+       hpux-cs-exposed.cf hpux-cs-hidden.cf \
+       sunos3.5-cs-exposed.cf sunos3.5-cs-hidden.cf \
+       sunos4.1-cs-exposed.cf sunos4.1-cs-hidden.cf \
+       ultrix4.1-cs-exposed.cf ultrix4.1-cs-hidden.cf \
+       mail.cs.cf mail.eecs.cf ucbvax.cf vangogh.cf \
+       chez.cf knecht.cf cogsci.cf alpha.cf s2k.cf auspex.cf \
+       python.cf sun-lamp.cf boat-anchor.cf\
+       tcpproto.cf uucpproto.cf 
 
 all: $(ALL)
 
 
 all: $(ALL)
 
-clean:
-       rm -f $(ALL) a.out core make.out
-       rm -f ,*
-
-#
-# Standard files included by all
-#
-$(ALL): ../m4/nsmacros.m4 ../m4/nsclasses.m4 ../sitedep/nicregistered.m4 \
-       ../m4/version.m4 ../m4/boilerplate.m4 ../m4/prewriterule.m4 \
-       ../m4/postwriterule.m4 ../m4/rule3.m4 ../m4/localm.m4 ../m4/nstcpm.m4 \
-       ../m4/nstcpldm.m4 ../m4/rule0.m4 ../m4/fake_domains.m4
-
-#
-# Special include files used only by specific hosts
-#
-cad.cf:                proto.mc $(UUCP) ../sitedep/uucp.cad.m4 \
-               ../sitedep/smtpuucp.cad.m4
-cadgroup.cf:   proto.mc
-cc.cf:         proto.mc
-cchem.cf:      proto.mc
-ic.cf:         proto.mc $(UUCP) ../sitedep/uucp.ic.m4
-id.cf:         proto.mc $(UUCP) ../sitedep/uucp.id.m4
-cogsci.cf:     proto.mc $(UUCP) ../sitedep/uucp.cogsci.m4
-okeeffe.cf:    proto.mc $(UUCP) ../sitedep/uucp.okeeffe.m4
-ucbarpa.cf:    proto.mc $(UUCP) ../sitedep/uucp.ucbarpa.m4
-ucbvax.cf:     $(UUCP) ../sitedep/uucp.cad.m4 ../sitedep/uucp.cogsci.m4 \
-               ../sitedep/uucp.ucbarpa.m4 ../sitedep/uucp.ucbvax.m4 \
-               ../sitedep/smtpuucp.ucbvax.m4
-# prototypes
-uucpproto.cf:  proto.mc $(UUCP) ../sitedep/uucp.proto.m4
-tcpproto.cf:   proto.mc
+clean cleandir:
+       $(RM) $(ALL) core
+
+depend install: 
+
+# this is overkill, but....
+M4FILES=../domain/cs.exposed.m4 \
+       ../domain/cs.hidden.m4 \
+       ../domain/Berkeley.m4 \
+       ../feature/use_cw_file.m4 \
+       ../hack/cssubdomain.m4 \
+       ../m4/cf.m4 \
+       ../m4/proto.m4 \
+       ../m4/version.m4 \
+       ../mailer/local.m4 \
+       ../mailer/smtp.m4 \
+       ../mailer/uucp.m4 \
+       ../ostype/bsd4.3.m4 \
+       ../ostype/bsd4.4.m4 \
+       ../ostype/riscos4.5.m4 \
+       ../ostype/sunos3.5.m4 \
+       ../ostype/sunos4.1.m4 \
+       ../ostype/ultrix4.1.m4 \
+
+$(ALL):  $(M4FILES)
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/cf/cf/alpha.mc b/usr.sbin/sendmail/cf/cf/alpha.mc
new file mode 100644 (file)
index 0000000..026fed1
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)alpha.mc        8.1 (Berkeley) 6/7/93')
+OSTYPE(osf1)dnl
+DOMAIN(s2k)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/auspex.mc b/usr.sbin/sendmail/cf/cf/auspex.mc
new file mode 100644 (file)
index 0000000..961c139
--- /dev/null
@@ -0,0 +1,42 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)auspex.mc       8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos4.1)dnl
+DOMAIN(cs.hidden)dnl
+FEATURE(use_cw_file)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/boat-anchor.mc b/usr.sbin/sendmail/cf/cf/boat-anchor.mc
new file mode 100644 (file)
index 0000000..3741795
--- /dev/null
@@ -0,0 +1,47 @@
+divert(-1)
+#
+# Copyright (c) 1993 Adam Glass
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)boat-anchor.mc  $Revision: 1.1 $')
+OSTYPE(bsd4.4)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+define(`UUCP_RELAY', ucbvax.Berkeley.EDU)dnl
+define(`BITNET_RELAY', mailhost.Berkeley.EDU)dnl
+define(`CSNET_RELAY', mailhost.Berkeley.EDU)dnl
+define(`LOCAL_RELAY', sun-lamp.CS.Berkeley.EDU)
+define(`MAIL_HUB', sun-lamp.CS.Berkeley.EDU)
+define(`confCHECKPOINT_INTERVAL', 4)dnl
diff --git a/usr.sbin/sendmail/cf/cf/chez.mc b/usr.sbin/sendmail/cf/cf/chez.mc
new file mode 100644 (file)
index 0000000..13f9519
--- /dev/null
@@ -0,0 +1,44 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)chez.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(bsd4.4)dnl
+DOMAIN(cs.exposed)dnl
+define(`LOCAL_RELAY', vangogh.CS.Berkeley.EDU)dnl
+define(`MASQUERADE_NAME', vangogh.CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+Fw/etc/sendmail.cw
index 62a2841..4faa46d 100644 (file)
@@ -1,18 +1,41 @@
-divert(10)dnl
+divert(-1)
 #
 #
-# cogsci configuration file
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
 #
 #
-# @(#)cogsci.mc        1.6 (Berkeley) 1/3/89
+# 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.
 #
 #
-define(DOMAIN, `DDBerkeley.EDU')
-define(UUCP_NAME, DUcogsci)
-define(UUCP_ALIASES, CUcogsci)
-define(UUCP_HOSTS_FILE, ../sitedep/uucp.cogsci.m4)
-define(INTERNET_RELAY, `DAucbvax.Berkeley.EDU')
-define(UUCP_RELAY, DRucbvax.Berkeley.EDU)
-define(BITNET_RELAY, `DBjade.Berkeley.EDU')
-define(CSNET_RELAY, `DCrelay.cs.net')
-define(ARPAKLUDGE, `1')
-define(EXTERNAL_VERSION, ``#'  `@(#)cogsci.mc  1.6' (Berkeley) `1/3/89'')
-divert(0)dnl
-include(proto.mc)
+# 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.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)cogsci.mc       8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.exposed)dnl
+MAILER(smtp)dnl
+MAILER(uucp)dnl
+SITECONFIG(uucp.cogsci, Ucogsci, U)
diff --git a/usr.sbin/sendmail/cf/cf/cs-exposed.mc b/usr.sbin/sendmail/cf/cf/cs-exposed.mc
new file mode 100644 (file)
index 0000000..62072b7
--- /dev/null
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)cs-exposed.mc   8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/cs-hidden.mc b/usr.sbin/sendmail/cf/cf/cs-hidden.mc
new file mode 100644 (file)
index 0000000..216062c
--- /dev/null
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)cs-hidden.mc    8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/hpux-cs-exposed.mc b/usr.sbin/sendmail/cf/cf/hpux-cs-exposed.mc
new file mode 100644 (file)
index 0000000..4f61ffd
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)hpux-cs-exposed.mc      8.1 (Berkeley) 6/7/93')
+OSTYPE(hpux)dnl
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/hpux-cs-hidden.mc b/usr.sbin/sendmail/cf/cf/hpux-cs-hidden.mc
new file mode 100644 (file)
index 0000000..33cf580
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)hpux-cs-hidden.mc       8.1 (Berkeley) 6/7/93')
+OSTYPE(hpux)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/knecht.mc b/usr.sbin/sendmail/cf/cf/knecht.mc
new file mode 100644 (file)
index 0000000..0cd17fa
--- /dev/null
@@ -0,0 +1,44 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)knecht.mc       8.1 (Berkeley) 6/7/93')
+OSTYPE(ultrix4.1)dnl
+DOMAIN(cs.exposed)dnl
+define(`LOCAL_RELAY', CS.Berkeley.EDU)dnl
+MAILER(smtp)dnl
+
+# our local domain
+DDCS.Berkeley.EDU
diff --git a/usr.sbin/sendmail/cf/cf/mail.cs.mc b/usr.sbin/sendmail/cf/cf/mail.cs.mc
new file mode 100644 (file)
index 0000000..cb447c1
--- /dev/null
@@ -0,0 +1,54 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)mail.cs.mc      8.1 (Berkeley) 6/7/93')
+OSTYPE(ultrix4.1)dnl
+DOMAIN(cs.exposed)dnl
+FEATURE(notsticky)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+define(`confUSERDB_SPEC', ``/usr/local/lib/users.cs.db,/usr/local/lib/users.eecs.db'')dnl
+DDBerkeley.EDU
+
+# hosts for which we accept and forward mail (must be in .Berkeley.EDU)
+CF CS
+FF/etc/sendmail.cw
+
+LOCAL_RULE_0
+R< @ $=F . $D . > : $*         $@ $>7 $2               @here:... -> ...
+R$* $=O $* < @ $=F . $D . >    $@ $>7 $1 $2 $3         ...@here -> ...
+
+R$* < @ $=F . $D . >           $#local $: $1           use UDB
diff --git a/usr.sbin/sendmail/cf/cf/mail.eecs.mc b/usr.sbin/sendmail/cf/cf/mail.eecs.mc
new file mode 100644 (file)
index 0000000..3b6200c
--- /dev/null
@@ -0,0 +1,54 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)mail.eecs.mc    8.1 (Berkeley) 6/7/93')
+OSTYPE(ultrix4.1)dnl
+DOMAIN(eecs.hidden)dnl
+FEATURE(notsticky)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+define(`confUSERDB_SPEC', `/usr/local/lib/users.cs.db,/usr/local/lib/users.eecs.db')dnl
+DDBerkeley.EDU
+
+# hosts for which we accept and forward mail (must be in .Berkeley.EDU)
+CF EECS
+FF/etc/sendmail.cw
+
+LOCAL_RULE_0
+R< @ $=F . $D . > : $*         $@ $>7 $2               @here:... -> ...
+R$* $=O $* < @ $=F . $D . >    $@ $>7 $1 $2 $3         ...@here -> ...
+
+R$* < @ $=F . $D . >           $#local $: $1           use UDB
diff --git a/usr.sbin/sendmail/cf/cf/python.mc b/usr.sbin/sendmail/cf/cf/python.mc
new file mode 100644 (file)
index 0000000..ac23e61
--- /dev/null
@@ -0,0 +1,52 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)python.mc       8.1 (Berkeley) 6/7/93')
+OSTYPE(bsd4.4)dnl
+DOMAIN(cs.exposed)dnl
+define(`LOCAL_RELAY', vangogh.CS.Berkeley.EDU)dnl
+define(`MASQUERADE_NAME', vangogh.CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+
+# accept mail sent to the domain head
+DDBostic.COM
+
+LOCAL_RULE_0
+# accept mail sent to the domain head
+R< @ $D . > : $*               $@ $>7 $1               @here:... -> ...
+R$* $=O $* < @ $D . >          $@ $>7 $1 $2 $3         ...@here -> ...
+R$* < @ $D . >                 $#local $: $1           user@here -> user
diff --git a/usr.sbin/sendmail/cf/cf/s2k.mc b/usr.sbin/sendmail/cf/cf/s2k.mc
new file mode 100644 (file)
index 0000000..e65fc9f
--- /dev/null
@@ -0,0 +1,42 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)s2k.mc  8.1 (Berkeley) 6/7/93')
+OLDSENDMAIL
+OSTYPE(ultrix4.1)dnl
+DOMAIN(s2k)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/sun-lamp.mc b/usr.sbin/sendmail/cf/cf/sun-lamp.mc
new file mode 100644 (file)
index 0000000..9a722da
--- /dev/null
@@ -0,0 +1,49 @@
+divert(-1)
+#
+# Copyright (c) 1993 Adam Glass
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)sun-lamp.mc     $Revision: 1.1 $')
+OSTYPE(bsd4.4)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+define(`UUCP_RELAY', ucbvax.Berkeley.EDU)dnl
+define(`BITNET_RELAY', mailhost.Berkeley.EDU)dnl
+define(`CSNET_RELAY', mailhost.Berkeley.EDU)dnl
+define(`confCHECKPOINT_INTERVAL', 4)dnl
+define(`confAUTO_REBUILD', True)dnl
+Cwlamp
+
+
diff --git a/usr.sbin/sendmail/cf/cf/sunos3.5-cs-exposed.mc b/usr.sbin/sendmail/cf/cf/sunos3.5-cs-exposed.mc
new file mode 100644 (file)
index 0000000..46d04d9
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)sunos3.5-cs-exposed.mc  8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos3.5)dnl
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/sunos3.5-cs-hidden.mc b/usr.sbin/sendmail/cf/cf/sunos3.5-cs-hidden.mc
new file mode 100644 (file)
index 0000000..a3d6f20
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)sunos3.5-cs-hidden.mc   8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos3.5)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/sunos4.1-cs-exposed.mc b/usr.sbin/sendmail/cf/cf/sunos4.1-cs-exposed.mc
new file mode 100644 (file)
index 0000000..7c94ba5
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)sunos4.1-cs-exposed.mc  8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos4.1)dnl
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/sunos4.1-cs-hidden.mc b/usr.sbin/sendmail/cf/cf/sunos4.1-cs-hidden.mc
new file mode 100644 (file)
index 0000000..8e1dbb9
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)sunos4.1-cs-hidden.mc   8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos4.1)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
index 1b7bd40..7fcb65a 100644 (file)
@@ -1,14 +1,40 @@
-divert(10)dnl
+divert(-1)
 #
 #
-# Prototype configuration file for systems on TCP/IP (SMTP) based networks
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
 #
 #
-# @(#)tcpproto.mc      1.2 (Berkeley) 1/24/89
+# 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.
 #
 #
-define(DOMAIN, `DDYOUR_DOMAIN_GOES_HERE')
-define(UUCP_RELAY, DRYOUR_UUCP_RELAY_GOES_HERE)
-define(BITNET_RELAY, `DBYOUR_BITNET_RELAY_GOES_HERE')
-define(CSNET_RELAY, `DCYOUR_CSNET_RELAY_GOES_HERE')
-define(ARPAKLUDGE, `1')
-define(EXTERNAL_VERSION, ``#'  `@(#)tcpproto.mc        1.2' (Berkeley) `1/24/89'')
-divert(0)dnl
-include(proto.mc)dnl
+# 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.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)tcpproto.mc     8.1 (Berkeley) 6/7/93')
+FEATURE(nouucp)
+MAILER(local)
+MAILER(smtp)
index c1d0aa8..21f35fd 100644 (file)
@@ -1,18 +1,43 @@
-divert(10)dnl
+divert(-1)
 #
 #
-# ucbarpa configuration file
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
 #
 #
-# @(#)ucbarpa.mc       1.3 (Berkeley) 1/3/89
+# 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.
 #
 #
-define(DOMAIN, `DDBerkeley.EDU')
-define(UUCP_NAME, DUucbarpa)
-define(UUCP_ALIASES, CUucbarpa)
-define(UUCP_HOSTS_FILE, ../sitedep/uucp.ucbarpa.m4)
-define(INTERNET_RELAY, `DAucbvax.Berkeley.EDU')
-define(UUCP_RELAY, DRucbvax.Berkeley.EDU)
-define(BITNET_RELAY, `DBjade.Berkeley.EDU')
-define(CSNET_RELAY, `DCrelay.cs.net')
-define(ARPAKLUDGE, `1')
-define(EXTERNAL_VERSION, ``#'  `@(#)ucbarpa.mc 1.3' (Berkeley) `1/3/89'')
-divert(0)dnl
-include(proto.mc)dnl
+# 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.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)ucbarpa.mc      8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.exposed)dnl
+OSTYPE(bsd4.4)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+MAILER(uucp)dnl
+SITECONFIG(uucp.ucbarpa, ucbarpa, U)
index 3bd26a7..bae55d5 100644 (file)
-############################################################
+divert(-1)
 #
 #
-#  Sendmail
-#  Copyright (c) 1983  Eric P. Allman
-#  Berkeley, California
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
 #
 #
-#  Copyright (c) 1983 Regents of the University of California.
-#  All rights reserved.  The Berkeley software License Agreement
-#  specifies the terms and conditions for redistribution.
+# 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.
 #
 #
-#      @(#)ucbvax.mc   1.39 (Berkeley) 1/3/89
+# 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.
 #
 #
-sinclude(buildinfo)dnl
-#
-############################################################
-############################################################
-#####
-#####          SENDMAIL CONFIGURATION FILE
-#####
-#####  This one is the big daddy.  There is no "upstairs"
-#####  to bounce a message to -- except perhaps the arpanet.
-#####
-#####
-############################################################
-############################################################
-
-
-
-######################
-###   local info   ###
-######################
-
-# internet hostnames
-Cwucbvax vax k UCB-VAX Berkeley UCB-C70 UCB
-
-# UUCP hostnames
-DUucbvax
-CUucbvax 
-
-# local UUCP connections
-include(../sitedep/uucp.ucbvax.m4)dnl
-
-# UUCP connections on ucbarpa
-DWucbarpa.Berkeley.EDU
-define(`CV', CW)dnl
-include(../sitedep/uucp.ucbarpa.m4)dnl
-undefine(`CV')dnl
-
-# UUCP connections on ucbcad
-DXcad.Berkeley.EDU
-define(`CV', CX)dnl
-include(../sitedep/uucp.cad.m4)dnl
-undefine(`CV')dnl
-
-# UUCP connections on cogsci
-DYcogsci.Berkeley.EDU
-define(`CV', CY)dnl
-include(../sitedep/uucp.cogsci.m4)dnl
-undefine(`CV')dnl
-
-# known uucp connections with a smart uucp
-CMdecvax
-
-# we have full sendmail support here
-Oa
-
-#############################
-###   Setup Information   ###
-#############################
-
-include(../m4/nsmacros.m4)
-include(../m4/nsclasses.m4)
-include(../sitedep/nicregistered.m4)
-include(../m4/version.m4)
-include(../m4/boilerplate.m4)
-
-###########################
-###   Rewriting Rules   ###
-###########################
-
-include(../m4/prewriterule.m4)
-include(../m4/postwriterule.m4)
-
-# addition to Post-rewrite Rule
-R$+%$=w@$=w.EDU                $1@$w                   u%UCB@UCB.edu => u@UCB.berk.edu
-R$+%$=w@$=w.$=w.EDU    $1@$w                   u%UCB@UCB.berk.edu => u@UCB
-
-include(../m4/rule3.m4)
-include(../m4/rule5.m4)
-
-###################
-###   Mailers   ###
-###################
-
-include(../m4/localm.m4)
-define(`m4UUCP',TRUE)
-include(../m4/suucpm.m4)
-include(../m4/uucpm.m4)
-include(../m4/smtpuucpm.m4)
-include(../m4/nstcpm.m4)
-include(../m4/nstcpldm.m4)
-
-#####################
-###   Rule Zero   ###
-#####################
-
-include(../m4/rule0.m4)
-
-################################################
-###  Machine dependent part of ruleset zero  ###
-################################################
-
-# resolve SMTP UUCP connections
-include(../sitedep/smtpuucp.ucbvax.m4)
-
-# resolve local UUCP links
-R<@$=V.UUCP>:$+                $#uucp$@$1$:$1:$2               @host.UUCP: ...
-R$+<@$=V.UUCP>         $#uucp$@$2$:$1                  user@host.UUCP
-
-# resolve explicit arpanet names (to avoid with machine name "arpa" below)
-R$*<@$*$-.ARPA>$*      $#tcp$@$3.ARPA$:$1<@$2$3.ARPA>$4        user@domain.ARPA
-
-# resolve fake top level domains by forwarding to other hosts
-include(../m4/fake_domains.m4)
-
-# resolve non-local UUCP links
-R$*<@$=W.UUCP>$*       $#tcpld$@$W$:$1<@$2.UUCP>$3     user@host.UUCP
-R$*<@$=X.UUCP>$*       $#tcpld$@$X$:$1<@$2.UUCP>$3     user@host.UUCP
-R$*<@$=Y.UUCP>$*       $#tcpld$@$Y$:$1<@$2.UUCP>$3     user@host.UUCP
-
-# this uucp stuff is wrong for domain uucp addresses
-# - we should pass the whole "host.domain" to uucp so it can
-#   find the best route.  But that depends on a uucp router
-#   which doesn't exist here yet, so for now, we'll settle for
-#   trying to route to the domain (pretending its a host).
-#   Suitable L.sys entries can make this work.  If it doesn't
-#   then returned mail will just say "dom unknown", which is true ..
-
-# resolve smart UUCP links
-R<@$=M.$-.UUCP>:$+     $#suucp$@$2$:@$1.$2.UUCP:$3     @host.domain.UUCP: ...
-R<@$=M.UUCP>:$+                $#suucp$@$1$:$2                 @host.UUCP: ...
-R$+<@$=M.$-.UUCP>      $#suucp$@$3$:$1@$2.$3.UUCP      user@host.domain.UUCP
-R$+<@$=M.UUCP>         $#suucp$@$2$:$1                 user@host.UUCP
-
-# local domain sites
-R$*<@$*.$D>$*          $#tcpld$@$2.$D$:$1<@$2.$D>$3    user@host.our.domain
-R$*<@$->$*             $#tcpld$@$2.$D$:$1<@$2.$D>$3    user@host
-R$*<@$-.UUCP>$*                $#tcpld$@$2.$D$:$1<@$2.$D>$3    user@host.UUCP
-
-# other non-local names will be kicked upstairs
-R$*<@$+>$*             $#tcp$@$2$:$1<@$2>$3            user@some.where
-
-# remaining names must be local
-R$+                    $#local$:$1                     everything else
-
-########################################
-###  Host dependent address cleanup  ###
-########################################
 
 
-S8
-R$*$=U!$+@$+           $3@$4                           drop uucp forward
+include(`../m4/cf.m4')
+VERSIONID(`@(#)ucbvax.mc       8.1 (Berkeley) 6/7/93')
+OSTYPE(bsd4.3)
+DOMAIN(cs.hidden)
+FEATURE(notsticky)
+MAILER(local)
+MAILER(smtp)
+MAILER(uucp)
+undefine(`UUCP_RELAY')dnl
+DDBerkeley.EDU
+
+# names for which we act as a local forwarding agent
+CF CS
+FF/etc/sendmail.cw
+
+# local UUCP connections, and our local uucp name
+SITECONFIG(uucp.ucbvax, ucbvax, U)
+
+# remote UUCP connections, and the machine they are on
+SITECONFIG(uucp.ucbarpa, ucbarpa.Berkeley.EDU, W)
+
+SITECONFIG(uucp.cogsci, cogsci.Berkeley.EDU, X)
+
+LOCAL_RULE_3
+# map old UUCP names into Internet names
+UUCPSMTP(bellcore,     bellcore.com)
+UUCPSMTP(decvax,       decvax.dec.com)
+UUCPSMTP(decwrl,       decwrl.dec.com)
+UUCPSMTP(hplabs,       hplabs.hp.com)
+UUCPSMTP(lbl-csam,     lbl-csam.arpa)
+UUCPSMTP(pur-ee,       ecn.purdue.edu)
+UUCPSMTP(purdue,       purdue.edu)
+UUCPSMTP(research,     research.att.com)
+UUCPSMTP(sdcarl,       sdcarl.ucsd.edu)
+UUCPSMTP(sdcsvax,      sdcsvax.ucsd.edu)
+UUCPSMTP(ssyx,         ssyx.ucsc.edu)
+UUCPSMTP(sun,          sun.com)
+UUCPSMTP(ucdavis,      ucdavis.ucdavis.edu)
+UUCPSMTP(ucivax,       ics.uci.edu)
+UUCPSMTP(ucla-cs,      cs.ucla.edu)
+UUCPSMTP(ucla-se,      seas.ucla.edu)
+UUCPSMTP(ucsbcsl,      ucsbcsl.ucsb.edu)
+UUCPSMTP(ucscc,                c.ucsc.edu)
+UUCPSMTP(ucsd,         ucsd.edu)
+UUCPSMTP(ucsfcgl,      cgl.ucsf.edu)
+UUCPSMTP(unmvax,       unmvax.cs.unm.edu)
+UUCPSMTP(uwvax,                spool.cs.wisc.edu)
+
+LOCAL_RULE_0
+
+# make sure we handle the local domain as absolute
+R$* <  @ $* $D > $*            $: $1 < @ $2 $D . > $3
+
+# handle names we forward for as though they were local, so we will use UDB
+R< @ $=F . $D . > : $*         $@ $>7 $2               @here:... -> ...
+R< @ $D . > : $*               $@ $>7 $1               @here:... -> ...
+R$* $=O $* < @ $=F . $D . >    $@ $>7 $1 $2 $3         ...@here -> ...
+R$* $=O $* < @ $D . >          $@ $>7 $1 $2 $3         ...@here -> ...
+
+R$* < @ $=F . $D . >           $#local $: $1           use UDB
+
+# handle local UUCP connections in the Berkeley.EDU domain
+R$+<@cnmat.$D . >              $#uucp$@cnmat$:$1
+R$+<@cnmat.CS.$D . >           $#uucp$@cnmat$:$1
+R$+<@craig.$D . >              $#uucp$@craig$:$1
+R$+<@craig.CS.$D . >           $#uucp$@craig$:$1
diff --git a/usr.sbin/sendmail/cf/cf/udb.mc b/usr.sbin/sendmail/cf/cf/udb.mc
new file mode 100644 (file)
index 0000000..624d2d4
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)udb.mc  8.1 (Berkeley) 6/7/93')
+OSTYPE(sunos4.1)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(smtp)dnl
+define(`USERDB_FILE', `/home/auspex/a/staff/gnn/UDB/UI')dnl
diff --git a/usr.sbin/sendmail/cf/cf/ultrix4.1-cs-exposed.mc b/usr.sbin/sendmail/cf/cf/ultrix4.1-cs-exposed.mc
new file mode 100644 (file)
index 0000000..093590f
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)ultrix4.1-cs-exposed.mc 8.1 (Berkeley) 6/7/93')
+OSTYPE(ultrix4.1)dnl
+DOMAIN(cs.exposed)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/ultrix4.1-cs-hidden.mc b/usr.sbin/sendmail/cf/cf/ultrix4.1-cs-hidden.mc
new file mode 100644 (file)
index 0000000..ea25375
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)ultrix4.1-cs-hidden.mc  8.1 (Berkeley) 6/7/93')
+OSTYPE(ultrix4.1)dnl
+DOMAIN(cs.hidden)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
index 86751fc..9fe749e 100644 (file)
@@ -1,14 +1,39 @@
-divert(10)dnl
+divert(-1)
 #
 #
-# Prototype configuration file for systems only on UUCP networks
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
 #
 #
-# @(#)uucpproto.mc     1.2 (Berkeley) 1/24/89
+# 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.
 #
 #
-define(DOMAIN, `DDUUCP')
-define(UUCP_NAME, DUYOUR_UUCP_HOSTNAME_HERE)
-define(UUCP_ALIASES, CUYOUR_UUCP_ALIASES_HERE)
-define(UUCP_HOSTS_FILE, ../sitedep/uucp.proto.m4)
-define(UUCP_ONLY, 1)
-define(EXTERNAL_VERSION, ``#'  `@(#)uucpproto.mc       1.2' (Berkeley) `1/24/89'')
-divert(0)dnl
-include(proto.mc)dnl
+# 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.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)uucpproto.mc    8.1 (Berkeley) 6/7/93')
+MAILER(local)dnl
+MAILER(uucp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/vangogh.mc b/usr.sbin/sendmail/cf/cf/vangogh.mc
new file mode 100644 (file)
index 0000000..edf9865
--- /dev/null
@@ -0,0 +1,43 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+include(`../m4/cf.m4')
+VERSIONID(`@(#)vangogh.mc      8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.exposed)dnl
+OSTYPE(bsd4.4)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+define(`MCI_CACHE_SIZE', 5)
+Cw okeeffe
diff --git a/usr.sbin/sendmail/cf/domain/Berkeley.m4 b/usr.sbin/sendmail/cf/domain/Berkeley.m4
new file mode 100644 (file)
index 0000000..fc72e07
--- /dev/null
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)Berkeley.m4     8.1 (Berkeley) 6/7/93')
+define(`UUCP_RELAY', `ucbvax.Berkeley.EDU')dnl
+define(`BITNET_RELAY', `jade.Berkeley.EDU')dnl
+define(`CSNET_RELAY', `Relay.Prime.COM')dnl
+FEATURE(redirect)dnl
diff --git a/usr.sbin/sendmail/cf/domain/cs.exposed.m4 b/usr.sbin/sendmail/cf/domain/cs.exposed.m4
new file mode 100644 (file)
index 0000000..43c07be
--- /dev/null
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)cs.exposed.m4   8.1 (Berkeley) 6/7/93')
+DOMAIN(Berkeley)dnl
+HACK(cssubdomain)dnl
+define(`confUSERDB_SPEC',
+       `/usr/sww/share/lib/users.cs.db,/usr/sww/share/lib/users.eecs.db')dnl
diff --git a/usr.sbin/sendmail/cf/domain/cs.hidden.m4 b/usr.sbin/sendmail/cf/domain/cs.hidden.m4
new file mode 100644 (file)
index 0000000..3d9721a
--- /dev/null
@@ -0,0 +1,38 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)cs.hidden.m4    8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.exposed)dnl
+MASQUERADE_AS(CS.Berkeley.EDU)dnl
diff --git a/usr.sbin/sendmail/cf/domain/eecs.hidden.m4 b/usr.sbin/sendmail/cf/domain/eecs.hidden.m4
new file mode 100644 (file)
index 0000000..bbdc01a
--- /dev/null
@@ -0,0 +1,38 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)eecs.hidden.m4  8.1 (Berkeley) 6/7/93')
+DOMAIN(Berkeley)dnl
+MASQUERADE_AS(EECS.Berkeley.EDU)dnl
diff --git a/usr.sbin/sendmail/cf/domain/s2k.m4 b/usr.sbin/sendmail/cf/domain/s2k.m4
new file mode 100644 (file)
index 0000000..25b931f
--- /dev/null
@@ -0,0 +1,38 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)s2k.m4  8.1 (Berkeley) 6/7/93')
+DOMAIN(cs.exposed)dnl
+MASQUERADE_AS(postgres.Berkeley.EDU)dnl
diff --git a/usr.sbin/sendmail/cf/feature/always_add_domain.m4 b/usr.sbin/sendmail/cf/feature/always_add_domain.m4
new file mode 100644 (file)
index 0000000..dd572c8
--- /dev/null
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)always_add_domain.m4    8.1 (Berkeley) 6/7/93')
+divert(-1)
+
+define(`_ALWAYS_ADD_DOMAIN_', 1)
diff --git a/usr.sbin/sendmail/cf/feature/bitdomain.m4 b/usr.sbin/sendmail/cf/feature/bitdomain.m4
new file mode 100644 (file)
index 0000000..91ee8ae
--- /dev/null
@@ -0,0 +1,49 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)bitdomain.m4    8.1 (Berkeley) 6/7/93')
+divert(-1)
+
+
+PUSHDIVERT(6)
+Kbitdomain ifelse(_ARG_, `', `hash /etc/bitdomain -o', `_ARG_')
+POPDIVERT
+
+
+PUSHDIVERT(8)
+# handle BITNET mapping
+R$* < @ $+ .BITNET > $*                $: $1 < @ $(bitdomain $2 $: $2.BITNET $) > $3
+POPDIVERT
diff --git a/usr.sbin/sendmail/cf/feature/mailertable.m4 b/usr.sbin/sendmail/cf/feature/mailertable.m4
new file mode 100644 (file)
index 0000000..89e1748
--- /dev/null
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)mailertable.m4  8.1 (Berkeley) 6/7/93')
+divert(-1)
+
+define(`MAILER_TABLE', ifelse(_ARG_, `', `hash /etc/mailertable -o', `_ARG_'))dnl
diff --git a/usr.sbin/sendmail/cf/feature/nocanonify.m4 b/usr.sbin/sendmail/cf/feature/nocanonify.m4
new file mode 100644 (file)
index 0000000..0157e6b
--- /dev/null
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)nocanonify.m4   8.1 (Berkeley) 6/7/93')
+divert(-1)
+
+define(`_NO_CANONIFY_', 1)
diff --git a/usr.sbin/sendmail/cf/feature/notsticky.m4 b/usr.sbin/sendmail/cf/feature/notsticky.m4
new file mode 100644 (file)
index 0000000..5118923
--- /dev/null
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)notsticky.m4    8.1 (Berkeley) 6/7/93')
+divert(-1)
+
+define(`_LOCAL_NOT_STICKY_', 1)
diff --git a/usr.sbin/sendmail/cf/feature/nouucp.m4 b/usr.sbin/sendmail/cf/feature/nouucp.m4
new file mode 100644 (file)
index 0000000..8723437
--- /dev/null
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)nouucp.m4       8.1 (Berkeley) 6/7/93')
+divert(-1)
+
+define(`_NO_UUCP_', 1)
diff --git a/usr.sbin/sendmail/cf/feature/redirect.m4 b/usr.sbin/sendmail/cf/feature/redirect.m4
new file mode 100644 (file)
index 0000000..941fad8
--- /dev/null
@@ -0,0 +1,48 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)redirect.m4     8.1 (Berkeley) 6/7/93')
+divert(-1)
+
+
+PUSHDIVERT(3)
+# addresses sent to foo@host.REDIRECT will give a 551 error code
+R$* < @ $+ .REDIRECT > $# error $@ NOUSER $: "551 User not local; please try " <$1@$2>
+POPDIVERT
+
+PUSHDIVERT(6)
+CPREDIRECT
+POPDIVERT
diff --git a/usr.sbin/sendmail/cf/feature/use_cw_file.m4 b/usr.sbin/sendmail/cf/feature/use_cw_file.m4
new file mode 100644 (file)
index 0000000..33b5ad5
--- /dev/null
@@ -0,0 +1,46 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)use_cw_file.m4  8.1 (Berkeley) 6/7/93')
+divert(-1)
+
+# if defined, the sendmail.cf will read the /etc/sendmail.cw file
+# to find alternate names for this host.  Typically only used when
+# several hosts have been squashed into one another at high speed.
+
+define(`USE_CW_FILE', `')
+
+divert(0)
diff --git a/usr.sbin/sendmail/cf/feature/uucpdomain.m4 b/usr.sbin/sendmail/cf/feature/uucpdomain.m4
new file mode 100644 (file)
index 0000000..98396fd
--- /dev/null
@@ -0,0 +1,49 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)uucpdomain.m4   8.1 (Berkeley) 6/7/93')
+divert(-1)
+
+
+PUSHDIVERT(6)
+Kuudomain ifelse(_ARG_, `', `hash /etc/uudomain -o', `_ARG_')
+POPDIVERT
+
+
+PUSHDIVERT(8)
+# handle UUCP mapping
+R$* < @ $+ .UUCP > $*          $: $1 < @ $(uudomain $2 $: $2.UUCP $) > $3
+POPDIVERT
diff --git a/usr.sbin/sendmail/cf/hack/cssubdomain.m4 b/usr.sbin/sendmail/cf/hack/cssubdomain.m4
new file mode 100644 (file)
index 0000000..4f270c0
--- /dev/null
@@ -0,0 +1,44 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+VERSIONID(`@(#)cssubdomain.m4  8.1 (Berkeley) 6/7/93')
+
+divert(2)
+# find possible (old & new) versions of our name via short circuit hack
+# (this code should exist ONLY during the transition from .Berkeley.EDU
+#  names to .CS.Berkeley.EDU names -- probably not more than a few months)
+R$* < @ $=w .CS.Berkeley.EDU > $*      $: $1 < @ $j > $3
+R$* < @ $=w .Berkeley.EDU> $*          $: $1 < @ $j > $3
+divert(0)
diff --git a/usr.sbin/sendmail/cf/m4/cf.m4 b/usr.sbin/sendmail/cf/m4/cf.m4
new file mode 100644 (file)
index 0000000..4e4ca92
--- /dev/null
@@ -0,0 +1,147 @@
+divert(0)dnl
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+
+######################################################################
+######################################################################
+#####
+#####          SENDMAIL CONFIGURATION FILE
+#####
+define(`TEMPFILE', maketemp(/tmp/cfXXXXXX))dnl
+syscmd(sh ../sh/makeinfo.sh > TEMPFILE)dnl
+include(TEMPFILE)dnl
+syscmd(rm -f TEMPFILE)dnl
+#####
+######################################################################
+######################################################################
+
+divert(-1)
+
+changecom(\ 1)
+undefine(`format')
+ifdef(`pushdef', `',
+       `errprint(`You need a newer version of M4, at least as new as
+System V or GNU')
+       include(NoSuchFile)')
+define(`PUSHDIVERT', `pushdef(`__D__', divnum)divert($1)')
+define(`POPDIVERT', `divert(__D__)popdef(`__D__')')
+define(`OSTYPE', `PUSHDIVERT(-1)define(`_ARG_', $2)include(../ostype/$1.m4)POPDIVERT`'')
+define(`MAILER',
+`ifdef(`_MAILER_$1_', `dnl`'',
+`define(`_MAILER_$1_', `')PUSHDIVERT(7)include(../mailer/$1.m4)POPDIVERT`'')')
+define(`DOMAIN', `PUSHDIVERT(-1)define(`_ARG_', $2)include(../domain/$1.m4)POPDIVERT`'')
+define(`FEATURE', `PUSHDIVERT(-1)define(`_ARG_', $2)include(../feature/$1.m4)POPDIVERT`'')
+define(`HACK', `PUSHDIVERT(-1)define(`_ARG_', $2)include(../hack/$1.m4)POPDIVERT`'')
+define(`OLDSENDMAIL', `define(`_OLD_SENDMAIL_', `')')
+define(`VERSIONID', ``#####  $1  #####'')
+define(`LOCAL_RULE_0', `divert(3)')
+define(`LOCAL_RULE_1',
+`divert(9)dnl
+#######################################
+###  Ruleset 1 -- Sender Rewriting  ###
+#######################################
+
+S1
+')
+define(`LOCAL_RULE_2',
+`divert(9)dnl
+##########################################
+###  Ruleset 2 -- Recipient Rewriting  ###
+##########################################
+
+S2
+')
+define(`LOCAL_RULE_3', `divert(2)')
+define(`LOCAL_CONFIG', `divert(6)')
+define(`LOCAL_NET_CONFIG', `define(`_LOCAL_RULES_', 1)divert(1)')
+define(`UUCPSMTP', `R DOL(*) < @ $1 .UUCP > DOL(*)     DOL(1) < @ $2 > DOL(2)')
+define(`CONCAT', `$1$2$3$4$5$6$7')
+define(`DOL', ``$'$1')
+define(`SITECONFIG',
+`CONCAT(D, $3, $2)
+define(`_CLASS_$3_', `')dnl
+ifelse($3, U, Cw$2, `dnl')
+define(`SITE', `ifelse(CONCAT($'2`, $3), SU,
+               CONCAT(CY, $'1`),
+               CONCAT(C, $3, $'1`))')
+sinclude(../siteconfig/$1.m4)')
+define(`EXPOSED_USER', `PUSHDIVERT(5)CE$1
+POPDIVERT`'dnl')
+define(`LOCAL_USER', `PUSHDIVERT(5)CL$1
+POPDIVERT`'dnl')
+define(`MASQUERADE_AS', `define(`MASQUERADE_NAME', $1)')
+
+m4wrap(`include(`../m4/proto.m4')')
+
+# set up default values for options
+define(`confMAILER_NAME', ``MAILER-DAEMON'')
+define(`confFROM_LINE', `From $g  $d')
+define(`confOPERATORS', `.:%@!^/[]')
+define(`confSMTP_LOGIN_MSG', `$j Sendmail $v/$Z ready at $b')
+define(`confSEVEN_BIT_INPUT', `False')
+define(`confALIAS_WAIT', `10')
+define(`confMIN_FREE_BLOCKS', `4')
+define(`confBLANK_SUB', `.')
+define(`confCON_EXPENSIVE', `False')
+define(`confCHECKPOINT_INTERVAL', `10')
+define(`confDELIVERY_MODE', `background')
+define(`confAUTO_REBUILD', `False')
+define(`confSAVE_FROM_LINES', `False')
+define(`confTEMP_FILE_MODE', `0600')
+define(`confMATCH_GECOS', `False')
+define(`confDEF_GROUP_ID', `1')
+define(`confMAX_HOP', `17')
+define(`confIGNORE_DOTS', `False')
+define(`confBIND_OPTS', `')
+define(`confMCI_CACHE_SIZE', `2')
+define(`confMCI_CACHE_TIMEOUT', `5m')
+define(`confUSE_ERRORS_TO', `False')
+define(`confLOG_LEVEL', `9')
+define(`confME_TOO', `False')
+define(`confCHECK_ALIASES', `True')
+define(`confOLD_STYLE_HEADERS', `True')
+define(`confPRIVACY_FLAGS', `authwarnings')
+define(`confSAFE_QUEUE', `True')
+define(`confMESSAGE_TIMEOUT', `5d/4h')
+define(`confTIME_ZONE', `USE_SYSTEM')
+define(`confDEF_USER_ID', `1')
+define(`confQUEUE_LA', `8')
+define(`confREFUSE_LA', `12')
+define(`confSEPARATE_PROC', `False')
+define(`confCW_FILE', `/etc/sendmail.cw')
+define(`confMIME_FORMAT_ERRORS', `True')
+
+divert(0)dnl
+VERSIONID(`@(#)cf.m4   8.1 (Berkeley) 6/7/93')
diff --git a/usr.sbin/sendmail/cf/m4/proto.m4 b/usr.sbin/sendmail/cf/m4/proto.m4
new file mode 100644 (file)
index 0000000..846cc16
--- /dev/null
@@ -0,0 +1,644 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+divert(0)
+
+VERSIONID(`@(#)proto.m4        8.1 (Berkeley) 6/27/93')
+
+MAILER(local)dnl
+
+ifdef(`_OLD_SENDMAIL_',
+`define(`_SET_96_', 6)dnl
+define(`_SET_97_', 7)dnl',
+`# level 4 config file format
+V4
+define(`_SET_96_', 96)dnl
+define(`_SET_97_', 97)dnl')
+
+##################
+#   local info   #
+##################
+
+CP.
+
+Cwlocalhost
+ifdef(`USE_CW_FILE',
+`# file containing names of hosts for which we receive email
+CONCAT(`Fw', confCW_FILE)', `dnl')
+
+ifdef(`UUCP_RELAY',
+`# UUCP relay host
+CONCAT(DY, UUCP_RELAY)
+CPUUCP
+
+')dnl
+ifdef(`BITNET_RELAY',
+`#  BITNET relay host
+CONCAT(DB, BITNET_RELAY)
+CPBITNET
+
+')dnl
+ifdef(`CSNET_RELAY',
+`# CSNET relay host
+CONCAT(DC, CSNET_RELAY)
+CPCSNET
+
+')dnl
+ifdef(`FAX_RELAY',
+`# FAX relay host
+CONCAT(DF, FAX_RELAY)
+CPFAX
+
+')dnl
+ifdef(`SMART_HOST',
+`# "Smart" UUCP relay host
+CONCAT(DS, SMART_HOST)
+
+')dnl
+ifdef(`MAILER_TABLE',
+`# Mailer table (overriding domains)
+Kmailertable MAILER_TABLE
+
+')dnl
+# who I send unqualified names to (null means deliver locally)
+CONCAT(DR, ifdef(`LOCAL_RELAY', LOCAL_RELAY))
+
+# who gets all local email traffic ($R has precedence for unqualified names)
+CONCAT(DH, ifdef(`MAIL_HUB', MAIL_HUB))
+
+# my official hostname ($w or $w.$D)
+CONCAT(Dj$w, ifdef(`NEED_DOMAIN', .$D))
+
+# who I masquerade as (can be $j)
+CONCAT(DM, ifdef(`MASQUERADE_NAME', MASQUERADE_NAME, $j))
+
+# class L: names that should be delivered locally, even if we have a relay
+# class E: names that should be exposed as from this host, even if we masquerade
+CLroot
+CEroot
+undivert(5)dnl
+
+# operators that cannot be in local usernames (i.e., network indicators)
+CO @ % ifdef(`_NO_UUCP_', `', `!')
+
+# a class with just dot (for identifying canonical names)
+C..
+
+ifdef(`_OLD_SENDMAIL_', `dnl',
+`# dequoting map
+Kdequote dequote')
+
+undivert(6)dnl
+
+######################
+#   Special macros   #
+######################
+
+# SMTP initial login message
+CONCAT(De, confSMTP_LOGIN_MSG)
+
+# UNIX initial From header format
+CONCAT(Dl, confFROM_LINE)
+
+# my name for error messages
+CONCAT(Dn, confMAILER_NAME)
+
+# delimiter (operator) characters
+CONCAT(Do, confOPERATORS)
+
+# format of a total name
+CONCAT(Dq, ifdef(`confFROM_HEADER', confFROM_HEADER,
+       ifdef(`_OLD_SENDMAIL_', `$g$?x ($x)$.', `$?x$x <$g>$|$g$.')))
+include(`../m4/version.m4')
+
+###############
+#   Options   #
+###############
+
+# strip message body to 7 bits on input?
+CONCAT(O7, confSEVEN_BIT_INPUT)
+
+# wait (in minutes) for alias file rebuild
+CONCAT(Oa, confALIAS_WAIT)
+
+# location of alias file
+CONCAT(OA, ifdef(`ALIAS_FILE', ALIAS_FILE, /etc/aliases))
+
+# minimum number of free blocks on filesystem
+CONCAT(Ob, confMIN_FREE_BLOCKS)
+
+# substitution for space (blank) characters
+CONCAT(OB, confBLANK_SUB)
+
+# connect to "expensive" mailers on initial submission?
+CONCAT(Oc, confCON_EXPENSIVE)
+
+# checkpoint queue runs after every N successful deliveries
+CONCAT(OC, confCHECKPOINT_INTERVAL)
+
+# default delivery mode
+CONCAT(Od, confDELIVERY_MODE)
+
+# automatically rebuild the alias database?
+CONCAT(OD, confAUTO_REBUILD)
+
+# error message header/file */
+ifdef(`confERROR_MESSAGE',
+       CONCAT(OE, confERROR_MESSAGE),
+       #OE/etc/sendmail.oE)
+
+# error mode
+ifdef(`confERROR_MODE',
+       CONCAT(Oe, confERROR_MODE),
+       #Oep)
+
+# save Unix-style "From_" lines at top of header?
+CONCAT(Of, confSAVE_FROM_LINES)
+
+# temporary file mode
+CONCAT(OF, confTEMP_FILE_MODE)
+
+# match recipients against GECOS field?
+CONCAT(OG, confMATCH_GECOS)
+
+# default GID
+CONCAT(Og, confDEF_GROUP_ID)
+
+# maximum hop count
+CONCAT(Oh, confMAX_HOP)
+
+# location of help file
+CONCAT(OH, ifdef(`HELP_FILE', HELP_FILE, /usr/lib/sendmail.hf))
+
+# ignore dots as terminators in incoming messages?
+CONCAT(Oi, confIGNORE_DOTS)
+
+# Insist that the BIND name server be running to resolve names
+ifdef(`confBIND_OPTS',
+       CONCAT(OI, confBIND_OPTS),
+       #OI)
+
+# deliver MIME-encapsulated error messages?
+CONCAT(Oj, confMIME_FORMAT_ERRORS)
+
+# Forward file search path
+ifdef(`confFORWARD_PATH',
+       CONCAT(OJ, confFORWARD_PATH),
+       #OJ/var/forward/$u:$z/.forward.$w:$z/.forward)
+
+# open connection cache size
+CONCAT(Ok, confMCI_CACHE_SIZE)
+
+# open connection cache timeout
+CONCAT(OK, confMCI_CACHE_TIMEOUT)
+
+# use Errors-To: header?
+CONCAT(Ol, confUSE_ERRORS_TO)
+
+# log level
+CONCAT(OL, confLOG_LEVEL)
+
+# send to me too, even in an alias expansion?
+CONCAT(Om, confME_TOO)
+
+# verify RHS in newaliases?
+CONCAT(On, confCHECK_ALIASES)
+
+# default messages to old style headers if no special punctuation?
+CONCAT(Oo, confOLD_STYLE_HEADERS)
+
+# SMTP daemon options
+ifdef(`confDAEMON_OPTIONS',
+       CONCAT(OO, confDAEMON_OPTIONS),
+       #OOPort=esmtp)
+
+# privacy flags
+CONCAT(Op, confPRIVACY_FLAGS)
+
+# who (if anyone) should get extra copies of error messages
+ifdef(`confCOPY_ERRORS_TO',
+       CONCAT(OP, confCOPY_ERRORS_TO),
+       #OPPostmaster)
+
+# slope of queue-only function
+ifdef(`confQUEUE_FACTOR',
+       CONCAT(Oq, confQUEUE_FACTOR),
+       #Oq600000)
+
+# queue directory
+CONCAT(OQ, ifdef(`QUEUE_DIR', QUEUE_DIR, /var/spool/mqueue))
+
+# read timeout -- now OK per RFC 1123 section 5.3.2
+ifdef(`confREAD_TIMEOUT',
+       CONCAT(Or, confREAD_TIMEOUT),
+       #Ordatablock=10m)
+
+# queue up everything before forking?
+CONCAT(Os, confSAFE_QUEUE)
+
+# status file
+CONCAT(OS, ifdef(`STATUS_FILE', STATUS_FILE, /etc/sendmail.st))
+
+# default message timeout interval
+CONCAT(OT, confMESSAGE_TIMEOUT)
+
+# time zone handling:
+#  if undefined, use system default
+#  if defined but null, use TZ envariable passed in
+#  if defined and non-null, use that info
+ifelse(confTIME_ZONE, `USE_SYSTEM', `#Ot',
+       confTIME_ZONE, `USE_TZ', `',
+       `CONCAT(Ot, confTIME_ZONE)')
+
+# default UID
+CONCAT(Ou, confDEF_USER_ID)
+
+# list of locations of user database file (null means no lookup)
+OU`'ifdef(`confUSERDB_SPEC', `confUSERDB_SPEC')
+
+# fallback MX host
+ifdef(`confFALLBACK_MX',
+       CONCAT(OV, confFALLBACK_MX),
+       #OVfall.back.host.net)
+
+# load average at which we just queue messages
+CONCAT(Ox, confQUEUE_LA)
+
+# load average at which we refuse connections
+CONCAT(OX, confREFUSE_LA)
+
+# work recipient factor
+ifdef(`confWORK_RECIPIENT_FACTOR',
+       CONCAT(Oy, confWORK_RECIPIENT_FACTOR),
+       #Oy30000)
+
+# deliver each queued job in a separate process?
+CONCAT(OY, confSEPARATE_PROC)
+
+# work class factor
+ifdef(`confWORK_CLASS_FACTOR',
+       CONCAT(Oz, confWORK_CLASS_FACTOR),
+       #Oz1800)
+
+# work time factor
+ifdef(`confWORK_TIME_FACTOR',
+       CONCAT(OZ, confWORK_TIME_FACTOR),
+       #OZ90000)
+
+###########################
+#   Message precedences   #
+###########################
+
+Pfirst-class=0
+Pspecial-delivery=100
+Plist=-30
+Pbulk=-60
+Pjunk=-100
+
+#####################
+#   Trusted users   #
+#####################
+
+Troot
+Tdaemon
+Tuucp
+
+#########################
+#   Format of headers   #
+#########################
+
+H?P?Return-Path: $g
+HReceived: $?sfrom $s $.$?_($_) $.by $j ($v/$Z)$?r with $r$. id $i; $b
+H?D?Resent-Date: $a
+H?D?Date: $a
+H?F?Resent-From: $q
+H?F?From: $q
+H?x?Full-Name: $x
+HSubject:
+# HPosted-Date: $a
+# H?l?Received-Date: $b
+H?M?Resent-Message-Id: <$t.$i@$j>
+H?M?Message-Id: <$t.$i@$j>
+#\f
+######################################################################
+######################################################################
+#####
+#####                  REWRITING RULES
+#####
+######################################################################
+######################################################################
+
+undivert(9)dnl
+
+###########################################
+###  Rulset 3 -- Name Canonicalization  ###
+###########################################
+S3
+
+# handle null input and list syntax (translate to <@> special case)
+R$@                    $@ <@>
+R$*:;$*                        $@ $1 :; <@>
+
+# basic textual canonicalization -- note RFC733 heuristic here
+R$*<$*>$*<$*>$*                <$2>$3$4$5                      strip multiple <> <>
+R$*<$*<$+>$*>$*                <$3>$5                          2-level <> nesting
+R$*<>$*                        $@ <@>                          MAIL FROM:<> case
+R$*<$+>$*              $2                              basic RFC821/822 parsing
+
+# make sure <@a,@b,@c:user@d> syntax is easy to parse -- undone later
+R@ $+ , $+             @ $1 : $2                       change all "," to ":"
+
+# localize and dispose of route-based addresses
+R@ $+ : $+             $@ $>_SET_96_ < @$1 > : $2              handle <route-addr>
+
+# find focus for list syntax
+R $+ : $* ; @ $+       $@ $>_SET_96_ $1 : $2 ; < @ $3 >        list syntax
+R $+ : $* ;            $@ $1 : $2;                     list syntax
+
+# find focus for @ syntax addresses
+R$+ @ $+               $: $1 < @ $2 >                  focus on domain
+R$+ < $+ @ $+ >                $1 $2 < @ $3 >                  move gaze right
+R$+ < @ $+ >           $@ $>_SET_96_ $1 < @ $2 >               already canonical
+
+ifdef(`_NO_UUCP_', `dnl',
+`# convert old-style addresses to a domain-based address
+R$- ! $+               $@ $>_SET_96_ $2 < @ $1 .UUCP > resolve uucp names
+R$+ . $- ! $+          $@ $>_SET_96_ $3 < @ $1 . $2 >          domain uucps
+R$+ ! $+               $@ $>_SET_96_ $2 < @ $1 .UUCP > uucp subdomains')
+
+# if we have % signs, take the rightmost one
+R$* % $*               $1 @ $2                         First make them all @s.
+R$* @ $* @ $*          $1 % $2 @ $3                    Undo all but the last.
+R$* @ $*               $@ $>_SET_96_ $1 < @ $2 >               Insert < > and finish
+
+# else we must be a local name
+
+
+################################################
+###  Ruleset _SET_96_ -- bottom half of ruleset 3  ###
+################################################
+
+#  At this point, everything should be in a "local_part<@domain>extra" format.
+S`'_SET_96_
+
+# handle special cases for local names
+R$* < @ localhost > $*         $: $1 < @ $j . > $2             no domain at all
+R$* < @ localhost . $m > $*    $: $1 < @ $j . > $2             local domain
+ifdef(`_NO_UUCP_', `dnl',
+`R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2             .UUCP domain')
+undivert(2)dnl
+
+ifdef(`_NO_UUCP_', `dnl',
+`ifdef(`UUCP_RELAY',
+`# pass UUCP addresses straight through
+R$* < @ $+ . UUCP > $*         $@ $1 < @ $2 . UUCP > $3',
+`# if really UUCP, handle it immediately
+ifdef(`_CLASS_U_',
+`R$* < @ $=U . UUCP > $*       $@ $1 < @ $2 . UUCP > $3', `dnl')
+ifdef(`_CLASS_V_',
+`R$* < @ $=V . UUCP > $*       $@ $1 < @ $2 . UUCP > $3', `dnl')
+ifdef(`_CLASS_W_',
+`R$* < @ $=W . UUCP > $*       $@ $1 < @ $2 . UUCP > $3', `dnl')
+ifdef(`_CLASS_X_',
+`R$* < @ $=X . UUCP > $*       $@ $1 < @ $2 . UUCP > $3', `dnl')
+ifdef(`_CLASS_Y_',
+`R$* < @ $=Y . UUCP > $*       $@ $1 < @ $2 . UUCP > $3', `dnl')
+
+# try UUCP traffic as a local address
+R$* < @ $+ . UUCP > $*         $: $1 < @ $[ $2 $] . UUCP > $3
+ifdef(`_OLD_SENDMAIL_',
+`R$* < @ $+ . $+ . UUCP > $*           $@ $1 < @ $2 . $3 . > $4',
+`R$* < @ $+ . . UUCP > $*              $@ $1 < @ $2 . > $3')')
+')
+ifdef(`_NO_CANONIFY_',
+`# make sure local host names appear canonical
+R$* < @ $=w > $*               $: $1 < @ $2 . > $3',
+`# pass to name server to make hostname canonical
+R$* < @ $* $~P > $*            $: $1 < @ $[ $2 $3 $] > $4')
+
+undivert(8)dnl
+
+# if this is the local hostname, make sure we treat is as canonical
+R$* < @ $j > $*                        $: $1 < @ $j . > $2
+
+
+##################################################
+###  Ruleset 4 -- Final Output Post-rewriting  ###
+##################################################
+S4
+
+R$*<@>                 $@ $1                           handle <> and list:;
+
+# resolve numeric addresses to name if possible
+R$* < @ [ $+ ] > $*    $: $1 < @ $[ [$2] $] > $3       lookup numeric internet addr
+
+# strip trailing dot off possibly canonical name
+R$* < @ $+ . > $*      $1 < @ $2 > $3
+
+# externalize local domain info
+R$* < $+ > $*          $1 $2 $3                        defocus
+R@ $+ : @ $+ : $+      @ $1 , @ $2 : $3                <route-addr> canonical
+R@ $*                  $@ @ $1                         ... and exit
+
+ifdef(`_NO_UUCP_', `dnl',
+`# UUCP must always be presented in old form
+R$+ @ $- . UUCP                $2!$1                           u@h.UUCP => h!u')
+
+# delete duplicate local names
+R$+ % $=w @ $=w                $1 @ $j                         u%host@host => u@host
+
+
+
+##############################################################
+###   Ruleset _SET_97_ -- recanonicalize and call ruleset zero   ###
+###               (used for recursive calls)              ###
+##############################################################
+
+S`'_SET_97_
+R$*                    $: $>3 $1
+R$*                    $@ $>0 $1
+
+
+######################################
+###   Ruleset 0 -- Parse Address   ###
+######################################
+
+S0
+
+R<@>                   $#local $: <>                   special case error msgs
+R$*:;<@>               $#error $@ USAGE $: "list:; syntax illegal for recipient addresses"
+
+ifdef(`_MAILER_smtp_',
+`# handle numeric address spec
+R$* < @ [ $+ ] > $*    $: $1 < @ $[ [$2] $] > $3       numeric internet addr
+R$* < @ [ $+ ] > $*    $#smtp $@ [$2] $: $1 @ [$2] $3  numeric internet spec',
+`dnl')
+
+# now delete the local info -- note $=O to find characters that cause forwarding
+R$* < @ > $*           $@ $>_SET_97_ $1                        user@ => user
+R< @ $=w . > : $*      $@ $>_SET_97_ $2                        @here:... -> ...
+R$* $=O $* < @ $=w . > $@ $>_SET_97_ $1 $2 $3                  ...@here -> ...
+ifdef(`MAILER_TABLE',
+`
+# try mailer table lookup
+R$* <@ $+ > $*         $: < $2 > $1 < @ $2 > $3        extract host name
+R< $+ . > $*           $: < $1 > $2                    strip trailing dot
+R< $+ > $*             $: < $(mailertable $1 $) > $2   lookup
+R< $- : $+ > $*                $# $1 $@ $2 $: $3               check -- resolved?
+R< $+ > $*             $: $>90 <$1> $2                 try domain',
+`dnl')
+
+# short circuit local delivery so forwarded email works
+ifdef(`_LOCAL_NOT_STICKY_',
+`R$=L < @ $=w . >              $#local $: @ $1                 special local names
+R$+ < @ $=w . >                $#local $: $1                   dispose directly',
+`R$+ < @ $=w . >               $: $1 < @ $2 @ $H >             first try hub
+ifdef(`_OLD_SENDMAIL_',
+`R$+ < $+ @ $-:$+ >    $# $3 $@ $4 $: $1 < $2 >        yep ....
+R$+ < $+ @ $+ >                $#relay $@ $3 $: $1 < $2 >      yep ....
+R$+ < $+ @ >           $#local $: $1                   nope, local address',
+`R$+ < $+ @ $+ >               $#local $: $1                   yep ....
+R$+ < $+ @ >           $#local $: @ $1                 nope, local address')')
+undivert(3)dnl
+undivert(4)dnl
+
+ifdef(`_NO_UUCP_', `dnl',
+`# resolve remotely connected UUCP links (if any)
+ifdef(`_CLASS_V_',
+`R$* < @ $=V . UUCP > $*               $#smtp $@ $V $: <@ $V> : $1 @ $2.UUCP $3',
+       `dnl')
+ifdef(`_CLASS_W_',
+`R$* < @ $=W . UUCP > $*               $#smtp $@ $W $: <@ $W> : $1 @ $2.UUCP $3',
+       `dnl')
+ifdef(`_CLASS_X_',
+`R$* < @ $=X . UUCP > $*               $#smtp $@ $X $: <@ $X> : $1 @ $2.UUCP $3',
+       `dnl')')
+
+# resolve fake top level domains by forwarding to other hosts
+ifdef(`BITNET_RELAY',
+`R$*<@$+.BITNET>$*     $#smtp $@ $B $: $1 <@$2.BITNET> $3      user@host.BITNET',
+       `dnl')
+ifdef(`CSNET_RELAY',
+`R$*<@$+.CSNET>$*      $#smtp $@ $C $: $1 <@$2.CSNET> $3       user@host.CSNET',
+       `dnl')
+ifdef(`_MAILER_fax_',
+`R$+ < @ $+ .FAX >     $#fax $@ $2 $: $1                       user@host.FAX',
+`ifdef(`FAX_RELAY',
+`R$*<@$+.FAX>$*                $#smtp $@ $F $: $1 <@$2.FAX> $3         user@host.FAX',
+       `dnl')')
+
+ifdef(`UUCP_RELAY',
+`# forward non-local UUCP traffic to our UUCP relay
+R$*<@$*.UUCP>$*                $#smtp $@ $Y $: <@ $Y> : $1 @ $2.UUCP $3        uucp mail',
+`ifdef(`_MAILER_uucp_',
+`# forward other UUCP traffic straight to UUCP
+R< @ $+ .UUCP > : $+   $#uucp $@ $1 $: $2                      @host.UUCP:...
+R$+ < @ $+ .UUCP >     $#uucp $@ $2 $: $1                      user@host.UUCP',
+       `dnl')')
+
+ifdef(`_LOCAL_RULES_',
+`# figure out what should stay in our local mail system
+undivert(1)',
+`ifdef(`_MAILER_smtp_',
+`# deal with other remote names
+R$* < @ $* > $*                $#smtp $@ $2 $: $1 < @ $2 > $3          user@host.domain')')
+ifdef(`SMART_HOST', `
+# pass names that still have a host to a smarthost
+R$* < @ $* > $*                $: < $S > $1 < @ $2 > $3        glue on smarthost name
+R<$-:$+> $* < @$* > $* $# $1 $@ $2 $: $3 < @ $4 > $5   if non-null, use it
+R<$+> $* < @$* > $*    $#suucp $@ $1 $: $2 < @ $3 > $4 if non-null, use it
+R<> $* < @ $* > $*     $1 < @ $2 > $3                  else strip off gunk',
+`ifdef(`_LOCAL_RULES_', `
+# reject messages that have host names we do not understand
+R$* < @ $* > $*                $#error $@ NOHOST $: Unrecognized host name $2',
+`dnl')')
+ifdef(`_MAILER_USENET_', `
+# addresses sent to net.group.USENET will get forwarded to a newsgroup
+R$+ . USENET           $# usenet $: $1')
+
+ifdef(`_OLD_SENDMAIL_',
+`# forward remaining names to local relay, if any
+R$=L                   $#local $: $1                   special local names
+R$+                    $: $1 < @ $R >                  append relay
+R$+ < @ >              $: $1 < @ $H >                  no relay, try hub
+R$+ < @ >              $#local $: $1                   no relay or hub: local
+R$+ < @ $=w  >         $#local $: $1                   we are relay/hub: local
+R$+ < @ $-:$+ >                $# $2 $@ $3 $: $1               deliver to relay/hub
+R$+ < @ $+ >           $#relay $@ $2 $: $1             deliver to relay/hub',
+
+`# if this is quoted, strip the quotes and try again
+R$+                    $: $(dequote $1 $)              strip quotes
+R$* $=O $*             $@ $>_SET_97_ $1 $2 $3                  try again
+
+# handle locally delivered names
+R$=L                   $#local $: @ $1                 special local names
+R$+                    $#local $: $1                   regular local names
+
+###########################################################################
+###   Ruleset 5 -- special rewriting after aliases have been expanded   ###
+###               (new sendmail only)                                  ###
+###########################################################################
+
+S5
+
+# see if we have a relay or a hub
+R$+                    $: $1 < @ $R >
+R$+ < @ >              $: $1 < @ $H >                  no relay, try hub
+R$+ < @ $=w >          $@ $1                           we are relay/hub: local
+R$+ < @ $-:$+ >                $# $2 $@ $3 $: $1               send to relay or hub
+ifdef(`_MAILER_smtp_',
+`R$+ < @ $+ >          $#relay $@ $2 $: $1             send to relay or hub')')
+ifdef(`MAILER_TABLE',
+`
+
+###########################################################################
+###  Ruleset 90 -- try domain part of mailertable entry                ###
+###               (new sendmail only)                                  ###
+###########################################################################
+
+S90
+R<$- . $+ > $*         $: < $(mailertable .$2 $) > $3  lookup
+R<$- : $+ > $*         $# $1 $@ $2 $: $3               check -- resolved?
+R< . $+ > $*           $@ $>90 <$1> $2                 no -- strip & try again
+R<$*> $*               $@ $2                           no match',
+`dnl')
+#\f
+######################################################################
+######################################################################
+#####
+`#####                 MAILER DEFINITIONS'
+#####
+######################################################################
+######################################################################
+undivert(7)dnl
index e301aac..3d22467 100644 (file)
@@ -1,17 +1,39 @@
-divert(10)
+divert(-1)
 #
 #
-#  Sendmail
-#  Copyright (c) 1983  Eric P. Allman
-#  Berkeley, California
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
 #
 #
-#  Copyright (c) 1983 Regents of the University of California.
-#  All rights reserved.  The Berkeley software License Agreement
-#  specifies the terms and conditions for redistribution.
+# 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.
+#
+VERSIONID(`@(#)version.m4      8.1 (Berkeley) 6/27/93')
 #
 #
-#      @(#)version.m4  1.34 (Berkeley) 12/24/88
 divert(0)
 divert(0)
-######################
-#   Version Number   #
-######################
-
-DZ1.34
+# Configuration version number
+DZ8.1B
diff --git a/usr.sbin/sendmail/cf/mailer/fax.m4 b/usr.sbin/sendmail/cf/mailer/fax.m4
new file mode 100644 (file)
index 0000000..3d9068d
--- /dev/null
@@ -0,0 +1,48 @@
+PUSHDIVERT(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+#      This assumes you already have Sam Leffler's FAX software.
+#
+# 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.
+#
+
+ifdef(`FAX_MAILER_PATH',,
+       `define(`FAX_MAILER_PATH', /usr/local/lib/fax/mailfax)')
+POPDIVERT
+####################################
+###   FAX Mailer specification   ###
+####################################
+
+VERSIONID(`@(#)fax.m4  8.1 (Berkeley) 6/7/93')
+
+Mfax,          P=FAX_MAILER_PATH, F=DFMhu, S=14, R=24, M=100000,
+               A=mailfax $u $h $f
diff --git a/usr.sbin/sendmail/cf/mailer/local.m4 b/usr.sbin/sendmail/cf/mailer/local.m4
new file mode 100644 (file)
index 0000000..60285dd
--- /dev/null
@@ -0,0 +1,57 @@
+PUSHDIVERT(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', `rn')')
+ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /bin/mail)')
+ifdef(`LOCAL_SHELL_PATH',, `define(`LOCAL_SHELL_PATH', /bin/sh)')
+POPDIVERT
+
+##################################################
+###   Local and Program Mailer specification   ###
+##################################################
+
+VERSIONID(`@(#)local.m4        8.1 (Berkeley) 6/7/93')
+
+Mlocal,                P=LOCAL_MAILER_PATH, F=CONCAT(`lsDFMm', LOCAL_MAILER_FLAGS), S=10, R=20,
+               A=mail -d $u
+Mprog,         P=LOCAL_SHELL_PATH, F=lsDFMeu, S=10, R=20, D=$z:/,
+               A=sh -c $u
+
+S10
+R<@>                   $n                      errors to mailer-daemon
+ifdef(`_ALWAYS_ADD_DOMAIN_',
+`R$* < @ $* > $*               $@ $1 < @ $2 > $3       already fully qualified
+R$*                    $: $1 @ $M              add local qualification
+R$* @                  $: $1 @ $j              if $M not defined',
+`dnl')
diff --git a/usr.sbin/sendmail/cf/mailer/smtp.m4 b/usr.sbin/sendmail/cf/mailer/smtp.m4
new file mode 100644 (file)
index 0000000..c97983b
--- /dev/null
@@ -0,0 +1,93 @@
+PUSHDIVERT(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+ifdef(`SMTP_MAILER_FLAGS',,
+       `define(`SMTP_MAILER_FLAGS',
+               `ifdef(`_OLD_SENDMAIL_', `L', `')')')
+POPDIVERT
+#####################################
+###   SMTP Mailer specification   ###
+#####################################
+
+VERSIONID(`@(#)smtp.m4 8.1 (Berkeley) 6/7/93')
+
+Msmtp,         P=[IPC], F=CONCAT(mDFMueXC, SMTP_MAILER_FLAGS), S=11, R=21, E=\r\n,
+               ifdef(`_OLD_SENDMAIL_',, `L=990, ')A=IPC $h
+Mrelay,                P=[IPC], F=CONCAT(mDFMueXC, SMTP_MAILER_FLAGS), S=11, R=19, E=\r\n,
+               ifdef(`_OLD_SENDMAIL_',, `L=2040, ')A=IPC $h
+
+S11
+
+# do sender/recipient common rewriting
+R$+                    $: $>19 $1
+
+# if already @ qualified, we are done
+R$* < @ $* > $*                $@ $1 < @ $2 > $3               already qualified
+
+# don't qualify list:; syntax
+R$* :; <@>             $@ $1 :;
+
+# unqualified names (e.g., "eric") "come from" $M
+R$=E                   $@ $1 < @ $j>                   show exposed names
+R$+                    $: $1 < @ $M >                  user w/o host
+R$+ <@>                        $: $1 < @ $j >                  in case $M undefined
+
+S21
+
+# do sender/recipient common rewriting
+R$+                    $: $>19 $1
+
+# if already @ qualified, we are done
+R$* < @ $* > $*                $@ $1 < @ $2 > $3               already qualified
+
+# don't qualify list:; syntax
+R$* :; <@>             $@ $1 :;
+
+# unqualified names (e.g., "eric") are qualified by local host
+R$+                    $: $1 < @ $j >
+
+S19
+
+# pass <route-addr>s through
+R< @ $+ > $*           $@ < @ $1 > $2                  resolve <route-addr>
+
+# output fake domains as user%fake@relay
+ifdef(`BITNET_RELAY',
+`R$+ <@ $+ . BITNET >  $: $1 % $2 .BITNET < @ $B >     user@host.BITNET',
+       `dnl')
+ifdef(`CSNET_RELAY',
+`R$+ <@ $+ . CSNET >   $: $1 % $2 .CSNET < @ $C >      user@host.CSNET',
+       `dnl')
+ifdef(`_NO_UUCP_', `dnl',
+`R$+ <@ $+ . UUCP >    $: $2 ! $1 < @ $j >             user@host.UUCP')
diff --git a/usr.sbin/sendmail/cf/mailer/usenet.m4 b/usr.sbin/sendmail/cf/mailer/usenet.m4
new file mode 100644 (file)
index 0000000..4a2fdda
--- /dev/null
@@ -0,0 +1,47 @@
+PUSHDIVERT(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+ifdef(`USENET_MAILER_PATH',, `define(`USENET_MAILER_PATH', /usr/lib/news/inews)')
+ifdef(`USENET_MAILER_FLAGS',, `define(`USENET_MAILER_FLAGS', `rlsDFMmn')')
+ifdef(`USENET_MAILER_ARGS',, `define(`USENET_MAILER_ARGS', `-m -h -n')')
+POPDIVERT
+####################################
+###  USENET Mailer specification ###
+####################################
+
+VERSIONID(`@(#)usenet.m4       8.1 (Berkeley) 6/7/93')
+
+Musenet,       P=USENET_MAILER_PATH, F=USENET_MAILER_FLAGS, S=10, R=20,
+               A=inews USENET_MAILER_ARGS $u
diff --git a/usr.sbin/sendmail/cf/mailer/uucp.m4 b/usr.sbin/sendmail/cf/mailer/uucp.m4
new file mode 100644 (file)
index 0000000..0bbadcd
--- /dev/null
@@ -0,0 +1,83 @@
+PUSHDIVERT(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+ifdef(`UUCP_MAILER_PATH',, `define(`UUCP_MAILER_PATH', /usr/bin/uux)')
+ifdef(`UUCP_MAILER_FLAGS',, `define(`UUCP_MAILER_FLAGS', `')')
+POPDIVERT
+#####################################
+###   UUCP Mailer specification   ###
+#####################################
+
+VERSIONID(`@(#)uucp.m4 8.1 (Berkeley) 6/7/93')
+
+Msuucp,                P=UUCP_MAILER_PATH, F=CONCAT(mDFMhuU, UUCP_MAILER_FLAGS), S=12, R=22, M=100000,
+               A=uux - -r -z -a$f -gC $h!rmail ($u)
+
+Muucp,         P=UUCP_MAILER_PATH, F=CONCAT(DFMhuU, UUCP_MAILER_FLAGS), S=12, R=22, M=100000,
+               A=uux - -r -z -a$f -gC $h!rmail ($u)
+
+# sender rewriting
+S12
+
+# handle error address as a special case
+R<@>                           $n                      errors to mailer-daemon
+
+# don't qualify list:; syntax
+R$* :; <@>                     $@ $1 :;
+
+R$* < @ $* . >                 $1 < @ $2 >             strip trailing dots
+R$* < @ $j >                   $1                      strip local name
+R$* < @ $- . UUCP >            $2 ! $1                 convert to UUCP format
+R$* < @ $+ >                   $2 ! $1                 convert to UUCP format
+R$+                            $: $k ! $1              prepend our name
+
+# recipient rewriting
+S22
+
+# don't touch list:; syntax
+R$* :; <@>                     $@ $1 ;:
+
+R$* < @ $* . >                 $1 < @ $2 >             strip trailing dots
+R$* < @ $j >                   $1                      strip local name
+R$* < @ $- . UUCP >            $2 ! $1                 convert to UUCP format
+R$* < @ $+ >                   $2 ! $1                 convert to UUCP format
+
+PUSHDIVERT(4)
+# resolve locally connected UUCP links
+R< @ $=Y . UUCP > : $+         $#suucp $@ $1 $: $2     @host.UUCP: ...
+R< @ $=U . UUCP > : $+         $#uucp $@ $1 $: $2      @host.UUCP: ...
+R$+ < @ $=Y . UUCP >           $#suucp $@ $2 $: $1     user@host.UUCP
+R$+ < @ $=U . UUCP >           $#uucp $@ $2 $: $1      user@host.UUCP
+POPDIVERT
diff --git a/usr.sbin/sendmail/cf/ostype/bsd4.3.m4 b/usr.sbin/sendmail/cf/ostype/bsd4.3.m4
new file mode 100644 (file)
index 0000000..3c519ca
--- /dev/null
@@ -0,0 +1,38 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)bsd4.3.m4       8.1 (Berkeley) 6/7/93')
+define(`QUEUE_DIR', /usr/spool/mqueue)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/bsd4.4.m4 b/usr.sbin/sendmail/cf/ostype/bsd4.4.m4
new file mode 100644 (file)
index 0000000..bdaa1fc
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#
+
+divert(0)
+VERSIONID(`@(#)bsd4.4.m4       8.1 (Berkeley) 6/7/93')
+define(`HELP_FILE', /usr/share/misc/sendmail.hf)dnl
+define(`STATUS_FILE', /var/log/sendmail.st)dnl
+define(`LOCAL_MAILER_PATH', /usr/libexec/mail.local)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/hpux.m4 b/usr.sbin/sendmail/cf/ostype/hpux.m4
new file mode 100644 (file)
index 0000000..ea1c05b
--- /dev/null
@@ -0,0 +1,39 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)hpux.m4 8.1 (Berkeley) 6/7/93')
+define(`_HPUX_', `')dnl
+define(`LOCAL_MAILER_FLAGS', `')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/irix.m4 b/usr.sbin/sendmail/cf/ostype/irix.m4
new file mode 100644 (file)
index 0000000..7e4e8dc
--- /dev/null
@@ -0,0 +1,38 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)irix.m4 8.1 (Berkeley) 6/7/93')
+define(`LOCAL_MAILER_FLAGS', Ehu)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/osf1.m4 b/usr.sbin/sendmail/cf/ostype/osf1.m4
new file mode 100644 (file)
index 0000000..fbc4832
--- /dev/null
@@ -0,0 +1,41 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)osf1.m4 8.1 (Berkeley) 6/7/93')
+ifdef(`_OLD_SENDMAIL_', `define(`NEED_DOMAIN', `')')dnl
+define(`ALIAS_FILE', /usr/adm/sendmail/aliases)dnl
+define(`STATUS_FILE', /usr/adm/sendmail/sendmail.st)dnl
+define(`HELP_FILE', /usr/share/lib/sendmail.hf)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/riscos4.5.m4 b/usr.sbin/sendmail/cf/ostype/riscos4.5.m4
new file mode 100644 (file)
index 0000000..847cb0e
--- /dev/null
@@ -0,0 +1,37 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)riscos4.5.m4    8.1 (Berkeley) 6/7/93')
diff --git a/usr.sbin/sendmail/cf/ostype/sunos3.5.m4 b/usr.sbin/sendmail/cf/ostype/sunos3.5.m4
new file mode 100644 (file)
index 0000000..fe76931
--- /dev/null
@@ -0,0 +1,37 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)sunos3.5.m4     8.1 (Berkeley) 6/7/93')
diff --git a/usr.sbin/sendmail/cf/ostype/sunos4.1.m4 b/usr.sbin/sendmail/cf/ostype/sunos4.1.m4
new file mode 100644 (file)
index 0000000..cfa7a9a
--- /dev/null
@@ -0,0 +1,37 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)sunos4.1.m4     8.1 (Berkeley) 6/7/93')
diff --git a/usr.sbin/sendmail/cf/ostype/ultrix4.1.m4 b/usr.sbin/sendmail/cf/ostype/ultrix4.1.m4
new file mode 100644 (file)
index 0000000..87c4425
--- /dev/null
@@ -0,0 +1,38 @@
+divert(-1)
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+divert(0)
+VERSIONID(`@(#)ultrix4.1.m4    8.1 (Berkeley) 6/7/93')
+ifdef(`_OLD_SENDMAIL_', `define(`NEED_DOMAIN', `')')dnl
diff --git a/usr.sbin/sendmail/cf/sh/makeinfo.sh b/usr.sbin/sendmail/cf/sh/makeinfo.sh
new file mode 100644 (file)
index 0000000..c7c3633
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# Copyright (c) 1983 Eric P. Allman
+# Copyright (c) 1988, 1993
+#      The Regents of the University of California.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+#    must display the following acknowledgement:
+#      This product includes software developed by the University of
+#      California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+#      @(#)makeinfo.sh 8.1 (Berkeley) 6/7/93
+#
+
+echo '#####' built by `whoami` on `date`
+echo '#####' in `pwd` on `hostname`
diff --git a/usr.sbin/sendmail/cf/siteconfig/uucp.cogsci.m4 b/usr.sbin/sendmail/cf/siteconfig/uucp.cogsci.m4
new file mode 100644 (file)
index 0000000..33c7151
--- /dev/null
@@ -0,0 +1,6 @@
+SITE(contessa)
+SITE(emind)
+SITE(hoptoad)
+SITE(nkainc)
+SITE(well)
+SITE(ferdy)
diff --git a/usr.sbin/sendmail/cf/siteconfig/uucp.old.arpa.m4 b/usr.sbin/sendmail/cf/siteconfig/uucp.old.arpa.m4
new file mode 100644 (file)
index 0000000..81d5e94
--- /dev/null
@@ -0,0 +1,4 @@
+SITE(endotsew)
+SITE(fateman)
+SITE(interlan)
+SITE(metron)
diff --git a/usr.sbin/sendmail/cf/siteconfig/uucp.ucbarpa.m4 b/usr.sbin/sendmail/cf/siteconfig/uucp.ucbarpa.m4
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/usr.sbin/sendmail/cf/siteconfig/uucp.ucbvax.m4 b/usr.sbin/sendmail/cf/siteconfig/uucp.ucbvax.m4
new file mode 100644 (file)
index 0000000..ee2c34f
--- /dev/null
@@ -0,0 +1,73 @@
+SITE(Padova)
+SITE(Shasta)
+SITE(alice)
+SITE(allegra)
+SITE(amdcad)
+SITE(att)
+SITE(attunix)
+SITE(avsd)
+SITE(bellcore bellcor)
+SITE(calma)
+SITE(cithep)
+SITE(cnmat)
+SITE(craig)
+SITE(craylab)
+SITE(decusj)
+SITE(decvax, S)
+SITE(decwrl)
+SITE(dssovax)
+SITE(eagle)
+SITE(ecovax)
+SITE(floyd)
+SITE(franz)
+SITE(geoff)
+SITE(harpo)
+SITE(ho3e2)
+SITE(hpda)
+SITE(hplabs)
+SITE(ibmsupt ibmuupa ibmpa)
+SITE(iiasa70)
+SITE(imagen)
+SITE(isunix menlo70)
+SITE(kentmth)
+SITE(lbl-csam lbl-csa)
+SITE(lime)
+SITE(mothra)
+SITE(mseonyx)
+SITE(mtxinu)
+SITE(pixar)
+SITE(pur-ee)
+SITE(purdue)
+SITE(pwbd)
+SITE(sdcarl)
+SITE(sftig)
+SITE(sgi olympus)
+SITE(sii)
+SITE(srivisi)
+SITE(ssyx)
+SITE(sun)
+SITE(trwrb)
+SITE(twg)
+SITE(ucivax)
+SITE(ucla-se)
+SITE(ucla-cs)
+SITE(ucsbcsl ucsbhub)
+SITE(ucscc)
+SITE(ucsd)
+SITE(ucsfcgl)
+SITE(ucsfmis)
+SITE(ulysses)
+SITE(unisoft)
+SITE(unmvax)
+SITE(usenix)
+SITE(uw)
+SITE(uwvax)
+SITE(vax135)
+SITE(voder)
+SITE(wheps)
+SITE(whuxle)
+SITE(whuxlj)
+SITE(xicomp)
+SITE(xprin)
+SITE(zehntel)
+SITE(zilog)
diff --git a/usr.sbin/sendmail/contrib/README b/usr.sbin/sendmail/contrib/README
new file mode 100644 (file)
index 0000000..dcf5c8f
--- /dev/null
@@ -0,0 +1,10 @@
+Everything in this directory (except this file) has been contributed.
+We will not fix bugs in these programs.  Contact the original author
+for assistance.
+
+Some of these are patches to sendmail itself.  You may need to take
+care -- some of the patches may be out of date with the latest release
+of sendmail.  Also, the previous comment applies -- patches belong to
+the original author, not to me.
+
+Eric Allman, 26 May 1993
diff --git a/usr.sbin/sendmail/contrib/bitdomain.c b/usr.sbin/sendmail/contrib/bitdomain.c
new file mode 100644 (file)
index 0000000..4fad761
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * By John G. Myers, jgm+@cmu.edu
+ * Version 1.1
+ *
+ * Process a BITNET "internet.listing" file, producing output
+ * suitable for input to makemap.
+ *
+ * The input file can be obtained via anonymous FTP to bitnic.educom.edu.
+ * Change directory to "netinfo" and get the file internet.listing
+ * The file is updated monthly.
+ *
+ * Feed the output of this program to "makemap hash /etc/bitdomain.db"
+ * to create the table used by the "FEATURE(bitdomain)" config file macro.
+ * If your sendmail does not have the db library compiled in, you can instead
+ * use "makemap dbm /etc/bitdomain" and
+ * "FEATURE(bitdomain,`dbm -o /etc/bitdomain')"
+ *
+ * The bitdomain table should be rebuilt monthly.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <string.h>
+
+/* don't use sizeof because sizeof(long) is different on 64-bit machines */
+#define SHORTSIZE      2       /* size of a short (really, must be 2) */
+#define LONGSIZE       4       /* size of a long (really, must be 4) */
+
+typedef union
+{
+       HEADER  qb1;
+       char    qb2[PACKETSZ];
+} querybuf;
+
+extern int h_errno;
+extern char *malloc();
+extern char *optarg;
+extern int optind;
+
+char *lookup();
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+    int opt;
+
+    while ((opt = getopt(argc, argv, "o:")) != EOF) {
+       switch (opt) {
+       case 'o':
+           if (!freopen(optarg, "w", stdout)) {
+               perror(optarg);
+               exit(1);
+           }
+           break;
+
+       default:
+           fprintf(stderr, "usage: %s [-o outfile] [internet.listing]\n",
+                   argv[0]);
+           exit(1);
+       }
+    }
+
+    if (optind < argc) {
+       if (!freopen(argv[optind], "r", stdin)) {
+           perror(argv[optind]);
+           exit(1);
+       }
+    }
+    readfile(stdin);
+    finish();
+    exit(0);
+}
+
+/*
+ * Parse and process an input file
+ */
+readfile(infile)
+FILE *infile;
+{
+    int skippingheader = 1;
+    char buf[1024], *node, *hostname, *p;
+
+    while (fgets(buf, sizeof(buf), infile)) {
+       for (p = buf; *p && isspace(*p); p++);
+       if (!*p) {
+           skippingheader = 0;
+           continue;
+       }
+       if (skippingheader) continue;
+
+       node = p;
+       for (; *p && !isspace(*p); p++) {
+           if (isupper(*p)) *p = tolower(*p);
+       }
+       if (!*p) {
+           fprintf(stderr, "%-8s: no domain name in input file\n", node);
+           continue;
+       }
+       *p++ = '\0';
+
+       for (; *p && isspace(*p); p++) ;
+       if (!*p) {
+           fprintf(stderr, "%-8s no domain name in input file\n", node);
+           continue;
+       }
+
+       hostname = p;
+       for (; *p && !isspace(*p); p++) {
+           if (isupper(*p)) *p = tolower(*p);
+       }
+       *p = '\0';
+
+       /* Chop off any trailing .bitnet */
+       if (strlen(hostname) > 7 &&
+           !strcmp(hostname+strlen(hostname)-7, ".bitnet")) {
+           hostname[strlen(hostname)-7] = '\0';
+       }
+       entry(node, hostname, sizeof(buf)-(hostname - buf));
+    }
+}
+
+/*
+ * Process a single entry in the input file.
+ * The entry tells us that "node" expands to "domain".
+ * "domain" can either be a domain name or a bitnet node name
+ * The buffer pointed to by "domain" may be overwritten--it
+ * is of size "domainlen".
+ */
+entry(node, domain, domainlen)
+char *node;
+char *domain;
+char *domainlen;
+{
+    char *otherdomain, *p, *err;
+
+    /* See if we have any remembered information about this node */
+    otherdomain = lookup(node);
+
+    if (otherdomain && strchr(otherdomain, '.')) {
+       /* We already have a domain for this node */
+       if (!strchr(domain, '.')) {
+           /*
+            * This entry is an Eric Thomas FOO.BITNET kludge.
+            * He doesn't want LISTSERV to do transitive closures, so we
+            * do them instead.  Give the the domain expansion for "node"
+            * (which is in "otherdomian") to FOO (which is in "domain")
+            * if "domain" doesn't have a domain expansion already.
+            */
+           p = lookup(domain);
+           if (!p || !index(p, '.')) remember(domain, otherdomain);
+       }
+    }
+    else {
+       if (!strchr(domain, '.') || valhost(domain, domainlen)) {
+           remember(node, domain);
+           if (otherdomain) {
+               /*
+                * We previously mapped the node "node" to the node
+                * "otherdomain".  If "otherdomain" doesn't already
+                * have a domain expansion, give it the expansion "domain".
+                */
+               p = lookup(otherdomain);
+               if (!p || !index(p, '.')) remember(otherdomain, domain);
+           }
+       }
+       else {
+           switch (h_errno) {
+           case HOST_NOT_FOUND:
+               err = "not registered in DNS";
+               break;
+
+           case TRY_AGAIN:
+               err = "temporary DNS lookup failure";
+               break;
+
+           case NO_RECOVERY:
+               err = "non-recoverable nameserver error";
+               break;
+
+           case NO_DATA:
+               err = "registered in DNS, but not mailable";
+               break;
+               
+           default:
+               err = "unknown nameserver error";
+               break;
+           }
+
+           fprintf(stderr, "%-8s %s %s\n", node, domain, err);
+       }
+    }
+}
+
+/*
+ * Validate whether the mail domain "host" is registered in the DNS.
+ * If "host" is a CNAME, it is expanded in-place if the expansion fits
+ * into the buffer of size "hbsize".  Returns nonzero if it is, zero
+ * if it is not.  A BIND error code is left in h_errno.
+ */
+int
+valhost(host, hbsize)
+       char *host;
+       int hbsize;
+{
+       register u_char *eom, *ap;
+       register int n; 
+       HEADER *hp;
+       querybuf answer;
+       int ancount, qdcount;
+       int ret;
+       int type;
+       int qtype;
+       char nbuf[1024];
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+               return (0);
+
+       _res.options &= ~(RES_DNSRCH|RES_DEFNAMES);
+       _res.retrans = 30;
+       _res.retry = 10;
+
+       qtype = T_ANY;
+
+       for (;;) {
+               h_errno = NO_DATA;
+               ret = res_querydomain(host, "", C_IN, qtype,
+                                     &answer, sizeof(answer));
+               if (ret <= 0)
+               {
+                       if (errno == ECONNREFUSED || h_errno == TRY_AGAIN)
+                       {
+                               /* the name server seems to be down */
+                               h_errno = TRY_AGAIN;
+                               return 0;
+                       }
+
+                       if (h_errno != HOST_NOT_FOUND)
+                       {
+                               /* might have another type of interest */
+                               if (qtype == T_ANY)
+                               {
+                                       qtype = T_A;
+                                       continue;
+                               }
+                               else if (qtype == T_A)
+                               {
+                                       qtype = T_MX;
+                                       continue;
+                               }
+                       }
+
+                       /* otherwise, no record */
+                       return 0;
+               }
+
+               /*
+               **  This might be a bogus match.  Search for A, MX, or
+               **  CNAME records.
+               */
+
+               hp = (HEADER *) &answer;
+               ap = (u_char *) &answer + sizeof(HEADER);
+               eom = (u_char *) &answer + ret;
+
+               /* skip question part of response -- we know what we asked */
+               for (qdcount = ntohs(hp->qdcount); qdcount--; ap += ret + QFIXEDSZ)
+               {
+                       if ((ret = dn_skipname(ap, eom)) < 0)
+                       {
+                               return 0;               /* ???XXX??? */
+                       }
+               }
+
+               for (ancount = ntohs(hp->ancount); --ancount >= 0 && ap < eom; ap += n)
+               {
+                       n = dn_expand((u_char *) &answer, eom, ap,
+                                     (u_char *) nbuf, sizeof nbuf);
+                       if (n < 0)
+                               break;
+                       ap += n;
+                       GETSHORT(type, ap);
+                       ap += SHORTSIZE + LONGSIZE;
+                       GETSHORT(n, ap);
+                       switch (type)
+                       {
+                         case T_MX:
+                         case T_A:
+                               return 1;
+
+                         case T_CNAME:
+                               /* value points at name */
+                               if ((ret = dn_expand((u_char *)&answer,
+                                   eom, ap, (u_char *)nbuf, sizeof(nbuf))) < 0)
+                                       break;
+                               if (strlen(nbuf) < hbsize) {
+                                   (void)strcpy(host, nbuf);
+                               }
+                               return 1;
+
+                         default:
+                               /* not a record of interest */
+                               continue;
+                       }
+               }
+
+               /*
+               **  If this was a T_ANY query, we may have the info but
+               **  need an explicit query.  Try T_A, then T_MX.
+               */
+
+               if (qtype == T_ANY)
+                       qtype = T_A;
+               else if (qtype == T_A)
+                       qtype = T_MX;
+               else
+                       return 0;
+       }
+}
+
+struct entry {
+    struct entry *next;
+    char *node;
+    char *domain;
+};
+struct entry *firstentry;
+
+/*
+ * Find any remembered information about "node"
+ */
+char *lookup(node)
+char *node;
+{
+    struct entry *p;
+
+    for (p = firstentry; p; p = p->next) {
+       if (!strcmp(node, p->node)) {
+           return p->domain;
+       }
+    }
+    return 0;
+}
+
+/*
+ * Mark the node "node" as equivalent to "domain".  "domain" can either
+ * be a bitnet node or a domain name--if it is the latter, the mapping
+ * will be written to stdout.
+ */
+remember(node, domain)
+char *node;
+char *domain;
+{
+    struct entry *p;
+
+    if (strchr(domain, '.')) {
+       fprintf(stdout, "%-8s %s\n", node, domain);
+    }
+
+    for (p = firstentry; p; p = p->next) {
+       if (!strcmp(node, p->node)) {
+           p->domain = malloc(strlen(domain)+1);
+           if (!p->domain) {
+               goto outofmemory;
+           }
+           strcpy(p->domain, domain);
+           return;
+       }
+    }
+
+    p = (struct entry *)malloc(sizeof(struct entry));
+    if (!p) goto outofmemory;
+
+    p->next = firstentry;
+    firstentry = p;
+    p->node = malloc(strlen(node)+1);
+    p->domain = malloc(strlen(domain)+1);
+    if (!p->node || !p->domain) goto outofmemory;
+    strcpy(p->node, node);
+    strcpy(p->domain, domain);
+    return;
+
+  outofmemory:
+    fprintf(stderr, "Out of memory\n");
+    exit(1);
+}
+
+/*
+ * Walk through the database, looking for any cases where we know
+ * node FOO is equivalent to node BAR and node BAR has a domain name.
+ * For those cases, give FOO the same domain name as BAR.
+ */
+finish()
+{
+    struct entry *p;
+    char *domain;
+
+    for (p = firstentry; p; p = p->next) {
+       if (!strchr(p->domain, '.') && (domain = lookup(p->domain))) {
+           remember(p->node, domain);
+       }
+    }
+}
+           
diff --git a/usr.sbin/sendmail/contrib/expn.pl b/usr.sbin/sendmail/contrib/expn.pl
new file mode 100644 (file)
index 0000000..4012699
--- /dev/null
@@ -0,0 +1,1239 @@
+#!/usr/local/bin/perl
+'di';
+'ig00';
+#       THIS PROGRAM IS ITS OWN MANUAL PAGE.  INSTALL IN man & bin.
+#      groff cannot handle the wrapman constructs, so if you use 
+#      groff, you must cut the manual part out and install it
+#      separately.
+
+# hardcoded constants, should work fine for BSD-based systems
+$AF_INET = 2;
+$SOCK_STREAM = 1;
+$sockaddr = 'S n a4 x8';
+
+# system requirements:
+#      must have 'nslookup' and 'hostname' programs.
+
+# version 3.2, 5/5/93
+
+# TODO:
+#      CERNVM.CERN.CH needs simple logins for the expn command.
+#      format with groff.
+#      less magic should apply to command-line addresses
+#      less magic should apply to local addresses
+
+# Checklist: (hard addresses)
+#      harry@hofmann.cs.Berkeley.EDU -> harry@tenet (.berkeley.edu)
+#      bks@cs.berkeley.edu -> shiva.CS (.berkeley.edu)
+#      dan@tc.cornell.edu -> brown@tiberius (.tc.cornell.edu)
+
+#############################################################################
+#
+#  Copyright (c) 1993 David Muir Sharnoff
+#  All rights reserved.
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions
+#  are met:
+#  1. Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+#  2. Redistributions in binary form must reproduce the above copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#  3. All advertising materials mentioning features or use of this software
+#     must display the following acknowledgement:
+#       This product includes software developed by the David Muir Sharnoff.
+#  4. The name of David Sharnoff may not be used to endorse or promote products
+#     derived from this software without specific prior written permission.
+#
+#  THIS SOFTWARE IS PROVIDED BY THE DAVID MUIR SHARNOFF ``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 DAVID MUIR SHARNOFF 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.
+#
+# This copyright notice derrived from material copyrighted by the Regents
+# of the University of California.
+#
+# Contributions accepted.
+#
+#############################################################################
+
+# overall structure:
+#      in an effort to not trace each address individually, but rather
+#      ask each server in turn a whole bunch of questions, addresses to
+#      be expanded are queued up.
+#
+#      This means that all account w.r.t. an address must be stored in
+#      various arrays.  Generally these arrays are indexed by the
+#      string "$addr *** $server" where $addr is the address to be
+#      expanded "foo" or maybe "foo@bar" and $server is the hostname
+#      of the SMTP server to contact.
+#
+
+# important global variables:
+#
+# @hosts : list of servers still to be contacted
+# $server : name of the current we are currently looking at
+# @users = $users{@hosts[0]} : addresses to expand at this server
+# $u = $users[0] : the current address being expanded
+# $names{"$users[0] *** $server"} : the 'name' associated with the address
+# $mxbacktrace{"$users[0] *** $server"} : record of mx expansion
+# $mx_secondary{$server} : other mx relays at the same priority
+# $domainify_fallback{"$users[0] *** $server"} : alternative names to try 
+#      instead of $server if $server doesn't work
+# $temporary_redirect{"$users[0] *** $server"} : when trying alternates,
+#      temporarily channel all tries along current path
+# $giveup{$server} : do not bother expanding addresses at $server
+# $verbose : -v
+# $watch : -w
+# $vw : -v or -w
+# $debug : -d
+# $valid : -a
+# $levels : -1
+# S : the socket connection to $server
+
+$have_nslookup = 1;    # we have the nslookup program
+$port = 'smtp';
+$av0 = $0;
+$0 = "$av0 - running hostname";
+$ENV{'PATH'} .= ":/usr/etc" unless $ENV{'PATH'} =~ m,/usr/etc,;
+chop($hostname = `hostname`);
+select(STDERR);
+
+$usage = "Usage: $av0 [-1avwd] user[@host] [user2[host2] ...]";
+$0 = "$av0 - parsing args";
+for $a (@ARGV) {
+       die $usage if $a eq "-";
+       while ($a =~ s/^(-.*)([1avwd])/$1/) {
+               eval '$'."flag_$2 += 1";
+       }
+       next if $a eq "-";
+       die $usage if $a =~ /^-/;
+       &expn(&parse($a,$hostname,undef,1,1));
+}
+$verbose = $flag_v;
+$watch = $flag_w;
+$vw = $flag_v + $flag_w;
+$debug = $flag_d;
+$valid = $flag_a;
+$levels = $flag_1;
+
+die $usage unless @hosts;
+if ($valid) {
+       if ($valid == 1) {
+               $validRequirement = 0.8;
+       } elsif ($valid == 2) {
+               $validRequirement = 1.0;
+       } elsif ($valid == 3) {
+               $validRequirement = 0.9;
+       } else {
+               $validRequirement = (1 - (1/($valid-3)));
+               print "validRequirement = $validRequirement\n" if $debug;
+       }
+}
+
+$0 = "$av0 - building local socket";
+($name,$aliases,$proto) = getprotobyname('tcp');
+($name,$aliases,$port) = getservbyname($port,'tcp')
+       unless $port =~ /^\d+/;
+($name,$aliases,$type,$len,$thisaddr) = gethostbyname($hostname);
+$this = pack($sockaddr, $AF_INET, 0, $thisaddr);
+
+HOST:
+while (@hosts) {
+       $server = shift(@hosts);
+       @users = split(' ',$users{$server});
+       delete $users{$server};
+
+       # is this server already known to be bad?
+       $0 = "$av0 - looking up $server";
+       if ($giveup{$server}) {
+               &giveup('mx domainify',$giveup{$server});
+               next;
+       }
+
+       # do we already have an mx record for this host?
+       next HOST if &mxredirect($server,*users);
+
+       # look it up, or try for an mx.
+       $0 = "$av0 - gethostbyname($server)";
+
+
+       ($name,$aliases,$type,$len,$thataddr) = gethostbyname($server);
+       # if we can't get an A record, try for an MX record.
+       unless($thataddr) {
+               &mxlookup(1,$server,"$server: could not resolve name",*users);
+               next HOST;
+       }
+                               
+       # get a connection, or look for an mx
+       $0 = "$av0 - socket to $server";
+       $that = pack($sockaddr, $AF_INET, $port, $thataddr);
+       socket(S, $AF_INET, $SOCK_STREAM, $proto)
+               || die "socket: $!";
+       $0 = "$av0 - bind to $server";
+       bind(S, $this) 
+               || die "bind $hostname,0: $!";
+       $0 = "$av0 - connect to $server";
+       print "debug = $debug server = $server\n" if $debug > 8;
+       if (! connect(S, $that) || ($debug == 10 && $server =~ /relay\d.UU.NET$/i)) {
+               $0 = "$av0 - $server: could not connect: $!\n";
+               $emsg = $!;
+               unless (&mxlookup(0,$server,"$server: could not connect: $!",*users)) {
+                       &giveup('mx',"$server: Could not connect: $emsg");
+               }
+               next HOST;
+       }
+       select((select(S),$| = 1)[0]); # don't buffer output to S
+
+       # read the greeting
+       $0 = "$av0 - talking to $server";
+       while(<S>) {
+               print if $watch;
+               if (/^(\d+)([- ])/) {
+                       if ($1 != 220) {
+                               $0 = "$av0 - bad numeric responce from $server";
+                               &toss($2);
+                               print STDERR "$server: NOT 220 greeting: $_"
+                                       if ($debug || $vw);
+                               if (&mxlookup(0,$server,"$server: did not respond with a 220 greeting",*users)) {
+                                       close(S);
+                                       next HOST;
+                               }
+                       }
+                       last if ($2 eq " ");
+               } else {
+                       $0 = "$av0 - bad responce from $server";
+                       print STDERR "$server: NOT 220 greeting: $_"
+                               if ($debug || $vw);
+                       unless (&mxlookup(0,$server,"$server: did not respond with SMTP codes",*users)) {
+                               &giveup('',"$server: did not talk SMTP");
+                       }
+                       close(S);
+                       next HOST;
+               }
+       }
+       
+       # if this causes problems, remove it
+       $0 = "$av0 - sending helo to $server";
+       &ps("helo $hostname");
+       while(<S>) {
+               print if $watch;
+               last if /^\d+ /;
+       }
+
+       # try the users, one by one
+       USER:
+       while(@users) {
+               $u = shift(@users);
+               $0 = "$av0 - expanding $u [\@$server]";
+
+               # do we already have a name for this user?
+               $oldname = $names{"$u *** $server"};
+
+               print &compact($u,$server)." ->\n" if ($verbose && ! $valid);
+               if ($valid) {
+                       #
+                       # when running with -a, we delay taking any action 
+                       # on the results of our query until we have looked
+                       # at the complete output.  @toFinal stores expansions
+                       # that will be final if we take them.  @toExpn stores
+                       # expnansions that are not final.  @isValid keeps
+                       # track of our ability to send mail to each of the
+                       # expansions.
+                       #
+                       @isValid = ();
+                       @toFinal = ();
+                       @toExpn = ();
+               }
+               &ps("expn $u");
+               $said_something = 0;
+               while($s = <S>) {
+                       $said_something = 1;
+
+                       # make sure the server is talking the right language
+                       if ($s =~ /^(\d+)([- ])/) {
+                               if ($1 != 250 && $1 != 550) {
+                                       &toss($2);
+                                       &ps("vrfy $u");
+                                       $s = <S>;
+                                       if ($s =~ /^(\d+)/) {
+                                               if ($1 != 250 && $1 != 550) {
+                                                       &toss($2);
+                                                       &giveup('',"$server: expn/vrfy not implemented",$u);
+                                                       last USER;
+                                               }
+                                       }
+                               }
+                       }
+
+                       $s =~ s/[\n\r]//g;
+                       $0 = "$av0 - parsing $server: $s";
+                       print "$s\n" if $watch;
+                       if ($s =~ /^250([- ])(.+)/) {
+                               ($done,$addr) = ($1,$2);
+                               ($newhost, $newaddr, $newname) =  &parse($addr,$server,$oldname);
+                               print "($newhost, $newaddr, $newname) = &parse($addr, $server, $oldname)\n" if $debug;
+                               if (! $newhost) {
+                                       # no expansion is possible w/o a new server to call
+                                       if ($valid) {
+                                               push(@isValid, &validAddr($newaddr));
+                                               push(@toFinal,$newaddr,$server,$newname);
+                                       } else {
+                                               &verbose(&final($newaddr,$server,$newname));
+                                       }
+                               } else {
+                                       $newmxhost = &mx($newhost,$newaddr);
+                                       print "$newmxhost = &mx($newhost)\n" 
+                                               if ($debug && $newhost ne $newmxhost);
+                                       $0 = "$av0 - parsing $newaddr [@$newmxhost]";
+                                       print "levels = $levels, level{$u *** $server} = ".$level{"$u *** $server"}."\n" if ($debug > 1);
+                                       # If the new server is the current one, 
+                                       # it would have expanded things for us
+                                       # if it could have.  Mx records must be
+                                       # followed to compare server names.
+                                       # We are also done if the recursion
+                                       # count has been exceeded.
+                                       if (&trhost($newmxhost) eq &trhost($server) || ($levels && $level{"$u *** $server"} >= $levels)) {
+                                               if ($valid) {
+                                                       push(@isValid, &validAddr($newaddr));
+                                                       push(@toFinal,$newaddr,$newmxhost,$newname);
+                                               } else {
+                                                       &verbose(&final($newaddr,$newmxhost,$newname));
+                                               }
+                                       } else {
+                                               # more work to do...
+                                               if ($valid) {
+                                                       push(@isValid, &validAddr($newaddr));
+                                                       push(@toExpn,$newmxhost,$newaddr,$newname,$level{"$u *** $server"});
+                                               } else {
+                                                       &verbose(&expn($newmxhost,$newaddr,$newname,$level{"$u *** $server"}));
+                                               }
+                                       }
+                               }
+                               last if ($done eq " ");
+                               next;
+                       }
+                       # 550 is a known code...  Should the be
+                       # included in -a output?  Might be a bug
+                       # here.  Does it matter?  Can assume that
+                       # there won't be UNKNOWN USER responces 
+                       # mixed with valid users?
+                       if ($s =~ /^(550)([- ])/) {
+                               if ($valid) {
+                                       print STDERR "\@$server:$u ($oldname) USER UNKNOWN\n";
+                               } else {
+                                       &verbose(&final($u,$server,$oldname,"USER UNKNOWN"));
+                               }
+                               last if ($2 eq " ");
+                               next;
+                       } 
+                       &giveup('',"$server: did not grok '$s'",$u);
+                       last USER;
+               }
+               if (! $said_something) {
+                       &giveup('',"$server: lost connection",$u);
+                       last USER;
+               }
+               if ($valid) {
+                       #
+                       # now we decide if we are going to take these
+                       # expansions or roll them back.
+                       #
+                       $avgValid = &average(@isValid);
+                       print "avgValid = $avgValid\n" if $debug;
+                       if ($avgValid >= $validRequirement) {
+                               print &compact($u,$server)." ->\n" if $verbose;
+                               while (@toExpn) {
+                                       &verbose(&expn(splice(@toExpn,0,4)));
+                               }
+                               while (@toFinal) {
+                                       &verbose(&final(splice(@toFinal,0,3)));
+                               }
+                       } else {
+                               print "Tossing some valid to avoid invalid ".&compact($u,$server)."\n" if ($avgValid > 0.0 && ($vw || $debug));
+                               print &compact($u,$server)." ->\n" if $verbose;
+                               &verbose(&final($u,$server,$newname));
+                       }
+               }
+       }
+
+       $0 = "$av0 - sending 'quit' to $server";
+       &ps("quit");
+       while(<S>) {
+               print if $watch;
+               last if /^\d+ /;
+       }
+       close(S);
+}
+
+$0 = "$av0 - printing final results";
+print "----------\n" if $vw;
+select(STDOUT);
+for $f (sort @final) {
+       print "$f\n";
+}
+unlink("/tmp/expn$$");
+exit(0);
+
+
+# abandon all attempts deliver to $server
+# register the current addresses as the final ones
+sub giveup
+{
+       local($redirect_okay,$reason,$user) = @_;
+       local($us,@so,$nh,@remaining_users);
+
+       $0 = "$av0 - giving up on $server: $reason";
+       #
+       # add back a user if we gave up in the middle
+       #
+       push(@users,$user) if $user;
+       #
+       # don't bother with this system anymore
+       #
+       unless ($giveup{$server}) {
+               $giveup{$server} = $reason;
+               print STDERR "$reason\n";
+       }
+       print "Giveup!!! redirect okay = $redirect_okay; $reason\n" if $debug;
+       #
+       # Wait!
+       # Before giving up, see if there is a chance that
+       # there is another host to redirect to!
+       # (Kids, don't do this at home!  Hacking is a dangerous
+       # crime and you could end up behind bars.)
+       #
+       for $u (@users) {
+               if ($redirect_okay =~ /\bmx\b/) {
+                       next if &try_fallback('mx',$u,*server,
+                               *mx_secondary,
+                               *already_mx_fellback);
+               }
+               if ($redirect_okay =~ /\bdomainify\b/) {
+                       next if &try_fallback('domainify',$u,*server,
+                               *domainify_fallback,
+                               *already_domainify_fellback);
+               }
+               push(@remaining_users,$u);
+       }
+       @users = @remaining_users;
+       for $u (@users) {
+               print &compact($u,$server)." ->\n" if ($verbose && $valid && $u);
+               &verbose(&final($u,$server,$names{"$u *** $server"},$reason));
+       }
+}
+#
+# This routine is used only within &giveup.  It checks to
+# see if we really have to giveup or if there is a second
+# chance because we did something before that can be 
+# backtracked.
+#
+# %fallback{"$user *** $host"} tracks what is able to fallback
+# %fellback{"$user *** $host"} tracks what has fallen back
+#
+# If there is a valid backtrack, then queue up the new possibility
+#
+sub try_fallback
+{
+       local($method,$user,*host,*fall_table,*fellback) = @_;
+       local($us,$fallhost,$oldhost,$ft,$i);
+
+       if ($debug > 8) {
+               print "Fallback table $method:\n";
+               for $i (sort keys %fall_table) {
+                       print "\t'$i'\t\t'$fall_table{$i}'\n";
+               }
+               print "Fellback table $method:\n";
+               for $i (sort keys %fellback) {
+                       print "\t'$i'\t\t'$fellback{$i}'\n";
+               }
+               print "U: $user H: $host\n";
+       }
+       
+       $us = "$user *** $host";
+       if (defined $fellback{$us}) {
+               #
+               # Undo a previous fallback so that we can try again
+               # Nest fallbacks are avoided because they could
+               # lead to infinite loops
+               #
+               $fallhost = $fellback{$us};
+               print "Already $method fell back from $us -> \n" if $debug;
+               $us = "$user *** $fallhost";
+               $oldhost = $fallhost;
+       } elsif (($method eq 'mx') && (defined $mxbacktrace{$us}) && (defined $mx_secondary{$mxbacktrace{$us}})) {
+               print "Fallback an MX expansion $us -> \n" if $debug;
+               $oldhost = $mxbacktrace{$us};
+       } else {
+               print "Oldhost(host, $us) = " if $debug;
+               $oldhost = $host;
+       }
+       print "$oldhost\n" if $debug;
+       if (((defined $fall_table{$us}) && ($ft = $us)) || ((defined $fall_table{$oldhost}) && ($ft = $oldhost))) {
+               print "$method Fallback = ".$fall_table{$ft}."\n" if $debug;
+               local(@so,$newhost);
+               @so = split(' ',$fall_table{$ft});
+               $newhost = shift(@so);
+               print "Falling back ($method) $us -> $newhost (from $oldhost)\n" if $debug;
+               if ($method eq 'mx') {
+                       if (! defined ($mxbacktrace{"$user *** $newhost"})) {
+                               if (defined $mxbacktrace{"$user *** $oldhost"}) {
+                                       print "resetting oldhost $oldhost to the original: " if $debug;
+                                       $oldhost = $mxbacktrace{"$user *** $oldhost"};
+                                       print "$oldhost\n" if $debug;
+                               }
+                               $mxbacktrace{"$user *** $newhost"} = $oldhost;
+                               print "mxbacktrace $user *** $newhost -> $oldhost\n" if $debug;
+                       }
+                       $mx{&trhost($oldhost)} = $newhost;
+               } else {
+                       $temporary_redirect{$us} = $newhost;
+               }
+               if (@so) {
+                       print "Can still $method  $us: @so\n" if $debug;
+                       $fall_table{$ft} = join(' ',@so);
+               } else {
+                       print "No more fallbacks for $us\n" if $debug;
+                       delete $fall_table{$ft};
+               }
+               if (defined $create_host_backtrack{$us}) {
+                       $create_host_backtrack{"$user *** $newhost"} 
+                               = $create_host_backtrack{$us};
+               }
+               $fellback{"$user *** $newhost"} = $oldhost;
+               &expn($newhost,$user,$names{$us},$level{$us});
+               return 1;
+       }
+       delete $temporary_redirect{$us};
+       $host = $oldhost;
+       return 0;
+}
+# return 1 if you could send mail to the address as is.
+sub validAddr
+{
+       local($addr) = @_;
+       $res = &do_validAddr($addr);
+       print "validAddr($addr) = $res\n" if $debug;
+       $res;
+}
+sub do_validAddr
+{
+       local($addr) = @_;
+       local($urx) = "[-A-Za-z_.0-9+]+";
+
+       # \u
+       return 0 if ($addr =~ /^\\/);
+       # ?@h
+       return 1 if ($addr =~ /.\@$urx$/);
+       # @h:?
+       return 1 if ($addr =~ /^\@$urx\:./);
+       # h!u
+       return 1 if ($addr =~ /^$urx!./);
+       # u
+       return 1 if ($addr =~ /^$urx$/);
+       # ?
+       print "validAddr($addr) = ???\n" if $debug;
+       return 0;
+}
+# returns ($new_smtp_server,$new_address,$new_name)
+# given a responce from a SMTP server ($newaddr), the 
+# current host ($server), the old "name" and a flag that
+# indicates if it is being called during the initial 
+# command line parsing ($parsing_args)
+sub parse
+{
+       local($newaddr,$context_host,$old_name,$parsing_args) = @_;
+       local(@names) = $old_name;
+       local($urx) = "[-A-Za-z_.0-9+]+";
+
+       #
+       # first, separate out the address part.
+       #
+
+       #
+       # [NAME] <ADDR [(NAME)]>
+       # [NAME] <[(NAME)] ADDR
+       # ADDR [(NAME)]
+       # (NAME) ADDR
+       # [(NAME)] <ADDR>
+       #
+       if ($newaddr =~ /^\<(.*)\>$/) {
+               print "<A:$1>\n" if $debug;
+               $newaddr = &trim($1);
+               print "na = $newaddr\n" if $debug;
+       }
+       if ($newaddr =~ /^([^\<\>]*)\<([^\<\>]*)\>([^\<\>]*)$/) {
+               # address has a < > pair in it.
+               print "N:$1 <A:$2> N:$3\n" if $debug;
+               $newaddr = &trim($2);
+               unshift(@names, &trim($3,$1));
+               print "na = $newaddr\n" if $debug;
+       }
+       if ($newaddr =~ /^([^\(\)]*)\(([^\(\)]*)\)([^\(\)]*)$/) {
+               # address has a ( ) pair in it.
+               print "A:$1 (N:$2) A:$3\n" if $debug;
+               unshift(@names,&trim($2));
+               local($f,$l) = (&trim($1),&trim($3));
+               if (($f && $l) || !($f || $l)) {
+                       # address looks like:
+                       # foo (bar) baz  or (bar)
+                       # not allowed!
+                       print STDERR "Could not parse $newaddr\n" if $vw;
+                       return(undef,$newaddr,&firstname(@names));
+               }
+               $newaddr = $f if $f;
+               $newaddr = $l if $l;
+               print "newaddr now = $newaddr\n" if $debug;
+       }
+       #
+       # @foo:bar
+       # j%k@l
+       # a@b
+       # b!a
+       # a
+       #
+       if ($newaddr =~ /^\@($urx)\:(.+)$/) {
+               print "(\@:)" if $debug;
+               # this is a bit of a cheat, but it seems necessary
+               return (&domainify($1,$context_host,$2),$2,&firstname(@names));
+       }
+       if ($newaddr =~ /^(.+)\@($urx)$/) {
+               print "(\@)" if $debug;
+               return (&domainify($2,$context_host,$newaddr),$newaddr,&firstname(@names));
+       }
+       if ($parsing_args) {
+               if ($newaddr =~ /^($urx)\!(.+)$/) {
+                       return (&domainify($1,$context_host,$newaddr),$newaddr,&firstname(@names));
+               }
+               if ($newaddr =~ /^($urx)$/) {
+                       return ($context_host,$newaddr,&firstname(@names));
+               }
+               print STDERR "Could not parse $newaddr\n";
+       }
+       print "(?)" if $debug;
+       return(undef,$newaddr,&firstname(@names));
+}
+# return $u (@$server) unless $u includes reference to $server
+sub compact
+{
+       local($u, $server) = @_;
+       local($se) = $server;
+       local($sp);
+       $se =~ s/(\W)/\\$1/g;
+       $sp = " (\@$server)";
+       if ($u !~ /$se/i) {
+               return "$u$sp";
+       }
+       return $u;
+}
+# remove empty (spaces don't count) members from an array
+sub trim
+{
+       local(@v) = @_;
+       local($v,@r);
+       for $v (@v) {
+               $v =~ s/^\s+//;
+               $v =~ s/\s+$//;
+               push(@r,$v) if ($v =~ /\S/);
+       }
+       return(@r);
+}
+# using the host part of an address, and the server name, add the
+# servers' domain to the address if it doesn't already have a 
+# domain.  Since this sometimes failes, save a back reference so
+# it can be unrolled.
+sub domainify
+{
+       local($host,$domain_host,$u) = @_;
+       local($domain,$newhost);
+
+       # cut of trailing dots 
+       $host =~ s/\.$//;
+       $domain_host =~ s/\.$//;
+
+       if ($domain_host !~ /\./) {
+               #
+               # domain host isn't, keep $host whatever it is
+               #
+               print "domainify($host,$domain_host) = $host\n" if $debug;
+               return $host;
+       }
+
+       # 
+       # There are several weird situtations that need to be 
+       # accounted for.  They have to do with domain relay hosts.
+       #
+       # Examples: 
+       #       host            server          "right answer"
+       #       
+       #       shiva.cs        cs.berkeley.edu shiva.cs.berkeley.edu
+       #       shiva           cs.berkeley.edu shiva.cs.berekley.edu
+       #       cumulus         reed.edu        @reed.edu:cumulus.uucp
+       #       tiberius        tc.cornell.edu  tiberius.tc.cornell.edu
+       #
+       # The first try must always be to cut the domain part out of 
+       # the server and tack it onto the host.
+       #
+       # A reasonable second try is to tack the whole server part onto
+       # the host and for each possible repeated element, eliminate 
+       # just that part.
+       #
+       # These extra "guesses" get put into the %domainify_fallback
+       # array.  They will be used to give addresses a second chance
+       # in the &giveup routine
+       #
+
+       local(%fallback);
+
+       local($long); 
+       $long = "$host $domain_host";
+       $long =~ tr/A-Z/a-z/;
+       print "long = $long\n" if $debug;
+       if ($long =~ s/^([^ ]+\.)([^ ]+) \2(\.[^ ]+\.[^ ]+)/$1$2$3/) {
+               # matches shiva.cs cs.berkeley.edu and returns shiva.cs.berkeley.edu
+               print "condensed fallback $host $domain_host -> $long\n" if $debug;
+               $fallback{$long} = 9;
+       }
+
+       local($fh);
+       $fh = $domain_host;
+       while ($fh =~ /\./) {
+               print "FALLBACK $host.$fh = 1\n" if $debug > 7;
+               $fallback{"$host.$fh"} = 1;
+               $fh =~ s/^[^\.]+\.//;
+       }
+
+       $fallback{"$host.$domain_host"} = 2;
+
+       ($domain = $domain_host) =~ s/^[^\.]+//;
+       $fallback{"$host$domain"} = 6
+               if ($domain =~ /\./);
+
+       if ($host =~ /\./) {
+               #
+               # Host is already okay, but let's look for multiple
+               # interpretations
+               #
+               print "domainify($host,$domain_host) = $host\n" if $debug;
+               delete $fallback{$host};
+               $domainify_fallback{"$u *** $host"} = join(' ',sort {$fallback{$b} <=> $fallback{$a};} keys %fallback) if %fallback;
+               return $host;
+       }
+
+       $domain = ".$domain_host"
+               if ($domain !~ /\..*\./);
+       $newhost = "$host$domain";
+
+       $create_host_backtrack{"$u *** $newhost"} = $domain_host;
+       print "domainify($host,$domain_host) = $newhost\n" if $debug;
+       delete $fallback{$newhost};
+       $domainify_fallback{"$u *** $newhost"} = join(' ',sort {$fallback{$b} <=> $fallback{$a};} keys %fallback) if %fallback;
+       if ($debug) {
+               print "fallback = ";
+               print $domainify_fallback{"$u *** $newhost"} 
+                       if defined($domainify_fallback{"$u *** $newhost"});
+               print "\n";
+       }
+       return $newhost;
+}
+# return the first non-empty element of an array
+sub firstname
+{
+       local(@names) = @_;
+       local($n);
+       while(@names) {
+               $n = shift(@names);
+               return $n if $n =~ /\S/;
+       }
+       return undef;
+}
+# queue up more addresses to expand
+sub expn
+{
+       local($host,$addr,$name,$level) = @_;
+       if ($host) {
+               $host = &trhost($host);
+
+               if (($debug > 3) || (defined $giveup{$host})) {
+                       unshift(@hosts,$host) unless $users{$host};
+               } else {
+                       push(@hosts,$host) unless $users{$host};
+               }
+               $users{$host} .= " $addr";
+               $names{"$addr *** $host"} = $name;
+               $level{"$addr *** $host"} = $level + 1;
+               print "expn($host,$addr,$name)\n" if $debug;
+               return "\t$addr\n";
+       } else {
+               return &final($addr,'NONE',$name);
+       }
+}
+# compute the numerical average value of an array
+sub average
+{
+       local(@e) = @_;
+       return 0 unless @e;
+       local($e,$sum);
+       for $e (@e) {
+               $sum += $e;
+       }
+       $sum / @e;
+}
+# print to the server (also to stdout, if -w)
+sub ps
+{
+       local($p) = @_;
+       print ">>> $p\n" if $watch;
+       print S "$p\n";
+}
+# return case-adjusted name for a host (for comparison purposes)
+sub trhost 
+{
+       # treat foo.bar as an alias for Foo.BAR
+       local($host) = @_;
+       local($trhost) = $host;
+       $trhost =~ tr/A-Z/a-z/;
+       if ($trhost{$trhost}) {
+               $host = $trhost{$trhost};
+       } else {
+               $trhost{$trhost} = $host;
+       }
+       $trhost{$trhost};
+}
+# re-queue users if an mx record dictates a redirect
+# don't allow a user to be redirected more than once
+sub mxredirect
+{
+       local($server,*users) = @_;
+       local($u,$nserver,@still_there);
+
+       $nserver = &mx($server);
+
+       if (&trhost($nserver) ne &trhost($server)) {
+               $0 = "$av0 - mx redirect $server -> $nserver\n";
+               for $u (@users) {
+                       if (defined $mxbacktrace{"$u *** $nserver"}) {
+                               push(@still_there,$u);
+                       } else {
+                               $mxbacktrace{"$u *** $nserver"} = $server;
+                               print "mxbacktrace{$u *** $nserver} = $server\n"
+                                       if ($debug > 1);
+                               &expn($nserver,$u,$names{"$u *** $server"});
+                       }
+               }
+               @users = @still_there;
+               if (! @users) {
+                       return $nserver;
+               } else {
+                       return undef;
+               }
+       }
+       return undef;
+}
+# follow mx records, return a hostname
+# also follow temporary redirections comming from &domainify and
+# &mxlookup
+sub mx
+{
+       local($h,$u) = @_;
+
+       for (;;) {
+               if (defined $mx{&trhost($h)} && $h ne $mx{&trhost($h)}) {
+                       $0 = "$av0 - mx expand $h";
+                       $h = $mx{&trhost($h)};
+                       return $h;
+               }
+               if ($u) {
+                       if (defined $temporary_redirect{"$u *** $h"}) {
+                               $0 = "$av0 - internal redirect $h";
+                               print "Temporary redirect taken $u *** $h -> " if $debug;
+                               $h = $temporary_redirect{"$u *** $h"};
+                               print "$h\n" if $debug;
+                               next;
+                       }
+                       $htr = &trhost($h);
+                       if (defined $temporary_redirect{"$u *** $htr"}) {
+                               $0 = "$av0 - internal redirect $h";
+                               print "temporary redirect taken $u *** $h -> " if $debug;
+                               $h = $temporary_redirect{"$u *** $htr"};
+                               print "$h\n" if $debug;
+                               next;
+                       }
+               }
+               return $h;
+       }
+}
+# look up mx records with the name server.
+# re-queue expansion requests if possible
+# optionally give up on this host.
+sub mxlookup 
+{
+       local($lastchance,$server,$giveup,*users) = @_;
+       local(*T);
+       local(*NSLOOKUP);
+       local($nh, $pref,$cpref);
+       local($o0) = $0;
+       local($nserver);
+       local($name,$aliases,$type,$len,$thataddr);
+       local(%fallback);
+
+       return 1 if &mxredirect($server,*users);
+
+       if ((defined $mx{$server}) || (! $have_nslookup)) {
+               return 0 unless $lastchance;
+               &giveup('mx domainify',$giveup);
+               return 0;
+       }
+
+       $0 = "$av0 - nslookup of $server";
+       open(T,">/tmp/expn$$") || die "open > /tmp/expn$$: $!\n";
+       print T "set querytype=MX\n";
+       print T "$server\n";
+       close(T);
+       $cpref = 1.0E12;
+       undef $nserver;
+       open(NSLOOKUP,"nslookup < /tmp/expn$$ 2>&1 |") || die "open nslookup: $!";
+       while(<NSLOOKUP>) {
+               print if ($debug > 2);
+               if (/mail exchanger = ([-A-Za-z_.0-9+]+)/) {
+                       $nh = $1;
+                       if (/preference = (\d+)/) {
+                               $pref = $1;
+                               if ($pref < $cpref) {
+                                       $nserver = $nh;
+                                       $cpref = $pref;
+                               } elsif ($pref) {
+                                       $fallback{$pref} .= " $nh";
+                               }
+                       }
+               }
+               if (/Non-existent domain/) {
+                       #
+                       # These addresss are hosed.  Kaput!  Dead! 
+                       # However, if we created the address in the
+                       # first place then there is a chance of 
+                       # salvation.
+                       #
+                       1 while(<NSLOOKUP>);    
+                       close(NSLOOKUP);
+                       return 0 unless $lastchance;
+                       &giveup('domainify',"$server: Non-existent domain",undef,1);
+                       return 0;       
+               }
+                               
+       }
+       close(NSLOOKUP);
+       unlink("/tmp/expn$$");
+       unless ($nserver) {
+               $0 = "$o0 - finished mxlookup";
+               return 0 unless $lastchance;
+               &giveup('mx domainify',"$server: Could not resolve address");
+               return 0;
+       }
+
+       # provide fallbacks in case $nserver doesn't work out
+       if (defined $fallback{$cpref}) {
+#              for $u (@users) {
+#                      print "mx_secondary{$u *** $nserver} = ".$fallback{$cpref}."\n"
+#                              if $debug;
+#                      $mx_secondary{"$u *** $nserver"} = $fallback{$cpref};
+#              }
+               $mx_secondary{$server} = $fallback{$cpref};
+       }
+
+       $0 = "$av0 - gethostbyname($nserver)";
+       ($name,$aliases,$type,$len,$thataddr) = gethostbyname($nserver);
+
+       unless ($thataddr) {
+               $0 = $o0;
+               return 0 unless $lastchance;
+               &giveup('mx domainify',"$nserver: could not resolve address");
+               return 0;
+       }
+       print "MX($server) = $nserver\n" if $debug;
+       print "$server -> $nserver\n" if $vw && !$debug;
+       $mx{&trhost($server)} = $nserver;
+       # redeploy the users
+       unless (&mxredirect($server,*users)) {
+               return 0 unless $lastchance;
+               &giveup('mx domainify',"$nserver: only one level of mx redirect allowed");
+               return 0;
+       }
+       $0 = "$o0 - finished mxlookup";
+       return 1;
+}
+# if mx expansion did not help to resolve an address
+# (ie: foo@bar became @baz:foo@bar, then undo the 
+# expansion).
+# this is only used by &final
+sub mxunroll
+{
+       local(*host,*addr) = @_;
+       local($r) = 0;
+       print "looking for mxbacktrace{$addr *** $host}\n"
+               if ($debug > 1);
+       while (defined $mxbacktrace{"$addr *** $host"}) {
+               print "Unrolling MX expnasion: \@$host:$addr -> " 
+                       if ($debug || $verbose);
+               $host = $mxbacktrace{"$addr *** $host"};
+               print "\@$host:$addr\n" 
+                       if ($debug || $verbose);
+               $r = 1;
+       }
+       return 1 if $r;
+       $addr = "\@$host:$addr"
+               if ($host =~ /\./);
+       return 0;
+}
+# register a completed expnasion.  Make the final address as 
+# simple as possible.
+sub final
+{
+       local($addr,$host,$name,$error) = @_;
+       local($he);
+       local($hb,$hr);
+       local($au,$ah);
+
+       if ($error =~ /Non-existent domain/) {
+               # 
+               # If we created the domain, then let's undo the
+               # damage...
+               #
+               if (defined $create_host_backtrack{"$addr *** $host"}) {
+                       while (defined $create_host_backtrack{"$addr *** $host"}) {
+                               print "Un&domainifying($host) = " if $debug;
+                               $host = $create_host_backtrack{"$addr *** $host"};
+                               print "$host\n" if $debug;
+                       }
+                       $error = "$host: could not locate";
+               } else {
+                       # 
+                       # If we only want valid addresses, toss out
+                       # bad host names.
+                       #
+                       if ($valid) {
+                               print STDERR "\@$host:$addr ($name) Non-existent domain\n";
+                               return "";
+                       }
+               }
+       }
+
+       MXUNWIND: {
+               $0 = "$av0 - final parsing of \@$host:$addr";
+               ($he = $host) =~ s/(\W)/\\$1/g;
+               if ($addr !~ /@/) {
+                       # addr does not contain any host
+                       $addr = "$addr@$host";
+               } elsif ($addr !~ /$he/i) {
+                       # if host part really something else, use the something
+                       # else.
+                       if ($addr =~ m/(.*)\@([^\@]+)$/) {
+                               ($au,$ah) = ($1,$2);
+                               print "au = $au ah = $ah\n" if $debug;
+                               if (defined $temporary_redirect{"$addr *** $ah"}) {
+                                       $addr = "$au\@".$temporary_redirect{"$addr *** $ah"};
+                                       print "Rewrite! to $addr\n" if $debug;
+                                       next MXUNWIND;
+                               }
+                       }
+                       # addr does not contain full host
+                       if ($valid) {
+                               if ($host =~ /^([^\.]+)(\..+)$/) {
+                                       # host part has a . in it - foo.bar
+                                       ($hb, $hr) = ($1, $2);
+                                       if ($addr =~ /\@([^\.\@]+)$/ && ($1 eq $hb)) {
+                                               # addr part has not . 
+                                               # and matches beginning of
+                                               # host part -- tack on a 
+                                               # domain name.
+                                               $addr .= $hr;
+                                       } else {
+                                               &mxunroll(*host,*addr) 
+                                                       && redo MXUNWIND;
+                                       }
+                               } else {
+                                       &mxunroll(*host,*addr) 
+                                               && redo MXUNWIND;
+                               }
+                       } else {
+                               $addr = "${addr}[\@$host]"
+                                       if ($host =~ /\./);
+                       }
+               }
+       }
+       $name = "$name " if $name;
+       $error = " $error" if $error;
+       if ($valid) {
+               push(@final,"$name<$addr>");
+       } else {
+               push(@final,"$name<$addr>$error");
+       }
+       "\t$name<$addr>$error\n";
+}
+# read the rest of the current smtp daemon's responce (and toss it away)
+sub toss
+{
+       local($done) = @_;
+       print $s if $watch;
+       while(($done eq "-") && ($s = <S>) && ($s =~ /^\d+([- ])/)) {
+               print $s if $watch;
+               $done = $1;
+       }
+}
+# print args if verbose.  Return them in any case
+sub verbose
+{
+       local(@tp) = @_;
+       print "@tp" if $verbose;
+}
+# to pass perl -w:
+@tp;
+$flag_a;
+$flag_d;
+$flag_1;
+%already_domainify_fellback;
+%already_mx_fellback;
+################### BEGIN PERL/TROFF TRANSITION 
+.00;
+
+'di            \\ " finish diversion--previous line must be blank
+.nr nl 0-1     \\ " fake up transition to first page again
+.nr % 0                \\ " start at page 1
+'; __END__  
+.\" ############### END PERL/TROFF TRANSITION
+.TH EXPN 1 "March 11, 1993"
+.AT 3
+.SH NAME
+expn \- recursively expand mail aliases
+.SH SYNOPSIS
+.B expn
+.RI [ -a ]
+.RI [ -v ]
+.RI [ -w ]
+.RI [ -d ]
+.IR user [@ hostname ]
+.RI [ user [@ hostname ]]...
+.SH DESCRIPTION
+.B expn
+will use the SMTP
+.B expn
+and 
+.B vrfy
+commands to expand mail aliases.  
+It will first look up the addresses you provide on the command line.
+If those expand into addresses on other systems, it will 
+connect to the other systems and expand again.  It will keep 
+doing this until no further expansion is possible.
+.SH OPTIONS
+The default output of 
+.B expn
+can contain many lines which are not valid
+email addresses.  With the 
+.I -aa
+flag, only expansions that result in legal addresses
+are used.  Since many mailing lists have an illegal
+address or two, the single
+.IR -a ,
+address, flag specifies that a few illegal addresses can
+be mixed into the results.   More 
+.I -a
+flags vary the ratio.  Read the source to track down
+the formula.  With the
+.I -a
+option, you should be able to construct a new mailing
+list out of an existing one.
+.LP
+If you wish to limit the number of levels deep that 
+.B expn
+will recurse as it traces addresses, use the
+.I -1
+option.  For each 
+.I -1
+another level will be traversed.  So, 
+.I -111
+will traverse no more than three levels deep.
+.LP
+The normal mode of operation for
+.B expn
+is to do all of its work silently.
+The following options make it more verbose.
+It is not necessary to make it verbose to see what it is
+doing because as it works, it changes its 
+.BR argv [0]
+variable to reflect its current activity.
+To see how it is expanding things, the 
+.IR -v ,
+verbose, flag will cause 
+.B expn 
+to show each address before
+and after translation as it works.
+The 
+.IR -w ,
+watch, flag will cause
+.B expn
+to show you its conversations with the mail daemons.
+Finally, the 
+.IR -d ,
+debug, flag will expose many of the inner workings so that
+it is possible to eliminate bugs.
+.SH ENVIRONMENT
+No enviroment variables are used.
+.SH FILES
+.PD 0
+.B /tmp/expn$$
+.B temporary file used as input to 
+.BR nslookup .
+.SH SEE ALSO
+.BR aliases (5), 
+.BR sendmail (8),
+.BR nslookup (8),
+RFC 823, and RFC 1123.
+.SH BUGS
+Not all mail daemons will implement 
+.B expn
+or
+.BR vrfy .
+It is not possible to verify addresses that are served
+by such daemons.
+.LP
+When attempting to connect to a system to verify an address,
+.B expn
+only tries one IP address.  Most mail daemons
+will try harder.
+.LP
+It is assumed that you are running domain names and that 
+the 
+.BR nslookup (8) 
+program is available.  If not, 
+.B expn
+will not be able to verify many addresses.  It will also pause
+for a long time unless you change the code where it says
+.I $have_nslookup = 1
+to read
+.I $have_nslookup = 
+.IR 0 .
+.LP
+Lastly, 
+.B expn
+does not handle every valid address.  If you have an example,
+please submit a bug report.
+.SH CREDITS
+In 1986 or so, Jon Broome wrote a program of the same name
+that did about the same thing.  It has since suffered bit rot
+and Jon Broome has dropped off the face of the earth!
+(Jon, if you are out there, drop me a line)
+.SH AVAILABILITY
+The latest version of 
+.B expn
+is available through anonymous ftp to
+.IR idiom.berkeley.ca.us .
+.SH AUTHOR
+.I David Muir Sharnoff\ \ \ \ <muir@idiom.berkeley.ca.us>
diff --git a/usr.sbin/sendmail/contrib/mmuegel b/usr.sbin/sendmail/contrib/mmuegel
new file mode 100644 (file)
index 0000000..48ea104
--- /dev/null
@@ -0,0 +1,2073 @@
+Return-Path: mmuegel@cssmp.corp.mot.com
+Received: from hofmann.CS.Berkeley.EDU by auspex.Berkeley.EDU (ALPHA-6.30/6.9) id AA02096; Sun, 11 Apr 1993 19:50:02 -0700
+Received: from motgate.mot.com by hofmann.CS.Berkeley.EDU (ALPHA-6.35/6.16) id AA14977; Sun, 11 Apr 1993 19:49:57 -0700
+Received: from pobox.mot.com ([129.188.137.100]) by motgate.mot.com with SMTP (5.65c/IDA-1.4.4/MOT-2.13 for <eric@cs.berkeley.edu>)
+          id AA05603; Sun, 11 Apr 1993 21:49:54 -0500
+Received: from cssmp.corp.mot.com by pobox.mot.com with SMTP (5.65c/IDA-1.4.4/MOT-2.12 for <eric@cs.berkeley.edu>)
+          id AA08281; Sun, 11 Apr 1993 21:49:51 -0500
+Received: by cssmp.corp.mot.com (5.65c/IDA-1.4.4/MOT-2.12 for eric@cs.berkeley.edu)
+          id AA02812; Sun, 11 Apr 1993 21:49:48 -0500
+From: "Michael S. Muegel" <mmuegel@cssmp.corp.mot.com>
+Message-Id: <199304120249.AA02812@cssmp.corp.mot.com>
+Subject: Sendmail tools README
+To: eric@cs.berkeley.edu (Eric Allman)
+Date: Sun, 11 Apr 1993 21:49:48 -0500 (CDT)
+Cc: costales@icsi.berkeley.edu (Bryan Costales)
+X-Mailer: ELM [version 2.4 PL17]
+Mime-Version: 1.0
+Content-Type: text/plain; charset=US-ASCII
+Content-Transfer-Encoding: 7bit
+Content-Length: 67910     
+
+
+As promised, here is a new distribution with a decent README.
+
+Cheers,
+-Mike
+
+---- Cut Here and feed the following to sh ----
+#!/bin/sh
+# This is a shell archive (produced by shar 3.49)
+# To extract the files from this archive, save it to a file, remove
+# everything above the "!/bin/sh" line above, and type "sh file_name".
+#
+# made 04/12/1993 02:34 UTC by mmuegel@mot.com (Michael S. Muegel)
+# Source directory /usr/var/rtmp/shar2336
+#
+# existing files will NOT be overwritten unless -c is specified
+#
+# This shar contains:
+# length  mode       name
+# ------ ---------- ------------------------------------------
+#   4367 -r--r--r-- README
+#  11619 -r--r--r-- libs/date.pl
+#   3243 -r--r--r-- libs/elapsed.pl
+#   4379 -r--r--r-- libs/mail.pl
+#   6953 -r--r--r-- libs/mqueue.pl
+#   7030 -r--r--r-- libs/newgetopts.pl
+#   4718 -r--r--r-- libs/strings1.pl
+#   1637 -r--r--r-- libs/timespec.pl
+#   5229 -r--r--r-- man/cqueue.1
+#   2097 -r--r--r-- man/postclip.1
+#   6702 -r-xr-xr-x src/cqueue
+#   1900 -r-xr-xr-x src/postclip
+#
+# ============= README ==============
+if test -f 'README' -a X"$1" != X"-c"; then
+       echo 'x - skipping README (File already exists)'
+else
+echo 'x - extracting README (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'README' &&
+-------------------------------------------------------------------------------
+Document Revision Control Information:
+X   $Author: glass $
+X   $Source: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v $
+X   $Revision: 1.2 $ of $Date: 1993/06/28 22:33:06 $
+-------------------------------------------------------------------------------
+X
+1. Introduction
+---------------
+X
+These tools may be of use to those sites using sendmail. Both are written in
+Perl. Our site, Mot.COM, receives a ton of mail being a top-level domain
+gateway. We have over 24 domains under us. Needless to say, we must have
+a robust mail system or my head, and others, would be on the chopping block.
+X
+2. Description
+--------------
+X
+The first tool, cqueue, checks the sendmail queue for problems. We use
+it to flag problems with subdomain mail servers (and even our own servers
+once in a while ;-). We run it via a cron job every hour during the day.
+You may find this too frequent, however. 
+X
+The other program, postclip, is used to "filter" non-deliverable NDNs that
+get sent to our Postmaster account now and then. This ensures privacy of
+e-mail and helps avoid disk problems from huge NDNs. It is different than
+a brute force "just keep the header" approach because it tries hard to keep
+other parts of the message that look like non-delivery information.
+X
+Both have been used for some time at our site with no problems. Everything 
+you need should be in this distribution: source, manual pages, and support 
+libs. See the manual pages for a complete description of each tool.
+X
+3. Installation
+---------------
+X
+No fancy Makefile simply because these tools are all under a large
+hierarchy at my site. Installation should be a snap, however. Install
+the nroff(1) man(5) manual pages from the man subdirectory to the
+appropriate directory on your system. This might be something like
+/usr/local/man/man1.
+X
+Next, install all of the Perl libraries located in the lib subdirectory
+to your Perl library area. /usr/local/lib/perl is a good bet. The person
+who installed Perl at your site will be able to tell you for sure. 
+X
+Finally, you need to install the programs. Note that cqueue wants to
+run setuid root by default. This is because the sendmail queue is normally
+only readable by root or some special group. In order to let any user
+run this suidperl is used. suidperl allows a Perl program to run with the
+privileges of another user. 
+X
+You will have to edit both the cqueue and postclip programs to change
+the #! line at the top of each. Just change the pathname to whatever is
+appropriate on your system. Note that Larry Wall's fixin program from
+the Camel book can also be used to do this. It is very handy. It changes
+#! lines by looking at your PATH.
+X
+If you do not have suidperl on your system change the #! line in cqueue
+to reference perl instead of suidperl.
+X
+You may also wish to change some constants in cqueue. $DEF_QUEUE should be
+changed to your queue directory if it is not /usr/spool/mqueue. $DEF_TIME
+could be changed easy enough also. It is the time spec for the time duration
+after which a mail message will be reported on if the -a option has not been
+specified. See the manual page for more information and the format of this
+constant (same as the -t argument). Then again, neither of these has to
+be changed. Command line options are there to override their default
+values.
+X
+After you have edited the programs as necessary, all that remains is to
+install them to some executable directory. Install postclip mode 555
+and cqueue mode 4555 with owner root (if using suidperl) or mode 555
+(if not using suidperl).
+X
+4. Gripes, Comments, Etc
+------------------------
+X
+If you start using either of these let me know. I have other mail tools I
+will likely post in the future if these prove useful. Also, if you think
+something is just plain dumb/wrong/stupid let me know!
+X
+Cheers,
+-Mike
+X
+--
++----------------------------------------------------------------------------+
+| Michael S. Muegel                    | Internet E-Mail:    mmuegel@mot.com |
+| UNIX Applications Startup Group      | Moto Dist E-Mail:   X10090          |
+| Corporate Information Office         | Voice:              (708) 576-0507  |
+| Motorola                             | Fax:                (708) 576-4153  |
++----------------------------------------------------------------------------+
+SHAR_EOF
+chmod 0444 README ||
+echo 'restore of README failed'
+Wc_c="`wc -c < 'README'`"
+test 4367 -eq "$Wc_c" ||
+       echo 'README: original size 4367, current size' "$Wc_c"
+fi
+# ============= libs/date.pl ==============
+if test ! -d 'libs'; then
+    echo 'x - creating directory libs'
+    mkdir 'libs'
+fi
+if test -f 'libs/date.pl' -a X"$1" != X"-c"; then
+       echo 'x - skipping libs/date.pl (File already exists)'
+else
+echo 'x - extracting libs/date.pl (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'libs/date.pl' &&
+;#
+;# Name
+;#     date.pl - Perl emulation of (the output side of) date(1)
+;#
+;# Synopsis
+;#     require "date.pl";
+;#     $Date = &date(time);
+;#     $Date = &date(time, $format);
+;#
+;# Description
+;#     This package implements the output formatting functions of date(1) in
+;#     Perl.  The format options are based on those supported by Ultrix 4.0
+;#     plus a couple of additions from SunOS 4.1.1 and elsewhere:
+;#
+;#             %a              abbreviated weekday name - Sun to Sat
+;#             %A              full weekday name - Sunday to Saturday
+;#             %b              abbreviated month name - Jan to Dec
+;#             %B              full month name - January to December
+;#             %c              date and time in local format [+]
+;#             %C              date and time in long local format [+]
+;#             %d              day of month - 01 to 31
+;#             %D              date as mm/dd/yy
+;#             %e              day of month (space padded) - ` 1' to `31'
+;#             %E              day of month (with suffix: 1st, 2nd, 3rd...)
+;#             %f              month of year (space padded) - ` 1' to `12'
+;#             %h              abbreviated month name - Jan to Dec
+;#             %H              hour - 00 to 23
+;#             %i              hour (space padded) - ` 1' to `12'
+;#             %I              hour - 01 to 12
+;#             %j              day of the year (Julian date) - 001 to 366
+;#             %k              hour (space padded) - ` 0' to `23'
+;#             %l              date in ls(1) format
+;#             %m              month of year - 01 to 12
+;#             %M              minute - 00 to 59
+;#             %n              insert a newline character
+;#             %p              AM or PM
+;#             %r              time in AM/PM notation
+;#             %R              time as HH:MM
+;#             %S              second - 00 to 59
+;#             %t              insert a tab character
+;#             %T              time as HH:MM:SS
+;#             %u              date/time in date(1) required format
+;#             %U              week number, Sunday as first day of week - 00 to 53
+;#             %V              date-time in SysV touch format (mmddHHMMyy)
+;#             %w              day of week - 0 (Sunday) to 6
+;#             %W              week number, Monday as first day of week - 00 to 53
+;#             %x              date in local format [+]
+;#             %X              time in local format [+]
+;#             %y              last 2 digits of year - 00 to 99
+;#             %Y              all 4 digits of year ~ 1700 to 2000 odd ?
+;#             %z              time zone from TZ environment variable w/ a trailing space
+;#             %Z              time zone from TZ environment variable
+;#             %%              insert a `%' character
+;#             %+              insert a `+' character
+;#
+;#     [+]:  These may need adjustment to fit local conventions, see below.
+;#
+;#     For the sake of compatibility, a leading `+' in the format
+;#     specificaiton is removed if present.
+;#
+;# Remarks
+;#     This is version 3.3 of date.pl
+;#
+;#     An extension of `ctime.pl' by Waldemar Kebsch (kebsch.pad@nixpbe.UUCP),
+;#     as modified by Marion Hakanson (hakanson@ogicse.ogi.edu).
+;#
+;#  Unlike date(1), unknown format tags are silently replaced by "".
+;#
+;#  defaultTZ is a blatant hack, but I wanted to be able to get date(1)
+;#     like behaviour by default and there does'nt seem to be an easy (read
+;#     portable) way to get the local TZ name back...
+;#
+;#     For a cheap date, try...
+;#
+;#             #!/usr/local/bin/perl
+;#             require "date.pl";
+;#             exit print (&date(time, shift @ARGV) . "\n") ? 0 : 1;
+;#
+;#     This package is redistributable under the same terms as apply to
+;#     the Perl 4.0 release.  See the COPYING file in your Perl kit for
+;#     more information.
+;#
+;#     Please send any bug reports or comments to tmcgonigal@gvc.com
+;#
+;# Modification History
+;#     Nmemonic        Version Date            Who
+;#
+;#     NONE            1.0             02feb91         Terry McGonigal (tmcgonigal@gvc.com)
+;#             Created from ctime.pl
+;#
+;#     NONE            2.0             07feb91         tmcgonigal
+;#             Added some of Marion Hakanson (hakanson@ogicse.ogi.edu)'s ctime.pl
+;#             TZ handling changes.
+;#
+;#     NONE            2.1             09feb91         tmcgonigal
+;#             Corrected week number calculations.
+;#
+;#     NONE            2.2             21oct91         tmcgonigal
+;#             Added ls(1) date format, `%l'.
+;#
+;#     NONE            2.3             06nov91         tmcgonigal
+;#             Added SysV touch(1) date-time format, `%V' (pretty thin as
+;#             mnemonics go, I know, but `t' and `T' were both gone already!)
+;#
+;#     NONE            2.4             05jan92         tmcgonigal
+;#             Corrected slight (cosmetic) problem with %V replacment string
+;#
+;#     NONE            3.0             09jul92         tmcgonigal
+;#             Fixed a couple of problems with &ls as pointed out by
+;#             Thomas Richter (richter@ki1.chemie.fu-berlin.de), thanks Thomas!
+;#             Also added a couple of SunOS 4.1.1 strftime-ish formats, %i and %k
+;#             for space padded hours (` 1' to `12' and ` 0' to `23' respectivly),
+;#             and %C for locale long date/time format.  Changed &ampmH to take a
+;#             pad char parameter to make to evaled code for %i and %k simpler. 
+;#             Added %E for suffixed day-of-month (ie 1st, 3rd, 4th etc).
+;#
+;#     NONE            3.1             16jul92         tmcgonigal
+;#             Added `%u' format to generate date/time in date(1) required
+;#             format (ie '%y%m%d%H%M.%S').
+;#
+;#     NONE            3.2             23jan93         tmcgonigal
+;#             Added `%f' format to generate space padded month numbers, added
+;#             `%E' to the header comments, it seems to have been left out (and
+;#             I'm sure I wanted to use it at some point in the past...).
+;#
+;#     NONE            3.3             03feb93         tmcgonigal
+;#             Corrected some problems with AM/PM handling pointed out by
+;#             Michael S. Muegel (mmuegel@mot.com).  Thanks Michael, I hope
+;#             this is the behaviour you were looking for, it seems more
+;#             correct to me...
+;#
+;# SccsId = "%W% %E%"
+;#
+package date;
+X
+# Months of the year
+@MoY = ('January',     'Febuary',      'March',        'April',        'May',          'June',
+X              'July',         'August',       'September','October',  'November', 'December');
+X
+# days of the week
+@DoW = ('Sunday',      'Monday',       'Tuesday',      'Wednesday',
+X              'Thursday',     'Friday',       'Saturday');
+X
+# CUSTOMIZE - defaults
+$defaultTZ = 'CST';                                            # time zone (hack!)
+$defaultFMT = '%a %h %e %T %z%Y';              # format (ala date(1))
+X
+# CUSTOMIZE - `local' formats
+$locTF = '%T';                                                 # time (as HH:MM:SS)
+$locDF = '%D';                                                 # date (as mm/dd/yy)
+$locDTF = '%a %b %d %T %Y';                            # date/time (as dow mon dd HH:MM:SS yyyy)
+$locLDTF = '%i:%M:%S %p %A %B %E %Y';  # long date/time (as HH:MM:SS a/p day month dom yyyy)
+X
+# Time zone info
+$TZ;                                                                   # wkno needs this info too
+X
+# define the known format tags as associative keys with their associated
+# replacement strings as values.  Each replacement string should be
+# an eval-able expresion assigning a value to $rep.  These expressions are
+# eval-ed, then the value of $rep is substituted into the supplied
+# format (if any).
+%Tags = ( '%a', q|($rep = $DoW[$wday])=~ s/^(...).*/\1/|,      # abbr. weekday name - Sun to Sat
+X                '%A', q|$rep = $DoW[$wday]|,                                          # full weekday name - Sunday to Saturday
+X                '%b', q|($rep = $MoY[$mon]) =~ s/^(...).*/\1/|,       # abbr. month name - Jan to Dec
+X                '%B', q|$rep = $MoY[$mon]|,                                           # full month name - January to December
+X                '%c', q|$rep = $locDTF; 1|,                                           # date/time in local format
+X                '%C', q|$rep = $locLDTF; 1|,                                          # date/time in local long format
+X                '%d', q|$rep = &date'pad($mday, 2, "0")|,                     # day of month - 01 to 31
+X                '%D', q|$rep = '%m/%d/%y'|,                                           # date as mm/dd/yy
+X                '%e', q|$rep = &date'pad($mday, 2, " ")|,                     # day of month (space padded) ` 1' to `31'
+X                '%E', q|$rep = &date'dsuf($mday)|,                            # day of month (w/suffix) `1st' to `31st'
+X                '%f', q|$rep = &date'pad($mon+1, 2, " ")|,            # month of year (space padded) ` 1' to `12'
+X                '%h', q|$rep = '%b'|,                                                         # abbr. month name (same as %b)
+X                '%H', q|$rep = &date'pad($hour, 2, "0")|,                     # hour - 00 to 23
+X                '%i', q|$rep = &date'ampmH($hour, " ")|,                      # hour (space padded ` 1' to `12'
+X                '%I', q|$rep = &date'ampmH($hour, "0")|,                      # hour - 01 to 12
+X                '%j', q|$rep = &date'pad($yday+1, 3, "0")|,           # Julian date 001 - 366
+X                '%k', q|$rep = &date'pad($hour, 2, " ")|,                     # hour (space padded) ` 0' to `23'
+X                '%l', q|$rep = '%b %d ' . &date'ls($year)|,           # ls(1) style date
+X                '%m', q|$rep = &date'pad($mon+1, 2, "0")|,            # month of year - 01 to 12
+X                '%M', q|$rep = &date'pad($min, 2, "0")|,                      # minute - 00 to 59
+X                '%n', q|$rep = "\n"|,                                                         # insert a newline
+X                '%p', q|$rep = &date'ampmD($hour)|,                           # insert `AM' or `PM'
+X                '%r', q|$rep = '%I:%M:%S %p'|,                                        # time in AM/PM notation
+X                '%R', q|$rep = '%H:%M'|,                                                      # time as HH:MM
+X                '%S', q|$rep = &date'pad($sec, 2, "0")|,                      # second - 00 to 59
+X                '%t', q|$rep = "\t"|,                                                         # insert a tab
+X                '%T', q|$rep = '%H:%M:%S'|,                                           # time as HH:MM:SS
+X                '%u', q|$rep = '%y%m%d%H%M.%S'|,                                      # daaate/time in date(1) required format
+X                '%U', q|$rep = &date'wkno($yday, 0)|,                         # week number (weeks start on Sun) - 00 to 53
+X                '%V', q|$rep = '%m%d%H%M%y'|,                                         # SysV touch(1) date-time format (mmddHHMMyy)
+X                '%w', q|$rep = $wday; 1|,                                                     # day of week - Sunday = 0
+X                '%W', q|$rep = &date'wkno($yday, 1)|,                         # week number (weeks start on Mon) - 00 to 53
+X                '%x', q|$rep = $locDF; 1|,                                            # date in local format
+X                '%X', q|$rep = $locTF; 1|,                                            # time in local format
+X                '%y', q|($rep = $year) =~ s/..(..)/\1/|,                      # last 2 digits of year - 00 to 99
+X                '%Y', q|$rep = "$year"; 1|,                                           # full year ~ 1700 to 2000 odd
+X                '%z', q|$rep = $TZ eq "" ? "" : "$TZ "|,                      # time zone from TZ env var (w/trail. space)
+X                '%Z', q|$rep = $TZ; 1|,                                                       # time zone from TZ env. var.
+X                '%%', q|$rep = '%'; $adv=1|,                                          # insert a `%'
+X                '%+', q|$rep = '+'|                                                           # insert a `+'
+);
+X      
+sub main'date {
+X      local($time, $format) = @_;
+X      local($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst);
+X      local($pos, $tag, $rep, $adv) = (0, "", "", 0);
+X
+X      # default to date/ctime format or strip leading `+'...
+X      if ($format eq "") {
+X              $format = $defaultFMT;
+X      } elsif ($format =~ /^\+/) {
+X              $format = $';
+X      }
+X
+X      # Use local time if can't find a TZ in the environment
+X      $TZ = defined($ENV{'TZ'}) ? $ENV{'TZ'} : $defaultTZ;
+X      ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = 
+X              &gettime ($TZ, $time);
+X
+X      # Hack to deal with 'PST8PDT' format of TZ
+X      # Note that this can't deal with all the esoteric forms, but it
+X      # does recognize the most common: [:]STDoff[DST[off][,rule]]
+X      if ($TZ =~ /^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/) {
+X              $TZ = $isdst ? $4 : $1;
+X      }
+X
+X      # watch out in 2070...
+X      $year += ($year < 70) ? 2000 : 1900;
+X
+X      # now loop throught the supplied format looking for tags...
+X      while (($pos = index ($format, '%')) != -1) {
+X
+X              # grab the format tag
+X              $tag = substr($format, $pos, 2);
+X              $adv = 0;                                                       # for `%%' processing
+X
+X              # do we have a replacement string?
+X              if (defined $Tags{$tag}) {
+X
+X                      # trap dead evals...
+X                      if (! eval $Tags{$tag}) {
+X                              print STDERR "date.pl: internal error: eval for $tag failed.\n";
+X                              return "";
+X                      }
+X              } else {
+X                      $rep = "";
+X              }
+X                      
+X              # do the substitution
+X              substr ($format, $pos, 2) =~ s/$tag/$rep/;
+X              $pos++ if ($adv);
+X      }
+X
+X      $format;
+}
+X
+# dsuf - add `st', `nd', `rd', `th' to a date (ie 1st, 22nd, 29th)
+sub dsuf {
+X      local ($mday) = @_;
+X
+X      return $mday . 'st' if ($mday =~ m/.*1$/);
+X      return $mday . 'nd' if ($mday =~ m/.*2$/);
+X      return $mday . 'rd' if ($mday =~ m/.*3$/);
+X      return $mday . 'th';
+}
+X      
+# weekno - figure out week number
+sub wkno {
+X      local ($yday, $firstweekday) = @_;   
+X      local ($jan1, @jan1, $wks);
+X      local ($now) = time;
+X
+X      # figure out the `time' value for January 1
+X      $jan1 = $now - ((&gettime ($TZ, $now))[7] * 86400);             # 86400 sec/day
+X
+X      # figure out what day of the week January 1 was
+X      @jan1= &gettime ($TZ, $jan1);
+X      
+X      # and calculate the week number
+X      $wks = (($yday + ($jan1[6] - $firstweekday)) + 1)/ 7;
+X      $wks += (($wks - int($wks) > 0.0) ? 1 : 0);
+X
+X      # supply zero padding
+X      &pad (int($wks), 2, "0");
+}
+X
+# ampmH - figure out am/pm (1 - 12) mode hour value, padded with $p (0 or ' ')
+sub ampmH { local ($h, $p) = @_;  &pad($h>12 ? $h-12 : ($h ? $h : 12), 2, $p); }
+X
+# ampmD - figure out am/pm designator
+sub ampmD { shift @_ >= 12 ? "PM" : "AM"; }
+X
+# gettime - get the time via {local,gmt}time
+sub gettime { ((shift @_) eq 'GMT') ? gmtime(shift @_) : localtime(shift @_); }
+X
+# ls - generate the time/year portion of an ls(1) style date
+sub ls {
+X      return ((&gettime ($TZ, time))[5] == @_[0]) ? "%R" : " %Y";
+}
+X
+# pad - pad $in with leading $pad until lenght $len
+sub pad {
+X      local ($in, $len, $pad) = @_;
+X      local ($out) = "$in";
+X
+X      $out = $pad . $out until (length ($out) == $len);
+X      return $out;
+}
+X
+1;
+SHAR_EOF
+chmod 0444 libs/date.pl ||
+echo 'restore of libs/date.pl failed'
+Wc_c="`wc -c < 'libs/date.pl'`"
+test 11619 -eq "$Wc_c" ||
+       echo 'libs/date.pl: original size 11619, current size' "$Wc_c"
+fi
+# ============= libs/elapsed.pl ==============
+if test -f 'libs/elapsed.pl' -a X"$1" != X"-c"; then
+       echo 'x - skipping libs/elapsed.pl (File already exists)'
+else
+echo 'x - extracting libs/elapsed.pl (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'libs/elapsed.pl' &&
+;# NAME
+;#    elapsed.pl - convert seconds to elapsed time format
+;#
+;# AUTHOR
+;#    Michael S. Muegel <mmuegel@mot.com>
+;#
+;# RCS INFORMATION
+;#    $Author: glass $
+;#    $Source: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v $
+;#    $Revision: 1.2 $ of $Date: 1993/06/28 22:33:06 $
+X
+package elapsed;
+X
+# Time field types
+$DAYS          = 1;
+$HOURS         = 2;
+$MINUTES       = 3;
+$SECONDS       = 4;
+X
+# The array contains four records each with four fields. The fields are,
+# in order:
+#
+#    Type              Specifies what kind of time field this is. Once of
+#                      $DAYS, $HOURS, $MINUTES, or $SECONDS.
+#
+#    Multiplier                Specifies what time field this is via the minimum
+#                      number of seconds this time field may specify. For
+#                      example, the minutes field would be non-zero
+#                      when there are 60 or more seconds.
+#                      
+#    Separator         How to separate this time field from the next
+#                      *greater* field.
+#
+#    Format            sprintf() format specifier on how to print this
+#                      time field.
+@MULT_AND_SEPS = ($DAYS, 60 * 60 * 24, "+", "%d",
+X                  $HOURS, 60 * 60, ":", "%d",
+X                  $MINUTES, 60, ":", "%02d",
+X                  $SECONDS, 1, "", "%02d"
+X                 );
+X
+;###############################################################################
+;# Seconds_To_Elapsed
+;#
+;# Coverts a seconds count to form [d+]h:mm:ss. If $Collapse
+;# is true then the result is compacted somewhat. The string returned
+;# will be of the form [d+][[h:]mm]:ss.
+;#
+;# Arguments:
+;#    $Seconds, $Collapse
+;#
+;# Examples:
+;#    &Seconds_To_Elapsed (0, 0)       -> 0:00:00
+;#    &Seconds_To_Elapsed (0, 1)       -> :00
+;#
+;#    &Seconds_To_Elapsed (119, 0)     -> 0:01:59
+;#    &Seconds_To_Elapsed (119, 1)     -> 01:59
+;#
+;#    &Seconds_To_Elapsed (3601, 0)    -> 1:00:01
+;#    &Seconds_To_Elapsed (3601, 1)    -> 1:00:01
+;#
+;#    &Seconds_To_Elapsed (86401, 0)   -> 1+0:00:01
+;#    &Seconds_To_Elapsed (86401, 1)   -> 1+:01
+;#
+;# Returns:
+;#    $Elapsed
+;###############################################################################
+sub main'Seconds_To_Elapsed
+{
+X   local ($Seconds, $Collapse) = @_;
+X   local ($Type, $Multiplier, @Multipliers, $Separator, $DHMS_Used, 
+X          $Elapsed, @Mult_And_Seps, $Print_Field);
+X
+X   $Multiplier = 1;
+X   @Mult_And_Seps = @MULT_AND_SEPS;
+X
+X   # Keep subtracting the number of seconds corresponding to a time field
+X   # from the number of seconds passed to the function.
+X   while (1)
+X   {
+X      ($Type, $Multiplier, $Separator, $Format) = splice (@Mult_And_Seps, 0, 4);
+X      last if (! $Multiplier);
+X      $Seconds -= $DHMS_Used * $Multiplier 
+X         if ($DHMS_Used = int ($Seconds / $Multiplier));
+X
+X      # Figure out if we should print this field
+X      if ($Type == $DAYS)
+X      {
+X       $Print_Field = $DHMS_Used;
+X      }
+X
+X      elsif ($Collapse)
+X      {
+X       if ($Type == $HOURS)
+X       {
+X          $Print_Field = $DHMS_Used;
+X       }
+X       elsif ($Type == $MINUTES)
+X       {
+X          $Print_Field = $DHMS_Used || $Printed_Field {$HOURS};
+X       }
+X       else
+X       {
+X          $Format = ":%02d" 
+X             if (! $Printed_Field {$MINUTES});
+X          $Print_Field = 1;
+X       };
+X      }
+X
+X      else
+X      {
+X       $Print_Field = 1;
+X      };
+X
+X      $Printed_Field {$Type} = $Print_Field;
+X      $Elapsed .= sprintf ("$Format%s", $DHMS_Used, $Separator) 
+X       if ($Print_Field);
+X   };
+X
+X   return ($Elapsed);
+};
+X
+1;
+SHAR_EOF
+chmod 0444 libs/elapsed.pl ||
+echo 'restore of libs/elapsed.pl failed'
+Wc_c="`wc -c < 'libs/elapsed.pl'`"
+test 3243 -eq "$Wc_c" ||
+       echo 'libs/elapsed.pl: original size 3243, current size' "$Wc_c"
+fi
+# ============= libs/mail.pl ==============
+if test -f 'libs/mail.pl' -a X"$1" != X"-c"; then
+       echo 'x - skipping libs/mail.pl (File already exists)'
+else
+echo 'x - extracting libs/mail.pl (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'libs/mail.pl' &&
+;# NAME
+;#    mail.pl - perl function(s) to handle mail processing
+;#
+;# AUTHOR
+;#    Michael S. Muegel (mmuegel@mot.com)
+;#
+;# RCS INFORMATION
+;#    $Author: glass $
+;#    $Header: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v 1.2 1993/06/28 22:33:06 glass Exp $
+X
+package mail;
+X
+# Mailer statement to eval. $Users, $Subject, and $Verbose are substituted 
+# via eval
+$BIN_MAILER            = "/usr/ucb/mail \$Verbose -s '\$Subject' \$Users";
+X
+# Sendmail command to use when $Use_Sendmail is true.
+$SENDMAIL              = '/usr/lib/sendmail $Verbose $Users';
+X
+;###############################################################################
+;# Send_Mail
+;#
+;# Sends $Message to $Users with a subject of $Subject. If $Message_Is_File
+;# is true then $Message is assumed to be a filename pointing to the mail
+;# message. This is a new option and thus the backwards-compatible hack.
+;# $Users should be a space separated list of mail-ids.
+;#
+;# If everything went OK $Status will be 1 and $Error_Msg can be ignored; 
+;# otherwise, $Status will be 0 and $Error_Msg will contain an error message.
+;# 
+;# If $Use_Sendmail is 1 then sendmail is used to send the message. Normally
+;# a mailer such as Mail is used. By specifiying this you can include 
+;# headers in addition to text in either $Message or $Message_Is_File.
+;# If either $Message or $Message_Is_File contain a Subject: header then
+;# $Subject is ignored; otherwise, a Subject: header is automatically created.
+;# Similar to the Subject: header, if a To: header does not exist one
+;# is automatically created from the $Users argument. The mail is still
+;# sent, however, to the recipients listed in $Users. This is keeping with
+;# normal sendmail usage (header vs. envelope).
+;# 
+;# In both bin mailer and sendmail modes $Verbose will turn on verbose mode
+;# (normally just sendmail verbose mode output).
+;#
+;# Arguments:
+;#    $Users, $Subject, $Message, $Message_Is_File, $Verbose, $Use_Sendmail
+;#
+;# Returns:
+;#    $Status, $Error_Msg
+;###############################################################################
+sub main'Send_Mail
+{
+X   local ($Users, $Subject, $Message, $Message_Is_File, $Verbose, 
+X        $Use_Sendmail) = @_;
+X   local ($BIN_MAILER_HANDLE, $Mailer_Command, $Header_Found, %Header_Map,
+X        $Header_Extra, $Mailer);
+X
+X   # If the message is contained in a file read it in so we can have one
+X   # consistent interface
+X   if ($Message_Is_File)
+X   {
+X      undef $/;
+X      $Message_Is_File = 0;
+X      open (Message) || return (0, "error reading $Message: $!");
+X      $Message = <Message>;
+X      close (Message);
+X   };
+X
+X   # If sendmail mode see if we need to add some headers
+X   if ($Use_Sendmail)
+X   {
+X      # Determine if a header block is included in the message and what headers
+X      # are there
+X      foreach (split (/\n/, $Message))
+X      {
+X       last if ($_ eq "");
+X       $Header_Found = $Header_Map {$1} = 1 if (/^([A-Z]\S*): /);
+X      };
+X
+X      # Add some headers?
+X      if (! $Header_Map {"To"})
+X      {
+X       $Header_Extra .= "To: " . join (", ", $Users) . "\n";
+X      };
+X      if (($Subject ne "") && (! $Header_Map {"Subject"}))
+X      {
+X       $Header_Extra .= "Subject: $Subject\n";
+X      };
+X
+X      # Add the required blank line between header/body if there where no
+X      # headers to begin with
+X      if ($Header_Found)
+X      {
+X         $Message = "$Header_Extra$Message";
+X      }
+X      else
+X      {
+X       $Message = "$Header_Extra\n$Message";
+X      };
+X   };
+X
+X   # Get a string that is the mail command
+X   $Verbose = ($Verbose) ? "-v" : "";
+X   $Mailer = ($Use_Sendmail) ? $SENDMAIL : $BIN_MAILER;
+X   eval "\$Mailer = \"$Mailer\"";
+X   return (0, "error setting \$Mailer: $@") if ($@);
+X
+X   # need to catch SIGPIPE in case the $Mailer call fails
+X   $SIG {'PIPE'} = "mail'Cleanup";
+X
+X   # Open mailer
+X   return (0, "can not open mail program: $Mailer") if (! open (MAILER, "| $Mailer"));
+X   
+X   # Send off the mail!
+X   print MAILER $Message;
+X   close (MAILER);
+X   return (0, "error running mail program: $Mailer") if ($?);
+X   
+X   # Everything must have went AOK
+X   return (1);
+};
+X
+;###############################################################################
+;# Cleanup
+;#
+;# Simply here so we can catch SIGPIPE and not exit.
+;#
+;# Globals:
+;#    None
+;#
+;# Arguments:
+;#    None
+;#
+;# Returns:
+;#    Nothing exciting
+;###############################################################################
+sub Cleanup
+{
+};
+X
+1;
+SHAR_EOF
+chmod 0444 libs/mail.pl ||
+echo 'restore of libs/mail.pl failed'
+Wc_c="`wc -c < 'libs/mail.pl'`"
+test 4379 -eq "$Wc_c" ||
+       echo 'libs/mail.pl: original size 4379, current size' "$Wc_c"
+fi
+# ============= libs/mqueue.pl ==============
+if test -f 'libs/mqueue.pl' -a X"$1" != X"-c"; then
+       echo 'x - skipping libs/mqueue.pl (File already exists)'
+else
+echo 'x - extracting libs/mqueue.pl (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'libs/mqueue.pl' &&
+;# NAME
+;#    mqueue.pl - functions to work with the sendmail queue
+;#
+;# DESCRIPTION
+;#    Both Get_Queue_IDs and Parse_Control_File are available to get 
+;#    information about the sendmail queue. The cqueue program is a good
+;#    example of how these functions work.
+;#
+;# AUTHOR
+;#    Michael S. Muegel (mmuegel@mot.com)  
+;#
+;# RCS INFORMATION
+;#    $Author: glass $
+;#    $Source: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v $
+;#    $Revision: 1.2 $ of $Date: 1993/06/28 22:33:06 $
+X
+package mqueue;
+X
+;###############################################################################
+;# Get_Queue_IDs
+;#
+;# Will figure out the queue IDs in $Queue that have both control and data
+;# files. They are returned in @Valid_IDs. Those IDs that have a
+;# control file and no data file are saved to the array globbed by 
+;# *Missing_Control_IDs. Likewise, those IDs that have a data file and no 
+;# control file are saved to the array globbed by *Missing_Data_IDs.
+;#
+;# If $Skip_Locked is true they a message that has a lock file is skipped
+;# and will not show up in any of the arrays.
+;#
+;# If everything went AOK then $Status is 1; otherwise, $Status is 0 and
+;# $Msg tells what went wrong.
+;#
+;# Globals:
+;#    None
+;#
+;# Arguments:
+;#    $Queue, $Skip_Locked, *Missing_Control_IDs, *Missing_Data_IDs
+;#
+;# Returns:
+;#    $Status, $Msg, @Valid_IDs
+;###############################################################################
+sub main'Get_Queue_IDs
+{
+X   local ($Queue, $Skip_Locked, *Missing_Control_IDs, 
+X          *Missing_Data_IDs) = @_;
+X   local (*QUEUE, @Files, %Lock_IDs, %Data_IDs, %Control_IDs, $_);
+X
+X   # Make sure that the * argument @arrays ar empty
+X   @Missing_Control_IDs = @Missing_Data_IDs = ();
+X
+X   # Save each data, lock, and queue file in @Files
+X   opendir (QUEUE, $Queue) || return (0, "error getting directory listing of $Queue");
+X   @Files = grep (/^(df|lf|qf)/, readdir (QUEUE));
+X   closedir (QUEUE);
+X   
+X   # Create indexed list of data and control files. IF $Skip_Locked is true
+X   # then skip either if there is a lock file present.
+X   if ($Skip_Locked)
+X   {
+X      grep ((s/^lf//) && ($Lock_IDs {$_} = 1), @Files);
+X      grep ((s/^df//) && (! $Lock_IDs {$_}) && ($Data_IDs {$_} = 1), @Files);
+X      grep ((s/^qf//) && (! $Lock_IDs {$_}) && ($Control_IDs {$_} = 1), @Files);
+X   }
+X   else
+X   {
+X      grep ((s/^df//) && ($Data_IDs {$_} = 1), @Files);
+X      grep ((s/^qf//) && ($Control_IDs {$_} = 1), @Files);
+X   };
+X   
+X   # Find missing control and data files and remove them from the lists of each
+X   @Missing_Control_IDs = sort (grep ((! $Control_IDs {$_}) && (delete $Data_IDs {$_}), keys (%Data_IDs)));
+X   @Missing_Data_IDs = sort (grep ((! $Data_IDs {$_} && (delete $Control_IDs {$_})), keys (%Control_IDs)));
+X   
+X   
+X   # Return the IDs in an appartently random order
+X   return (1, "", keys (%Control_IDs));
+};
+X
+X
+;###############################################################################
+;# Parse_Control_File
+;#
+;# Will pase a sendmail queue control file for useful information. See the
+;# Sendmail Installtion and Operation Guide (SMM:07) for a complete
+;# explanation of each field.
+;#
+;# The following globbed variables are set (or cleared) by this function:
+;#
+;#    $Sender           The sender's address. 
+;#
+;#    @Recipients       One or more addresses for the recipient of the mail.
+;#
+;#    @Errors_To        One or more addresses for addresses to which mail
+;#                      delivery errors should be sent.
+;#
+;#    $Creation_Time    The job creation time in time(3) format. That is,
+;#                      seconds since 00:00:00 GMT 1/1/70.
+;#
+;#    $Priority         An integer representing the current message priority.
+;#                      This is used to order the queue. Higher numbers mean 
+;#                      lower priorities.
+;#
+;#    $Status_Message   The status of the mail message. It can contain any
+;#                      text.
+;#
+;#    @Headers          Message headers unparsed but in their original order.
+;#                      Headers that span multiple lines are not mucked with,
+;#                      embedded \ns will be evident.
+;#
+;# In all e-mail addresses bounding <> pairs are stripped.
+;#
+;# If everything went AOK then $Status is 1. If the message with queue ID
+;# $Queue_ID just does not exist anymore -1 is returned. This is very
+;# possible and should be allowed for. Otherwise, $Status is 0 and $Msg 
+;# tells what went wrong.
+;#
+;# Globals:
+;#    None
+;#
+;# Arguments:
+;#    $Queue, $Queue_ID, *Sender, *Recipients, *Errors_To, *Creation_Time, 
+;#    *Priority, *Status_Message, *Headers
+;#
+;# Returns:
+;#    $Status, $Msg
+;###############################################################################
+sub main'Parse_Control_File
+{
+X   local ($Queue, $Queue_ID, *Sender, *Recipients, *Errors_To, *Creation_Time,
+X          *Priority, *Status_Message, *Headers) = @_;
+X   local (*Control, $_, $Not_Empty);
+X
+X   # Required variables and the associated control. If empty at the end of
+X   # parsing we return a bad status.
+X   @REQUIRED_INFO = ('$Creation_Time', 'T', '$Sender', 'S', '@Recipients', 'R',
+X                   '$Priority', 'P');
+X
+X   # Open up the control file for read
+X   $Control = "$Queue/qf$Queue_ID";
+X   if (! open (Control)) 
+X   {
+X      return (-1) if ((-x $Queue) && (! -f "$Queue/qf$Queue_ID") &&
+X       (! -f "$Queue/df$Queue_ID"));
+X      return (0, "error opening $Control for read: $!");
+X   };
+X
+X   # Reset the globbed variables just in case
+X   $Sender = $Creation_Time = $Priority = $Status_Message = "";
+X   @Recipients = @Errors_To = @Headers = ();
+X
+X   # Look for a few things in the control file
+X   READ: while (<Control>)
+X   {
+X      $Not_Empty = 1;
+X      chop;
+X
+X      PARSE:
+X      {
+X         if (/^T(\d+)$/)
+X         {
+X            $Creation_Time = $1;
+X         }
+X         elsif (/^S(<)?([^>]+)/)
+X         {
+X            $Sender = $2;
+X         }
+X         elsif (/^R(<)?([^>]+)/)
+X         {
+X            push (@Recipients, $2);
+X         }
+X         elsif (/^E(<)?([^>]+)/)
+X         {
+X            push (@Errors_To, $2);
+X         }
+X         elsif (/^M(.*)/)
+X         {
+X            $Status_Message = $1;
+X         }
+X         elsif (/^P(\d+)$/)
+X         {
+X            $Priority = $1;
+X         }
+X         elsif (/^H(.*)/)
+X         {
+X            $Header = $1;
+X            while (<Control>)
+X            {
+X               chop;
+X               last if (/^[A-Z]/);
+X               $Header .= "\n$_";
+X            };
+X            push (@Headers, $Header);
+X          redo PARSE if ($_);
+X          last if (eof);
+X         };
+X      };
+X   };
+X
+X   # If the file was empty scream bloody murder
+X   return (0, "empty control file") if (! $Not_Empty);
+X
+X   # Yell if we could not find a required field
+X   while (($Var, $Control) = splice (@REQUIRED_INFO, 0, 2))
+X   {
+X      eval "return (0, 'required control field $Control not found')
+X             if (! $Var)";
+X      return (0, "error checking \$Var: $@") if ($@);
+X   };
+X
+X   # Everything went AOK
+X   return (1);
+};
+X
+1;
+SHAR_EOF
+chmod 0444 libs/mqueue.pl ||
+echo 'restore of libs/mqueue.pl failed'
+Wc_c="`wc -c < 'libs/mqueue.pl'`"
+test 6953 -eq "$Wc_c" ||
+       echo 'libs/mqueue.pl: original size 6953, current size' "$Wc_c"
+fi
+# ============= libs/newgetopts.pl ==============
+if test -f 'libs/newgetopts.pl' -a X"$1" != X"-c"; then
+       echo 'x - skipping libs/newgetopts.pl (File already exists)'
+else
+echo 'x - extracting libs/newgetopts.pl (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'libs/newgetopts.pl' &&
+;# NAME
+;#    newgetopts.pl - a better newgetopt (which is a better getopts which is
+;#                    a better getopt ;-)
+;#
+;# AUTHOR
+;#    Mike Muegel (mmuegel@mot.com)
+;#
+;# $Author: glass $
+;# $Header: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v 1.2 1993/06/28 22:33:06 glass Exp $
+X
+;###############################################################################
+;# New_Getopts
+;#
+;# Does not care about order of switches, options, and arguments like 
+;# getopts.pl. Thus all non-switches/options will be kept in ARGV even if they
+;# are not at the end. If $Pass_Invalid is set all unkown options will be
+;# passed back to the caller by keeping them in @ARGV. This is useful when
+;# parsing a command line for your script while ignoring options that you
+;# may pass to another script. If this is set New_Getopts tries to maintain 
+;# the switch clustering on the unkown switches.
+;#
+;# Accepts the special argument -usage to print the Usage string. Also accepts 
+;# the special option -version which prints the contents of the string 
+;# $VERSION. $VERSION may or may not have an embeded \n in it. If -usage 
+;# or -version are specified a status of -1 is returned. Note that the usage
+;# option is only accepted if the usage string is not null.
+;# 
+;# $Switches is just like the formal arguemnt of getopts.pl. $Usage is a usage
+;# string with or without a trailing \n. *Switch_To_Order is an optional
+;# pointer to the name of an associative array which will contain a mapping of
+;# switch names to the order in which (if at all) the argument was entered.
+;#
+;# For example, if @ARGV contains -v, -x, test:
+;#
+;#    $Switch_To_Order {"v"} = 1;
+;#    $Switch_To_Order {"x"} = 2;
+;#
+;# Note that in the case of multiple occurances of an option $Switch_To_Order
+;# will store each occurance of the argument via a string that emulates
+;# an array. This is done by using join ($;, ...). You can retrieve the
+;# array by using split (/$;/, ...).
+;#
+;# *Split_ARGV is an optional pointer to an array which will conatin the
+;# original switches along with their values. For the example used above 
+;# Split_ARGV would contain:
+;#
+;#   @Split_ARGV = ("v", "", "x", "test");
+;#
+;# Another exciting ;-) feature that newgetopts has. Along with creating the 
+;# normal $opt_ scalars for the last value of an argument the list @opt_ is 
+;# created. It is an array which contains all the values of arguments to the 
+;# basename of the variable. They are stored in the order which they occured 
+;# on the command line starting with $[. Note that blank arguments are stored 
+;# as "". Along with providing support for multiple options on the command 
+;# line this also provides a method of counting the number of times an option 
+;# was specified via $#opt_.
+;#
+;# Automatically resets all $opt_, @opt_, %Switch_To_Order, and @Split_ARGV
+;# variables so that New_Getopts may be called more than once from within
+;# the same program. Thus, if $opt_v is set upon entry to New_Getopts and 
+;# -v is not in @ARGV $opt_v will not be set upon exit.
+;#
+;# Arguments:
+;#    $Switches, $Usage, $Pass_Invalid, *Switch_To_Order, *Split_ARGV
+;#
+;# Returns:
+;#    -1, 0, or 1 depending on status (printed Usage/Version, OK, not OK)
+;###############################################################################
+sub New_Getopts 
+{
+X    local($taint_argumentative, $Usage, $Pass_Invalid, *Switch_To_Order,
+X          *Split_ARGV) = @_;
+X    local(@args,$_,$first,$rest,$errs, @leftovers, @current_leftovers,
+X          %Switch_Found);
+X    local($[, $*, $Script_Name, $argumentative);
+X
+X    # Untaint the argument cluster so that we can use this with taintperl
+X    $taint_argumentative =~ /^(.*)$/;
+X    $argumentative = $1;
+X
+X    # Clear anything that might still be set from a previous New_Getopts
+X    # call.
+X    @Split_ARGV = ();
+X
+X    # Get the basename of the calling script
+X    ($Script_Name = $0) =~ s/.*\///;
+X    
+X    # Make Usage have a trailing \n
+X    $Usage .= "\n" if ($Usage !~ /\n$/);
+X
+X    @args = split( / */, $argumentative );
+X
+X    # Clear anything that might still be set from a previous New_Getopts call.
+X    foreach $first (@args)
+X    {
+X       next if ($first eq ":");
+X       delete $Switch_Found {$first};
+X       delete $Switch_To_Order {$first};
+X       eval "undef \@opt_$first; undef \$opt_$first;";
+X    };
+X
+X    while (@ARGV)
+X    {
+X        # Let usage through
+X        if (($ARGV[0] eq "-usage") && ($Usage ne "\n"))
+X        {
+X           print $Usage;
+X           exit (-1);
+X        }
+X
+X        elsif ($ARGV[0] eq "-version")
+X        {
+X           if ($VERSION)
+X           {
+X              print $VERSION;
+X              print "\n" if ($VERSION !~ /\n$/);
+X           }
+X           else
+X           {
+X              warn "${Script_Name}: no version information available, sorry\n";
+X           }
+X           exit (-1);
+X        }
+X
+X        elsif (($_ = $ARGV[0]) =~ /^-(.)(.*)/)
+X        {
+X           ($first,$rest) = ($1,$2);
+X           $pos = index($argumentative,$first);
+X
+X           $Switch_To_Order {$first} = join ($;, split (/$;/, $Switch_To_Order {$first}), ++$Order);
+X
+X           if($pos >= $[) 
+X           {
+X               if($args[$pos+1] eq ':') 
+X               {
+X                   shift(@ARGV);
+X                   if($rest eq '') 
+X                   {
+X                       $rest = shift(@ARGV);
+X                   }
+X
+X                   eval "\$opt_$first = \$rest;";
+X                   eval "push (\@opt_$first, \$rest);";
+X                   push (@Split_ARGV, $first, $rest);
+X               }
+X               else 
+X               {
+X                   eval "\$opt_$first = 1";
+X                   eval "push (\@opt_$first, '');";
+X                   push (@Split_ARGV, $first, "");
+X
+X                   if($rest eq '') 
+X                   {
+X                       shift(@ARGV);
+X                   }
+X                   else 
+X                   {
+X                       $ARGV[0] = "-$rest";
+X                   }
+X               }
+X           }
+X
+X           else 
+X           {
+X               # Save any other switches if $Pass_Valid
+X               if ($Pass_Invalid)
+X               {
+X                  push (@current_leftovers, $first);
+X               }
+X               else
+X               {
+X                  warn "${Script_Name}: unknown option: $first\n";
+X                  ++$errs;
+X               };
+X               if($rest ne '') 
+X               {
+X                   $ARGV[0] = "-$rest";
+X               }
+X               else 
+X               {
+X                   shift(@ARGV);
+X               }
+X           }
+X        }
+X
+X        else
+X        {
+X           push (@leftovers, shift (@ARGV));
+X        };
+X
+X        # Save any other switches if $Pass_Valid
+X        if ((@current_leftovers) && ($rest eq ''))
+X        {
+X           push (@leftovers, "-" . join ("", @current_leftovers));
+X           @current_leftovers = ();
+X        };
+X    };
+X
+X    # Automatically print Usage if a warning was given
+X    @ARGV = @leftovers;
+X    if ($errs != 0)
+X    {
+X       warn $Usage;
+X       return (0);
+X    }
+X    else
+X    {
+X       return (1);
+X    }
+X       
+}
+X
+1;
+SHAR_EOF
+chmod 0444 libs/newgetopts.pl ||
+echo 'restore of libs/newgetopts.pl failed'
+Wc_c="`wc -c < 'libs/newgetopts.pl'`"
+test 7030 -eq "$Wc_c" ||
+       echo 'libs/newgetopts.pl: original size 7030, current size' "$Wc_c"
+fi
+# ============= libs/strings1.pl ==============
+if test -f 'libs/strings1.pl' -a X"$1" != X"-c"; then
+       echo 'x - skipping libs/strings1.pl (File already exists)'
+else
+echo 'x - extracting libs/strings1.pl (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'libs/strings1.pl' &&
+;# NAME
+;#    strings1.pl - FUN with strings #1
+;#
+;# NOTES
+;#    I wrote Format_Text_Block when I just started programming Perl so
+;#    it is probably not very Perlish code. Center is more like it :-).
+;#
+;# AUTHOR
+;#    Michael S. Muegel (mmuegel@mot.com)
+;#
+;# RCS INFORMATION
+;#    $Author: glass $
+;#    $Header: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v 1.2 1993/06/28 22:33:06 glass Exp $
+X
+package strings1;
+X
+;###############################################################################;# Center
+;#
+;# Center $Text assuming the output should be $Columns wide. $Text can span
+;# multiple lines, of course :-). Lines within $Text that contain only 
+;# whitespace are not centered and are instead collapsed. This may save time 
+;# when printing them later.
+;#
+;# Arguments:
+;#    $Text, $Columns
+;#
+;# Returns:
+;#    $Centered_Text
+;###############################################################################
+sub main'Center
+{
+X   local ($_, $Columns) = @_;
+X   local ($*) = 1;
+X
+X   s@^(.*)$@" " x (($Columns - length ($1)) / 2) . $1@eg;
+X   s/^[\t ]*$//g;
+X   return ($_);
+};
+X
+;###############################################################################
+;# Format_Text_Block
+;#
+;# Formats a text string to be printed to the display or other similar device.
+;# Text in $String will be fomratted such that the following hold:
+;#
+;#    + $String contains the (possibly) multi-line text to print. It is
+;#     automatically word-wrapped to fit in $Columns. 
+;#
+;#    + \n'd are maintained and are not folded.
+;#
+;#    + $Offset        is pre-pended before each separate line of text. 
+;#
+;#    + If $Offset_Once        is $TRUE $Offset will only appear on the first line.
+;#      All other lines will be indented to match the amount of whitespace of
+;#      $Offset.
+;#
+;#    + If $Bullet_Indent is $TRUE $Offset will only be applied to the begining
+;#      of lines as they occured in the original $String. Lines that are created
+;#      by this routine will always be indented by blank spaces.
+;#
+;#    + If $Columns is 0 no word-wrap is done. This might be useful to still
+;#      to offset each line in a buffer.
+;#
+;#    + If $Split_Expr is supplied the string is split on it. If not supplied
+;#      the string is split on " \t\/\-\,\." by default.
+;#
+;#    + If $Offset_Blank is $TRUE then empty lines will have $Offset pre-pended
+;#      to them. Otherwise, they will still empty.
+;#
+;# This is a realy workhorse routine that I use in many places because of its
+;# veratility.
+;#
+;# Arguments:
+;#    $String, $Offset, $Offset_Once, $Bullet_Indent, $Columns, $Split_Expr,
+;#    $Offset_Blank
+;#
+;# Returns:
+;#    $Buffer
+;###############################################################################
+sub main'Format_Text_Block
+{
+X   local ($String, $Real_Offset, $Offset_Once, $Bullet_Indent, $Columns, 
+X      $Split_Expr, $Offset_Blank) = @_;
+X
+X   local ($New_Line, $Line, $Chars_Per_Line, $Space_Offset, $Buffer,
+X      $Next_New_Line, $Num_Lines, $Num_Offsets, $Offset);
+X   local ($*) = 0;
+X   local ($BLANK_TAG) = "__FORMAT_BLANK__";
+X   local ($Blank_Offset) = $Real_Offset if ($Offset_Blank);
+X
+X   # What should we split on?
+X   $Split_Expr = " \\t\\/\\-\\,\\." if (! $Split_Expr);
+X
+X   # Pre-process the string - convert blank lines to __FORMAT_BLANK__ sequence
+X   $String =~ s/\n\n/\n$BLANK_TAG\n/g;
+X   $String =~ s/^\n/$BLANK_TAG\n/g;
+X   $String =~ s/\n$/\n$BLANK_TAG/g;
+X
+X   # If bad $Columns/$Offset combo or no $Columns make a VERRRYYY wide $Column
+X   $Offset = $Real_Offset;
+X   $Chars_Per_Line = 16000 if (($Chars_Per_Line = $Columns - length ($Offset)) <= 0);
+X   $Space_Offset = " " x length ($Offset);
+X
+X   # Get a buffer
+X   foreach $Line (split ("\n", $String))
+X   {
+X      $Offset = $Real_Offset if ($Bullet_Indent);
+X
+X      # Find where to split the line
+X      if ($Line ne $BLANK_TAG)
+X      { 
+X         $New_Line = "";
+X         while ($Line =~ /^([$Split_Expr]*)([^$Split_Expr]+)/)
+X         {
+X            if (length ("$New_Line$&") >= $Chars_Per_Line)
+X            {
+X               $Next_New_Line = $+;
+X               $New_Line = "$Offset$New_Line$1";
+X               $Buffer .= "\n" if ($Num_Lines++);
+X               $Buffer .= $New_Line;
+X               $Offset = $Space_Offset if (($Offset) && ($Offset_Once));
+X               $New_Line = $Next_New_Line;
+X               ++$Num_Lines;
+X            }
+X            else
+X            {
+X               $New_Line .= $&;
+X            };
+X            $Line = $';
+X         };
+X
+X         $Buffer .= "\n" if ($Num_Lines++);
+X         $Buffer .= "$Offset$New_Line$Line";
+X         $Offset = $Space_Offset if (($Offset) && ($Offset_Once));
+X      }
+X
+X      else
+X      {
+X         $Buffer .= "\n$Blank_Offset";
+X      };
+X   };
+X
+X   return ($Buffer);
+X
+};
+X
+1;
+SHAR_EOF
+chmod 0444 libs/strings1.pl ||
+echo 'restore of libs/strings1.pl failed'
+Wc_c="`wc -c < 'libs/strings1.pl'`"
+test 4718 -eq "$Wc_c" ||
+       echo 'libs/strings1.pl: original size 4718, current size' "$Wc_c"
+fi
+# ============= libs/timespec.pl ==============
+if test -f 'libs/timespec.pl' -a X"$1" != X"-c"; then
+       echo 'x - skipping libs/timespec.pl (File already exists)'
+else
+echo 'x - extracting libs/timespec.pl (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'libs/timespec.pl' &&
+;# NAME
+;#    timespec.pl - convert a pre-defined time specifyer to seconds
+;#
+;# AUTHOR
+;#    Michael S. Muegel (mmuegel@mot.com)
+;#
+;# RCS INFORMATION
+;#    $Author: glass $
+;#    $Header: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v 1.2 1993/06/28 22:33:06 glass Exp $
+X
+package timespec;
+X
+%TIME_SPEC_TO_SECONDS  = ("s", 1,
+X                         "m", 60,
+X                         "h", 60 * 60,
+X                         "d", 60 * 60 * 24
+X                         );
+X
+$VALID_TIME_SPEC_EXPR  = "[" . join ("", keys (%TIME_SPEC_TO_SECONDS)) . "]";
+X
+;###############################################################################
+;# Time_Spec_To_Seconds
+;#
+;# Converts a string of the form:
+;#
+;#    (<number>(s|m|h|d))+
+;#
+;# to seconds. The second part of the time spec specifies seconds, minutes, 
+;# hours, or days, respectfully. The first part is the number of those untis. 
+;# There can be any number of such specifiers. As an example, 1h30m means 1 
+;# hour and 30 minutes.
+;#
+;# If the parsing went OK then $Status is 1, $Msg is undefined, and $Seconds
+;# is $Time_Spec converted to seconds. If something went wrong then $Status
+;# is 0 and $Msg explains what went wrong.
+;#
+;# Arguments:
+;#    $Time_Spec
+;#
+;# Returns:
+;#    $Status, $Msg, $Seconds
+;###############################################################################
+sub main'Time_Spec_To_Seconds
+{
+X   $Time_Spec = $_[0];
+X
+X   $Seconds = 0;
+X   while ($Time_Spec =~ /^(\d+)($VALID_TIME_SPEC_EXPR)/)
+X   {
+X      $Seconds += $1 * $TIME_SPEC_TO_SECONDS {$2};
+X      $Time_Spec = $';
+X   };
+X
+X   return (0, "error parsing time spec: $Time_Spec") if ($Time_Spec ne "");
+X   return (1, "", $Seconds);
+X
+};
+X
+X
+1;
+SHAR_EOF
+chmod 0444 libs/timespec.pl ||
+echo 'restore of libs/timespec.pl failed'
+Wc_c="`wc -c < 'libs/timespec.pl'`"
+test 1637 -eq "$Wc_c" ||
+       echo 'libs/timespec.pl: original size 1637, current size' "$Wc_c"
+fi
+# ============= man/cqueue.1 ==============
+if test ! -d 'man'; then
+    echo 'x - creating directory man'
+    mkdir 'man'
+fi
+if test -f 'man/cqueue.1' -a X"$1" != X"-c"; then
+       echo 'x - skipping man/cqueue.1 (File already exists)'
+else
+echo 'x - extracting man/cqueue.1 (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'man/cqueue.1' &&
+.TH CQUEUE 1L
+\"
+\" $Author: glass $
+\" $Header: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v 1.2 1993/06/28 22:33:06 glass Exp $
+\"
+.ds mp \fBcqueue\fR
+.de IB
+.IP \(bu 2
+..
+.SH NAME
+\*(mp - check sendmail queue for problems
+.SH SYNOPSIS
+.IP \*(mp 7 
+[ \fB-abdms\fR ] [ \fB-q\fR \fIqueue-dir\fI ] [ \fB-t\fR \fItime\fR ] 
+[ \fB-u\fR \fIusers\fR ] [ \fB-w\fR \fIwidth\fR ]
+.SH DESCRIPTION
+Reports on problems in the sendmail queue. With no options this simply
+means listing messages that have been in the queue longer than a default
+period along with a summary of queue mail by host and status message.
+.SH OPTIONS
+.IP \fB-a\fR 14
+Report on all messages in the queue. This is equivalent to saying \fB-t\fR 0s.
+You may like this command so much that you use it as a replacement for
+\fBmqueue\fR. For example:
+.sp 1
+.RS
+.RS
+\fBalias mqueue cqueue -a\fR
+.RE
+.RE
+.IP \fB-b\fR 14
+Also report on bogus queue files. Those are files that
+have data files and no control files or vice versa.
+.IP \fB-d\fR
+Print a detailed report of mail messages that have been queued longer than
+the specified or default time. Information that is presented includes:
+.RS
+.RS
+.IB
+Sendmail queue identifier.
+.IB
+Date the message was first queued.
+.IB
+Sender of the message.
+.IB
+One or more recipients of the message.
+.IB
+An optional status of the message. This usually indicates why the message
+has not been delivered.
+.RE
+.RE
+.IP \fB-m\fR 14
+Mail off the results if any problems were found.
+Normaly results are printed to stdout. If this option
+is specified they are mailed to one or more users. Results
+are not printed to stdout in this case. Results are \fBonly\fR
+mailed if \*(mp found something wrong.
+.IP "\fB-q\fR \fIqueue-dir\fI"
+The sendmail mail queue directory. Default is \fB/usr/spool/mqueue\fR or
+some other site configured value.
+.IP "\fB-t\fR \fItime\fR"
+List messages that have been in the queue longer than
+\fItime\fR. Time should of the form:
+.sp 1
+.RS
+.RS
+(<number>(s|m|h|d))+
+.sp 1
+.RE
+.RE
+.RS 14
+The second portion of the above definition
+specifies seconds, minutes, hours, or
+days, respectfully. The first portion is the number of
+those units. There can be any number of such specifiers.
+As an example, 1h30m means 1 hour and 30 minutes.
+.sp 1
+The default is 2 hours.
+.RE
+.IP \fB-s\fR 14
+Print a summary of messages that have been queued longer than
+the specified or default time. Two separate types of summaries are printed.
+The first summarizes the queue messages by destination host. The host name
+is gleaned from the recipient addresses for each message.
+Thus the actual host names for this summary should be taken with a grain
+of salt since ruleset 0 has not been applied to the address the host was
+taken from nor were MX records consulted. It would be possible to add
+this; however, the execution time of the script would increase 
+dramatically. The second summary is by status message.
+.IP "\fB-u\fR \fIusers\fR"
+Specify list of users to send a mail report to other than
+the invoker. This option is only valid when \fB-m\fR has been
+specified. Multiple recipients may be separated by spaces.
+.IP "\fB-w\fR \fIwidth\fR"
+Specify the page width to which the output should tailored. \fIwidth\fR
+should be an integer representing some character position. The default is
+80 or some other site configured value. Output is folded neatly to match 
+\fIwidth\fR.
+.SH EXAMPLES
+.nf
+% \fBdate\fR
+Tue Jan 19 12:07:20 CST 1993
+X
+% \fBcqueue -t 21h45m -w 70\fR
+X
+Summary of messages in queue longer than 21:45:00 by destination 
+host:
+X
+X   Number of
+X   Messages    Destination Host
+X   ---------   ----------------
+X   2           cigseg.rtsg.mot.com
+X   1           mnesouth.corp.mot.com
+X   ---------
+X   3
+X
+Summary of messages in queue longer than 21:45:00 by status message:
+X
+X   Number of
+X   Messages    Status Message
+X   ---------   --------------
+X   1           Deferred: Connection refused by mnesouth.corp.mot.com
+X   2           Deferred: Host Name Lookup Failure
+X   ---------
+X   3
+X
+Detail of messages in queue longer than 21:45:00 sorted by creation 
+date:
+X
+X   ID:        AA20573
+X   Date:      02:09:27 PM 01/18/93
+X   Sender:    melrose-place-owner@ferkel.ucsb.edu
+X   Recipient: pbaker@cigseg.rtsg.mot.com
+X   Status:    Deferred: Host Name Lookup Failure
+X
+X   ID:        AA20757
+X   Date:      02:11:30 PM 01/18/93
+X   Sender:    90210-owner@ferkel.ucsb.edu
+X   Recipient: pbaker@cigseg.rtsg.mot.com
+X   Status:    Deferred: Host Name Lookup Failure
+X
+X   ID:        AA21110
+X   Date:      02:17:01 PM 01/18/93
+X   Sender:    rd_lap_wg@mdd.comm.mot.com
+X   Recipient: jim_mathis@mnesouth.corp.mot.com
+X   Status:    Deferred: Connection refused by mnesouth.corp.mot.com
+.fi
+.SH AUTHOR
+.nf
+Michael S. Muegel (mmuegel@mot.com)
+UNIX Applications Startup Group
+Corporate Information Office, Schaumburg, IL
+Motorola, Inc.
+.fi
+.SH COPYRIGHT NOTICE
+Copyright 1993, Motorola, Inc.
+.sp 1
+Permission to use, copy, modify and distribute without charge this
+software, documentation, etc. is granted, provided that this
+comment and the author's name is retained.  The author nor Motorola assume any
+responsibility for problems resulting from the use of this software.
+.SH SEE ALSO
+.nf
+\fBsendmail(8)\fR
+\fISendmail Installation and Operation Guide\fR.
+.fi
+SHAR_EOF
+chmod 0444 man/cqueue.1 ||
+echo 'restore of man/cqueue.1 failed'
+Wc_c="`wc -c < 'man/cqueue.1'`"
+test 5229 -eq "$Wc_c" ||
+       echo 'man/cqueue.1: original size 5229, current size' "$Wc_c"
+fi
+# ============= man/postclip.1 ==============
+if test -f 'man/postclip.1' -a X"$1" != X"-c"; then
+       echo 'x - skipping man/postclip.1 (File already exists)'
+else
+echo 'x - extracting man/postclip.1 (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'man/postclip.1' &&
+.TH POSTCLIP 1L
+\"
+\" $Author: glass $
+\" $Header: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v 1.2 1993/06/28 22:33:06 glass Exp $
+\"
+.ds mp \fBpostclip\fR
+.SH NAME
+\*(mp - send only the headers to Postmaster
+.SH SYNOPSIS
+\*(mp [ \fB-v\fR ] [ \fIto\fR ... ]
+.SH DESCRIPTION
+\*(mp  will forward non-delivery reports to a postmaster after deleting the body
+of the message. This keeps bounced mail private and helps to avoid disk space problems. \*(mp tries its best to keep as much of the header trail as possible.
+Hopefully only the original body of the message will be filtered. Only messages
+that have a subject that begins with 'Returned mail:' are filtered. This
+ensures that other mail is not accidently mucked with. Finally, note that
+\fBsendmail\fR is used to deliver the message after it has been (possibly)
+filtered. All of the original headers will remain intact.
+.sp 1 
+You can use this with any \fBsendmail\fR by modifying the Postmaster alias.
+If you use IDA \fBsendmail\fR you could add the following to <machine>.m4:
+.sp 1
+.RS
+define(POSTMASTERBOUNCE, mailer-errors)
+.RE
+.sp 1
+In the aliases file, add a line similar to the following:
+.sp 1
+.RS
+mailer-errors: "|/usr/local/bin/postclip postmaster"
+.RE
+.SH OPTIONS
+.IP \fB-v\fR
+Be verbose about delivery. Probably only useful when debugging \*(mp.
+.IP \fIto\fR
+A list of one or more e-mail ids to send the modified
+Postmaster messages to. If none are specified postmaster
+is used.
+.SH AUTHOR
+.nf
+Michael S. Muegel (mmuegel@mot.com)
+UNIX Applications Startup Group
+Corporate Information Office, Schaumburg, IL
+Motorola, Inc.
+.fi
+.SH CREDITS
+The original idea to filter Postmaster mail was taken from a script by 
+Christopher Davis <ckd@eff.org>.
+.SH COPYRIGHT NOTICE
+Copyright 1992, Motorola, Inc.
+.sp 1
+Permission to use, copy, modify and distribute without charge this
+software, documentation, etc. is granted, provided that this
+comment and the author's name is retained.  The author nor Motorola assume any
+responsibility for problems resulting from the use of this software.
+.SH SEE ALSO
+.nf
+\fBsendmail(8)\fR
+.fi
+SHAR_EOF
+chmod 0444 man/postclip.1 ||
+echo 'restore of man/postclip.1 failed'
+Wc_c="`wc -c < 'man/postclip.1'`"
+test 2097 -eq "$Wc_c" ||
+       echo 'man/postclip.1: original size 2097, current size' "$Wc_c"
+fi
+# ============= src/cqueue ==============
+if test ! -d 'src'; then
+    echo 'x - creating directory src'
+    mkdir 'src'
+fi
+if test -f 'src/cqueue' -a X"$1" != X"-c"; then
+       echo 'x - skipping src/cqueue (File already exists)'
+else
+echo 'x - extracting src/cqueue (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'src/cqueue' &&
+#!/usr/local/ustart/bin/suidperl
+X
+# NAME
+#    cqueue - check sendmail queue for problems
+#
+# SYNOPSIS
+#    Type cqueue -usage
+#
+# AUTHOR
+#    Michael S. Muegel <mmuegel@mot.com>
+#
+# RCS INFORMATION
+#    $Author: glass $
+#    $Header: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v 1.2 1993/06/28 22:33:06 glass Exp $
+X
+# So that date.pl does not yell (Domain/OS version does a ``)
+$ENV{'PATH'}    = "";
+X
+# A better getopts routine
+require "newgetopts.pl";
+require "timespec.pl";
+require "mail.pl";
+require "date.pl";
+require "mqueue.pl";
+require "strings1.pl";
+require "elapsed.pl";
+X
+($Script_Name = $0) =~ s/.*\///;
+X         
+# Some defaults you may want to change
+$DEF_TIME      = "2h";
+$DEF_QUEUE      = "/usr/spool/mqueue";
+$DEF_COLUMNS   = 80;
+$DATE_FORMAT    = "%r %D";
+X
+# Constants that probably should not be changed
+$USAGE          = "Usage: $Script_Name [ -abdms ] [ -q queue-dir ] [ -t time ] [ -u user ] [ -w width ]\n";
+$VERSION        = "${Script_Name} by \$Author: glass $; \$Revision: 1.2 $ of \$Date: 1993/06/28 22:33:06 $";
+$SWITCHES       = "abdmst:u:q:w:";
+$SPLIT_EXPR    = '\s,\.@!%:';
+$ADDR_PART_EXPR        = '[^!@%]+';
+X
+# Let getopts parse for switches
+$Status = &New_Getopts ($SWITCHES, $USAGE);
+exit (0) if ($Status == -1);
+exit (1) if (! $Status);
+X
+# Check args 
+die "${Script_Name}: -u only valid with -m\n" if (($opt_u) && (! $opt_m));
+die "${Script_Name}: -a not valid with -t option\n" if ($opt_a && $opt_t);
+$opt_u = getlogin || (getpwuid ($<))[0] || $ENV{"USER"} || die "${Script_Name}: can not determine who you are!\n" if (! $opt_u);
+X
+# Set defaults
+$opt_t = "0s" if ($opt_a);
+$opt_t = $DEF_TIME if ($opt_t eq "");
+$opt_w = $DEF_COLUMNS if ($opt_w eq "");
+$opt_q = $DEF_QUEUE if ($opt_q eq "");
+$opt_s = $opt_d = 1 if (! ($opt_s || $opt_d));
+X
+# Untaint the users to mail to
+$opt_u =~ /^(.*)$/;
+$Users = $1;
+X
+# Convert time option to seconds and seconds to elapsed form
+die "${Script_Name}: $Msg\n" if (! (($Status, $Msg, $Seconds) = &Time_Spec_To_Seconds ($opt_t))[0]);
+$Elapsed = &Seconds_To_Elapsed ($Seconds, 1);
+$Time_Info = " longer than $Elapsed" if ($Seconds);
+X
+# Get the current time
+$Current_Time = time;
+$Current_Date = &date ($Current_Time, $DATE_FORMAT);
+X
+($Status, $Msg, @Queue_IDs) = &Get_Queue_IDs ($opt_q, 1, @Missing_Control_IDs,
+X   @Missing_Data_IDs);
+die "$Script_Name: $Msg\n" if (! $Status);
+X
+# Yell about missing data/control files?
+if ($opt_b)
+{
+X
+X   $Report = "\nMessages missing control files:\n\n   " . 
+X             join ("\n   ", @Missing_Control_IDs) . 
+X             "\n" 
+X      if (@Missing_Control_IDs);
+X
+X   $Report .= "\nMessages missing data files:\n\n   " . 
+X              join ("\n   ", @Missing_Data_IDs) . 
+X              "\n"
+X      if (@Missing_Data_IDs);
+};
+X
+# See if any mail messages are older than $Seconds
+foreach $Queue_ID (@Queue_IDs)
+{
+X   # Get lots of info about this sendmail message via the control file
+X   ($Status, $Msg) = &Parse_Control_File ($opt_q, $Queue_ID, *Sender, 
+X      *Recipients, *Errors_To, *Creation_Time, *Priority, *Status_Message, 
+X      *Headers);
+X   next if ($Status == -1);
+X   if (! $Status)
+X   {
+X      warn "$Script_Name: $Queue_ID: $Msg\n";
+X      next;
+X   };
+X
+X   # Report on message if it is older than $Seconds
+X   if ($Current_Time - $Creation_Time >= $Seconds)
+X   {
+X      # Build summary by host information. Keep track of each host destination
+X      # encountered.
+X      if ($opt_s)
+X      {
+X         %Host_Map = ();
+X         foreach (@Recipients)
+X         {
+X          if ((/@($ADDR_PART_EXPR)$/) || (/($ADDR_PART_EXPR)!$ADDR_PART_EXPR$/))
+X            {
+X             ($Host = $1) =~ tr/A-Z/a-z/;
+X               $Host_Map {$Host} = 1;
+X          }
+X          else
+X          {
+X             warn "$Script_Name: could not find host part from $_; contact author\n";
+X          };
+X         };
+X
+X         # For each unique target host add to its stats
+X         grep ($Host_Queued {$_}++, keys (%Host_Map));
+X
+X         # Build summary by message information.
+X         $Message_Queued {$Status_Message}++ if ($Status_Message);
+X      };
+X
+X      # Build long report information for this creation time (there may be
+X      # more than one message created at the same time)
+X      if ($opt_d)
+X      {
+X         $Creation_Date = &date ($Creation_Time, $DATE_FORMAT);
+X         $Recipient_Info = &Format_Text_Block (join (", ", @Recipients), 
+X          "   Recipient: ", 1, 0, $opt_w, $SPLIT_EXPR);
+X         $Time_To_Report {$Creation_Time} .= <<"EOS";
+X
+X   ID:        $Queue_ID
+X   Date:      $Creation_Date
+X   Sender:    $Sender
+$Recipient_Info
+EOS
+X
+X         # Add the status message if available to long report
+X         if ($Status_Message)
+X         {
+X          $Time_To_Report {$Creation_Time} .= &Format_Text_Block ($Status_Message, 
+X             "   Status:    ", 1, 0, $opt_w, $SPLIT_EXPR) . "\n";
+X         };
+X      };
+X   };
+X
+};
+X
+# Add the summary report by target host?
+if ($opt_s)
+{
+X   foreach $Host (sort (keys (%Host_Queued)))
+X   {
+X      $Host_Report .= &Format_Text_Block ($Host, 
+X         sprintf ("   %-9d   ", $Host_Queued{$Host}), 1, 0, $opt_w,
+X         $SPLIT_EXPR) . "\n";
+X      $Num_Hosts += $Host_Queued{$Host};
+X   };
+X   if ($Host_Report)
+X   {
+X      chop ($Host_Report);
+X      $Report .= &Format_Text_Block("\nSummary of messages in queue$Time_Info by destination host:\n", "", 0, 0, $opt_w);
+X
+X      $Report .= <<"EOS";
+X
+X   Number of
+X   Messages    Destination Host
+X   ---------   ----------------
+$Host_Report
+X   ---------
+X   $Num_Hosts
+EOS
+X   };
+};
+X
+# Add the summary by message report?
+if ($opt_s)
+{
+X   foreach $Message (sort (keys (%Message_Queued)))
+X   {
+X      $Message_Report .= &Format_Text_Block ($Message, 
+X         sprintf ("   %-9d   ", $Message_Queued{$Message}), 1, 0, $opt_w, 
+X         $SPLIT_EXPR) . "\n";
+X      $Num_Messages += $Message_Queued{$Message};
+X   };
+X   if ($Message_Report)
+X   {
+X      chop ($Message_Report);
+X      $Report .= &Format_Text_Block ("\nSummary of messages in queue$Time_Info by status message:\n", "", 0, 0, $opt_w);
+X
+X      $Report .= <<"EOS";
+X
+X   Number of
+X   Messages    Status Message
+X   ---------   --------------
+$Message_Report
+X   ---------
+X   $Num_Messages
+EOS
+X   };
+};
+X
+# Add the detailed message reports?
+if ($opt_d)
+{
+X   foreach $Time (sort { $a <=> $b} (keys (%Time_To_Report)))
+X   {
+X      $Report .= &Format_Text_Block ("\nDetail of messages in queue$Time_Info sorted by creation date:\n","", 0, 0, $opt_w) if (! $Detailed_Header++);
+X      $Report .= $Time_To_Report {$Time};
+X   };
+};
+X
+# Now mail or print the report
+if ($Report)
+{
+X   $Report .= "\n";
+X   if ($opt_m)
+X   {
+X      ($Status, $Msg) = &Send_Mail ($Users, "sendmail queue report for $Current_Date", $Report, 0);
+X      die "${Script_Name}: $Msg" if (! $Status);
+X   }
+X
+X   else
+X   {
+X      print $Report;
+X   };
+X
+};
+X
+# I am outta here...
+exit (0);
+SHAR_EOF
+chmod 0555 src/cqueue ||
+echo 'restore of src/cqueue failed'
+Wc_c="`wc -c < 'src/cqueue'`"
+test 6702 -eq "$Wc_c" ||
+       echo 'src/cqueue: original size 6702, current size' "$Wc_c"
+fi
+# ============= src/postclip ==============
+if test -f 'src/postclip' -a X"$1" != X"-c"; then
+       echo 'x - skipping src/postclip (File already exists)'
+else
+echo 'x - extracting src/postclip (Text)'
+sed 's/^X//' << 'SHAR_EOF' > 'src/postclip' &&
+#!/usr/local/bin/perl
+X
+# NAME
+#    postclip - send only the headers to Postmaster
+#
+# SYNOPSIS
+#    postclip [ -v ] [ to ... ]
+#
+# AUTHOR
+#    Michael S. Muegel <mmuegel@mot.com>
+#
+# RCS INFORMATION
+#    $Source: /b/source/CVS/src/usr.sbin/sendmail/contrib/mmuegel,v $
+#    $Revision: 1.2 $ of $Date: 1993/06/28 22:33:06 $
+X
+# We use this to send off the mail
+require "newgetopts.pl";
+require "mail.pl";
+X
+# Get the basename of the script
+($Script_Name = $0) =~ s/.*\///;
+X
+# Some famous constants
+$USAGE          = "Usage: $Script_Name [ -v ] [ to ... ]\n";
+$VERSION        = "${Script_Name} by \$Author: glass $; \$Revision: 1.2 $ of \$Date: 1993/06/28 22:33:06 $";
+$SWITCHES       = "v";
+X
+# Let getopts parse for switches
+$Status = &New_Getopts ($SWITCHES, $USAGE);
+exit (0) if ($Status == -1);
+exit (1) if (! $Status);
+X
+# Who should we send the modified mail to?
+@ARGV = ("postmaster") if (! @ARGV);
+$Users = join (" ", @ARGV);
+@ARGV = ();
+X
+# Suck in the original header and save a few interesting lines
+while (<>) 
+{
+X    $Buffer .= $_ if (! /^From /);
+X    $Subject = $1 if (/^Subject:\s+(.*)$/);
+X    $From = $1 if (/^From:\s+(.*)$/);
+X    last if (/^$/);
+};
+X
+# Do not filter the message unless it has a subject and the subject indicates
+# it is an NDN
+if ($Subject && ($Subject =~ /^returned mail/i))
+{
+X   # Slurp input by paragraph. Keep track of the last time we saw what
+X   # appeared to be NDN text. We keep this.
+X   $/ = "\n\n";
+X   $* = 1;
+X   while (<>)
+X   {
+X      push (@Paragraphs, $_);
+X      $Last_Error_Para = $#Paragraphs 
+X       if (/unsent message follows/i || /was not delivered because/);
+X   };
+X
+X   # Now save the NDN text into $Buffer
+X   $Buffer .= join ("", @Paragraphs [0..$Last_Error_Para]);
+}
+X
+else
+{
+X   undef $/;
+X   $Buffer .= <>;
+};
+X
+# Send off the (possibly) modified mail
+($Status, $Msg) = &Send_Mail ($Users, "", $Buffer, 0, $opt_v, 1);
+die "$Script_Name: $Msg\n" if (! $Status);
+SHAR_EOF
+chmod 0555 src/postclip ||
+echo 'restore of src/postclip failed'
+Wc_c="`wc -c < 'src/postclip'`"
+test 1900 -eq "$Wc_c" ||
+       echo 'src/postclip: original size 1900, current size' "$Wc_c"
+fi
+exit 0
+
+--
++----------------------------------------------------------------------------+
+| Michael S. Muegel                    | Internet E-Mail:    mmuegel@mot.com |
+| UNIX Applications Startup Group      | Moto Dist E-Mail:   X10090          |
+| Corporate Information Office         | Voice:              (708) 576-0507  |
+| Motorola                             | Fax:                (708) 576-4153  |
++----------------------------------------------------------------------------+
diff --git a/usr.sbin/sendmail/contrib/rcpt-streaming b/usr.sbin/sendmail/contrib/rcpt-streaming
new file mode 100644 (file)
index 0000000..329a978
--- /dev/null
@@ -0,0 +1,297 @@
+(Message /home/auspex/a/staff/eric/.mh/inbox:2575)
+From:    John Gardiner Myers <jgm+@cmu.edu>
+Subject: contrib/rcpt-streaming
+Date:    Fri,  4 Jun 1993 13:54:06 -0400 (EDT)
+To:      sendmail@cs.berkeley.edu
+
+This patch implements "RCPT streaming" in sendmail version 6.  This
+patch is not an official part of sendmail.  Please report all problems
+with this patch to jgm+@cmu.edu.
+
+RCPT streming avoids network round trips by sending all RCPT commands
+for a single SMTP transaction together.  Sendmail then waits for all
+the replies, matching them up with the apropriate addresses.
+
+Apply to the sendmail src directory (your line numbers may vary) and
+compile with -DRCPTSTREAM
+
+diff -cr src.orig/deliver.c src/deliver.c
+*** src.orig/deliver.c Thu May 27 14:38:22 1993
+--- src/deliver.c      Fri Jun  4 13:50:02 1993
+***************
+*** 1325,1330 ****
+--- 1325,1345 ----
+                       register int i;
+  
+                       /* send the recipient list */
++ #ifdef RCPTSTREAM
++ /***********************************************************************
++  *
++  * RCPT streaming code by John G Myers, jgm+@cmu.edu
++  * This is not supported by the maintainer of sendmail.
++  * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
++  *
++  ***********************************************************************
++  */
++                      for (to = tochain; to != NULL; to = to->q_tchain)
++                      {
++                              smtpstreammessage("RCPT To:<%s>", m, mci,
++                                                to->q_user);
++                      }
++ #endif
+                       tobuf[0] = '\0';
+                       for (to = tochain; to != NULL; to = to->q_tchain)
+                       {
+diff -cr src.orig/usersmtp.c src/usersmtp.c
+*** src.orig/usersmtp.c        Thu May 27 14:38:09 1993
+--- src/usersmtp.c     Fri Jun  4 13:48:24 1993
+***************
+*** 44,49 ****
+--- 44,61 ----
+  
+  # include <sysexits.h>
+  # include <errno.h>
++ #ifdef RCPTSTREAM
++ /***********************************************************************
++  *
++  * RCPT streaming code by John G Myers, jgm+@cmu.edu
++  * This is not supported by the maintainer of sendmail.
++  * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
++  *
++  ***********************************************************************
++  */
++ # include <sys/types.h>
++ # include <sys/time.h>
++ #endif
+  
+  # ifdef SMTP
+  
+***************
+*** 62,67 ****
+--- 74,87 ----
+  char SmtpError[MAXLINE] = "";        /* save failure error messages */
+  int  SmtpPid;                        /* pid of mailer */
+  
++ #ifdef RCPTSTREAM
++ char *SmtpStreamBuf;                 /* buffer for streaming output */
++ int  SmtpStreamBufSize = 0;          /* allocated size of buffer */
++ char *SmtpStreamStart;               /* pointer to text not yet written */
++ int  SmtpStreamLen = 0;              /* # chars not yet written */
++ #endif
++ 
++ 
+  #ifdef __STDC__
+  extern       smtpmessage(char *f, MAILER *m, MCI *mci, ...);
+  #endif
+***************
+*** 404,410 ****
+--- 424,432 ----
+  {
+       register int r;
+  
++ #ifndef RCPTSTREAM
+       smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
++ #endif
+  
+       SmtpPhase = mci->mci_phase = "RCPT wait";
+       setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+***************
+*** 626,631 ****
+--- 648,657 ----
+       bool firstline = TRUE;
+       char junkbuf[MAXLINE];
+  
++ #ifdef RCPTSTREAM
++      extern char MsgBuf[];           /* err.c */
++ #endif
++ 
+       if (mci->mci_out != NULL)
+               (void) fflush(mci->mci_out);
+  
+***************
+*** 641,646 ****
+--- 667,709 ----
+               register char *p;
+               extern time_t curtime();
+  
++ #ifdef RCPTSTREAM
++              if (SmtpStreamLen > 0) {
++                  int outfd;
++ 
++                  outfd = fileno(mci->mci_out);
++ 
++                  nonblock(outfd, TRUE);
++                  r = write(outfd, SmtpStreamStart, SmtpStreamLen);
++                  nonblock(outfd, FALSE);
++                  if (r == -1 && errno != EAGAIN
++ #ifdef EWOULDBLOCK
++                      && errno != EWOULDBLOCK
++ #endif
++                      ) {
++ 
++                      mci->mci_errno = errno;
++                      message("451 streamreply: write error to %s",
++                              mci->mci_host);
++ 
++                      /* if debugging, pause so we can see state */
++                      if (tTd(18, 100))
++                        pause();
++ # ifdef LOG
++                      if (LogLevel > 0)
++                        syslog(LOG_INFO, "%s", &MsgBuf[4]);
++ # endif /* LOG */
++                      /* stop trying to write output */
++                      SmtpStreamLen = 0;
++                      continue;
++                  }
++                  if (r > 0) {
++                      SmtpStreamStart += r;
++                      SmtpStreamLen -= r;
++                  }
++              }
++ #endif /* RCPTSTREAM */
++ 
+               /* actually do the read */
+               if (e->e_xfp != NULL)
+                       (void) fflush(e->e_xfp);        /* for debugging */
+***************
+*** 742,747 ****
+--- 805,880 ----
+  
+       return (r);
+  }
++ \f
++ #ifdef RCPTSTREAM
++ /*
++ **  SMTPSTREAMMESSAGE -- buffer message to be streamed to server
++ **
++ **   Parameters:
++ **           f -- format
++ **           m -- the mailer to control formatting.
++ **           a, b, c -- parameters
++ **
++ **   Returns:
++ **           none.
++ **
++ **   Side Effects:
++ **           stores message in SmtpStreamBuf
++ */
++ 
++ /*VARARGS1*/
++ #ifdef __STDC__
++ smtpstreammessage(char *f, MAILER *m, MCI *mci, ...)
++ #else
++ smtpstreammessage(f, m, mci, va_alist)
++      char *f;
++      MAILER *m;
++      MCI *mci;
++      va_dcl
++ #endif
++ {
++      VA_LOCAL_DECL
++      int len;
++ 
++      VA_START(mci);
++      (void) vsprintf(SmtpMsgBuffer, f, ap);
++      VA_END;
++ 
++      if (tTd(18, 1) || Verbose)
++              nmessage(">>> %s", SmtpMsgBuffer);
++ 
++      if (mci->mci_out == NULL) {
++          if (tTd(18, 1)) printf("smtpstreammessage: NULL mci_out\n");
++          return;
++      }
++ 
++      strcat(SmtpMsgBuffer, m == NULL ? "\r\n" : m->m_eol);
++      len = strlen(SmtpMsgBuffer);
++ 
++      if (SmtpStreamLen == 0) {
++          if (SmtpStreamBufSize == 0) {
++              SmtpStreamBufSize = MAXLINE;
++              SmtpStreamBuf = xalloc(SmtpStreamBufSize);
++          }
++          SmtpStreamStart = SmtpStreamBuf;
++      }
++ 
++      if (SmtpStreamBufSize - SmtpStreamLen < len + 1) {
++          int start = SmtpStreamStart - SmtpStreamBuf;
++          SmtpStreamBufSize += MAXLINE;
++          SmtpStreamBuf = realloc(SmtpStreamBuf, SmtpStreamBufSize);
++          if (!SmtpStreamBuf) {
++              syserr("Out of memory!!");
++              abort();
++              /* exit(EX_UNAVAILABLE); */
++          }
++          SmtpStreamStart = SmtpStreamBuf + start;
++      }
++ 
++      strcpy(SmtpStreamBuf + SmtpStreamLen, SmtpMsgBuffer);
++      SmtpStreamLen += len;
++ }
++ #endif /* RCPTSTREAM */
+  \f/*
+  **  SMTPMESSAGE -- send message to server
+  **
+Only in src: usersmtp.c.orig
+Only in src: usersmtp.c~
+Only in src: usersmtp.o
+diff -cr src.orig/util.c src/util.c
+*** src.orig/util.c    Thu May 27 14:38:20 1993
+--- src/util.c Wed Jun  2 16:39:15 1993
+***************
+*** 955,960 ****
+--- 955,1004 ----
+                       return (FALSE);
+       return (TRUE);
+  }
++ \f
++ #ifdef RCPTSTREAM
++ /***********************************************************************
++  *
++  * RCPT streaming code by John G Myers, jgm+@cmu.edu
++  * This is not supported by the maintainer of sendmail.
++  * Report all bugs concerning RCPT streaming to jgm+@cmu.edu
++  *
++  ***********************************************************************
++  */
++ 
++ #include <fcntl.h>
++ 
++ /*
++ **  NONBLOCK -- set or clear non-blocking mode on file descriptor
++ **
++ **   Parameters:
++ **           fd -- the file descriptor
++ **           mode -- TRUE to set non-blocking mode
++ **                   FALSE to clear non-blocking mode
++ **
++ **   Returns:
++ **           none
++ **
++ **   Side Effects:
++ **           modifies nonblocking status of fd
++ */
++ 
++ nonblock(fd, mode)
++ int fd;
++ bool mode;
++ {
++     int flags;
++ 
++     flags = fcntl(fd, F_GETFL, 0);
++     if (mode) {
++      flags |= FNONBIO;
++     }
++     else {
++      flags &= ~FNONBIO;
++     }
++     fcntl(fd, F_SETFL, flags);
++ }
++ #endif
+  \f/*
+  **  STRCONTAINEDIN -- tell if one string is contained in another
+  **
+Only in src: util.c.orig
+Only in src: util.o
+Only in src: version.o
diff --git a/usr.sbin/sendmail/contrib/xla/README b/usr.sbin/sendmail/contrib/xla/README
new file mode 100644 (file)
index 0000000..a72fd03
--- /dev/null
@@ -0,0 +1,207 @@
+         XLA - Extended Load Average design for Sendmail R6
+         --------------------------------------------------
+
+          Christophe Wolfhugel - Herve Schauer Consultants
+              wolf@grasp.insa-lyon.fr, wolf@hsc-sec.fr
+
+
+WARNING:  this extension is supplied as a contribution to Sendmail.
+Should you have trouble, questions, please contact me directly, and
+*not* the Sendmail development team.
+
+
+ABSTRACT
+
+Sendmail currently furnishes a limitation mecanism which is based on
+the system load average, when available.  Experience has prooven that
+this was not sufficiant for some particular situations, for example
+if you have slow and/or overloaded links. This can easily cause both
+system and network congestions with Sendmail having to handle a large
+number of simultaneous sessions on the same overloaded link, causing
+most of the SMTP sessions to timeout after a long time.  The system
+load average is also generally too slow to react when your system
+gets a burst of incoming or outgoing SMTP sessions which on some
+stations can easily cause system unavailabilities.
+
+The extended load average module has been designed in order to furnish
+a way of limitation the load generated by Sendmail to both your
+system and your network. This design can be used either alone or as
+complementary to the system load average if your system supports it.
+
+Limitation is based on the number of incoming/outgoing SMTP sessions,
+and remote hosts are classified in classes. The system administrator
+will define a maximum number of incoming SMTP sessions as well as
+a maximum total (incoming + outgoing) sessions for each class of
+hosts. A class can be either an individual machine or a network.
+
+When the limit is reached for a given class, all incoming SMTP
+connections will be politely refused. When the limit is reached for
+all classes, the SMTP connections will be refused by the system
+(which one could consider as less politely :)).
+On outgoing mail, messages will be queued for delayed processing.
+
+The extended load average parameters are given in the Sendmail
+configuration file, and when not present, Sendmail behaves the
+usual way.
+
+
+COMPILATION
+
+Copy the xla.c module in the src sub-directory, edit the Makefile
+in order to define XLA (-DXLA). Also add the xla.[co] module name
+in the list of files so that it gets compiled.
+
+Regenerate sendmail by removing all objects, or at least those
+containing references to XLA (this list may vary, so use grep to
+get the module list).  This will generate a new sendmail executable
+containing the xla code.
+
+Debugging level 59 has been assigned to this module and when used
+it provides some output (sendmail -d59.x).  Please check the source
+code to see which levels are supported.
+
+
+CONFIGURATION
+
+The extended average uses a new set of configuration lines in the
+sendmail.cf file.  All newly introduced line begin with the letter L
+(capital L).
+
+Before detailling the syntax, first an example (this can be placed
+at any section of the sendmail.cf file, note that the order is
+important). Fields are separated by (one or more) tabs/spaces.
+
+# File name used to store the counters
+L/etc/sendmail.la
+# Classes definition
+# Lname            #queue #reject
+L*.insa-lyon.fr         8       3
+L*.univ-lyon1.fr        6       4
+L*                     15      16
+
+The first line defines the working file which will be used in order
+to have the occurences of Sendmail read and update the counters. The
+format of this file is described in the "Design" section.
+This line is mandatory and the specified file must be absolute (ie
+begin with a slash).
+
+Then you can specify one or more classes. The last class (*) is also
+mandatory and should be in last position as the first match will stop
+the search and if there is no match the behavior of Sendmail is unknown.
+
+Each class has three fields separated by one or more tabs/spaces.
+
+L{mask}         {queue_#}      {refuse_#}
+
+The {mask} is a simple mask. It can be either an explicit host name
+(like grasp.insa-lyon.fr) or a mask starting with "*." or just "*".
+No other variants are allowed.
+
+Lgrasp.insa-lyon.fr  will match exactely any session to/from this host.
+
+L*.insa-lyon.fr      will match any session to/from any machine in the
+                     insa-lyon.fr domain as well as from the machine
+                     named "insa-lyon.fr" if it exists.
+
+L*                   will match any session, and thus should also be
+                     last in the list to act as a catchup line.
+
+The {queue_#} is the maximum number of SMTP sessions in the given class
+for both incoming and outgoing messages. The {refuse_#} indicates when
+to refuse incoming messages for this class. The interaction between
+those counters is somewhat subtle. It seems logical that a standard
+configuration has {queue_#} >= {refuse_#}, and in fact in most
+configurations they can be equal (that's why what I use in my environment).
+Thus, this is not mandatory. If {queue_#} < {refuse_#} outgoing messages
+will be lower priority than incoming messages and once a class gets loaded
+the outgoing messages are blocked first.
+
+I use very low values in some situations, for example I have a customer
+connected to the Internet via a 9600 bps line, they also have internal
+users sending burst of messages (10, 20 small messages coming in just
+one or two seconds).  Both situations were unsupportable. The line is
+too slow to handle many simultaneous connections and the mail server
+does not have the ressources to handle such a heavy load (it's a 12 Megs
+Sun 3 also doing Usenet news).
+
+I have defined following section in the configuration file, and experience
+shows the benefits for everyone. Fake domain for the example: customer.fr.
+
+L/etc/sendmail.la
+L*.customer.fr          8       8
+L*                      3       3
+
+This means that there might not be more than 8 simultaneous SMTP sessions
+between the mail server and any other internal host. This is to protect
+the station from heavy loads like users (or applications !) sending
+several tenths of messages in just a few seconds).
+No more than 3 SMTP sessions are authorized with any other host, this is
+to save the load of the slow 9600 line to the Internet.
+
+Drawback is that is you have 3 * 2 Megs sessions established from/to the
+outside, all your mail will be held until one slot gets available, on
+a 9600 bps line just make your counts, il blocks your line during over
+one hour.
+
+
+DESIGN
+
+Sendmail will analyze the "L" lines in the configuration file during
+startup (or read the initialized structure from the frozen file).
+When started in daemon mode (and only there), any existing working file
+will be cleared and a new one is created. Each class gets a record in
+the sendmail.la work file. The size of this record is a short integer
+(generally two bytes) and represents the count of active sessions in
+the given class.  Read/Write operations in this file are done in
+one operation (as anyway the size is far below one disk sector). The
+file is locked with Sendmail's lockfile() function priori to any
+access.
+
+Handling incoming SMTP sessions.
+
+There is interaction is two points in the Sendmail source code. First
+on the listen system call: if all slots in all classes are in use,
+a listen(0) is done so that the system rejects any incoming SMTP session.
+This avois to fork and then reject the connexion.
+
+If there are some free slots, nothing better than accepting the
+connection, then forking can be done. The child process then checks if
+the adequate class is full or not. If full, it rejects the connection
+with a "421 Too many sessions" diagnostic to the sender (which should
+then appear when the remote users do a mailq). If the treshold {reject_#}
+is not reached, the connection is accepted and the counter is sendmail.la
+is updated.
+
+Handling outgoing SMTP sessions.
+
+As soon as Sendmail needs to connect to a distant host, the adequate class
+is checked against {queue_#} and if no slots are available, the message is
+queued for further processing.
+
+Sendmail's connection caching.
+
+Sendmail-R6 introduces a new design: connection caching, ie several SMTP
+sessions can be opened at the same time.  This could cause some problems
+when sending mail, as after having a few connections opened, all slots
+could be in use and generate a partial delivery of the message.  In
+order to deal with this, xla.c uses following design "for a given
+sendmail process, only the first connection in a given class is counted".
+This can be done because sendmail does not do parralel message sending
+on the different channels.
+
+End of connection.
+
+As soon as a connection is closed, the counters will be automatically
+updated.
+
+
+
+Please look at the code to understand of all this works. Comments,
+suggestions, questions welcome.
+
+
+
+                                        Christophe Wolfhugel
+                                        Herve Schauer Consultants
+                                        Paris, France
+                                        May 23, 1993
diff --git a/usr.sbin/sendmail/contrib/xla/xla.c b/usr.sbin/sendmail/contrib/xla/xla.c
new file mode 100644 (file)
index 0000000..1b3c308
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * (C) Copyright 1993, Herve Schauer Consultants
+ *
+ * This module written by Christophe.Wolfhugel@hsc-sec.fr
+ * is to be used under the same conditions and terms (and absence
+ * or warranties) than the other modules of the Sendmail package.
+ *
+ * ABSOLUTELY NO WARRANTY. USE AT YOUR OWN RISKS.
+ *
+ */
+
+
+#ifdef XLA
+
+#ifndef MAXLARULES
+# define MAXLARULES    20
+#endif
+
+# include "sendmail.h"
+
+typedef struct {
+               short   queue;          /* # of connexions to have queueing */
+               short   reject;         /* # of conn. to reject */
+               short   num;            /* # of increments this process */
+               char    *mask;          /* Mask (domain) */
+        } XLARULE;
+
+char   *XlaFname;                      /* Work file name */
+char   XlaHostName[1024];              /* Temporary */
+int    XlaNext;                        /* # of XlaRules */
+pid_t  XlaPid;                         /* Pid updating the tables */
+XLARULE        XlaRules[MAXLARULES];           /* The rules themselves */
+short   XlaCtr[MAXLARULES];            /* Counter (for work file only) */
+
+extern bool    lockfile();
+
+/*
+** XLAMATCH -- Matches a fnmatch like expression.
+**
+**     Parameters:
+**             mask -- mask to match the string too;
+**             name -- string.
+**
+** Mask can either be a plain string or a simplified fnmatch like mask:
+**     *.string     or  string.*
+** No other alternatives are accepted.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             none.
+*/
+
+bool
+XlaMatch(mask, name)
+       char *mask, *name;
+{
+       int l1, l2;
+
+       l1 = strlen(mask);  l2 = strlen(name);
+       if (l1 == 1 && mask[0] == '*') return(TRUE);
+       if (mask[0] == '*' && mask[1] == '.') {
+               if (l2 < (l1 - 2)) return(FALSE);
+               if (strcasecmp(&mask[2], name) == 0) return(TRUE);
+               if (strcasecmp(&mask[1], name + l2 - l1 + 1) == 0) return(TRUE);
+               return(FALSE);
+       }
+       if (l1 < 3) return(FALSE);
+       if (mask[l1 -1] == '*') {
+               if (l2 < l1 - 1) return(FALSE);
+               if (strncasecmp(mask, name, l1 - 1) == 0) return(TRUE);
+               return(FALSE);
+       }
+       if (strcasecmp(mask, name) == 0) return(TRUE);
+       return(FALSE);
+}
+
+/*
+** XLAZERO -- Zeroes the used variables
+**
+**     Just initializes some variables, called once at sendmail
+**     startup.
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             none.
+*/
+
+xla_zero()
+{
+       if (tTd(59, 1)) {
+               printf("xla_zero\n");
+       }
+       XlaFname = NULL;
+       XlaNext  = 0;
+       XlaPid   = 0;
+       memset(&XlaRules[0], 0, sizeof(XLARULE) * MAXLARULES);
+}
+
+
+/*
+**  XLAINIT -- initialized extended load average stuff
+**
+**  This routine handles the L lines appearing in the configuration
+**  file.
+**
+**  L/etc/sendmail.la     indicates the working file
+**  Lmask   #1   #2      Xtended LA to apply to mask
+**     #1 = Queueing # of connections
+**     #2 = Reject connections.
+**
+**     Parameters:
+**             line -- the cf file line to parse.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Builds several internal tables.
+*/
+
+xla_init(line)
+       char *line;
+{
+       char *s;
+
+       if (tTd(59, 1)) {
+               printf("xla_init line: %s\n", line);
+       }
+       if (XlaFname == NULL && *line == '/') { /* Work file name */
+                XlaFname = newstr(line);
+               if (tTd(59, 10))
+                       printf("xla_init: fname = %s\n", XlaFname);
+               return;
+       }
+       if (XlaNext == MAXLARULES) {
+               syserr("too many xla rules defined (%d max)", MAXLARULES);
+               return;
+       }
+       s = strtok(line, " \t");
+       if (s == NULL) {
+               syserr("xla: line unparseable");
+               return;
+       }
+       XlaRules[XlaNext].mask = newstr(s);
+       s = strtok(NULL, " \t");
+       if (s == NULL) {
+               syserr("xla: line unparseable");
+               return;
+       }
+       XlaRules[XlaNext].queue = atoi(s);
+       s = strtok(NULL, " \t");
+       if (s == NULL) {
+               syserr("xla: line unparseable");
+               return;
+       }
+       XlaRules[XlaNext].reject = atoi(s);
+       if (tTd(59, 10))
+               printf("xla_init: rule #%d = %s q=%d r=%d\n", XlaNext, 
+                       XlaRules[XlaNext].mask,
+                       XlaRules[XlaNext].queue, XlaRules[XlaNext].reject);
+       XlaNext++;
+}
+
+
+/*
+**  XLACREATEFILE -- Create the working file
+**
+**     Tries to create the working file, called each time sendmail is
+**     invoked with the -bd option.
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Creates the working file (sendmail.la) and zeroes it.
+*/
+
+xla_create_file()
+{
+       int     fd, i;
+
+       if (tTd(59, 1))
+               printf("xla_create_file:\n");
+       if (XlaFname == NULL) return;
+       fd = open(XlaFname, O_RDWR|O_CREAT, 0644);
+       if (fd == -1) {
+               XlaFname = NULL;
+               syserr("xla_create_file: open failed");
+               return;
+       }
+       if (!lockfile(fd, XlaFname, LOCK_EX)) {
+               close(fd);
+               XlaFname = NULL;
+               syserr("xla_create_file: can't set lock");
+               return;
+       }
+       if (ftruncate(fd, 0) == -1) {
+               close(fd);
+               XlaFname = NULL;
+               syserr("xla_create_file: can't truncate XlaFname");
+               return;
+       }
+       if (write(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
+               XlaFname == NULL;
+               syserr("xla_create_file: can't write XlaFname");
+       }
+       close(fd);
+}
+
+
+/*
+**  XLASMTPOK -- Checks if all slots are in use
+**
+**     Check is there are still some slots available for an SMTP
+**     connection.
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             TRUE -- slots are available;
+**             FALSE -- no more slots.
+**
+**     Side Effects:
+**             Reads a file, uses a lock and updates sendmail.la if a slot
+**             is free for use.
+*/
+
+bool
+xla_smtp_ok()
+{
+       int     fd, i;
+
+       if (tTd(59, 1))
+               printf("xla_smtp_ok:\n");
+       if (XlaFname == NULL) return(TRUE);
+       fd = open(XlaFname, O_RDWR, 0644);
+       if (fd == -1) {
+               XlaFname = NULL;
+               syserr("xla_smtp_ok: open failed");
+               return(TRUE);
+       }
+       if (!lockfile(fd, XlaFname, LOCK_EX)) {
+               close(fd);
+               XlaFname = NULL;
+               syserr("xla_smtp_ok: can't set lock");
+               return(TRUE);
+       }
+       if (read(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
+               close(fd);
+                XlaFname = NULL;
+                syserr("xla_smtp_ok: can't read XlaFname");
+                return(TRUE);
+       }
+       close(fd);
+       for (i = 0; i < XlaNext; i++) {
+               if (XlaCtr[i] < XlaRules[i].reject)
+                       return(TRUE);
+       }
+       return(FALSE);
+}
+
+
+/*
+**  XLAHOSTOK -- Can we accept a connection from this host
+**
+**     Check the quota for the indicated host
+**
+**     Parameters:
+**             name -- host name or IP# (string)
+**
+**     Returns:
+**             TRUE -- we can accept the connection;
+**             FALSE -- we must refuse the connection.1
+**
+**     Side Effects:
+**             Reads and writes a file, uses a lock and still updates
+**             sendmail.la is a slot gets assigned.
+*/
+
+bool
+xla_host_ok(name)
+       char *name;
+{
+       int     fd, i;
+
+       if (tTd(59, 1))
+               printf("xla_host_ok:\n");
+       if (XlaFname == NULL) return(TRUE);
+       fd = open(XlaFname, O_RDWR, 0644);
+       if (fd == -1) {
+               XlaFname = NULL;
+               syserr("xla_host_ok: open failed");
+               return(TRUE);
+       }
+       XlaPid = getpid();
+       if (!lockfile(fd, XlaFname, LOCK_EX)) {
+               close(fd);
+               XlaFname = NULL;
+               syserr("xla_host_ok: can't set lock");
+               return(TRUE);
+       }
+       if (read(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
+               close(fd);
+                XlaFname = NULL;
+                syserr("xla_smtp_ok: can't read XlaFname");
+                return(TRUE);
+       }
+       strncpy(XlaHostName, name, sizeof(XlaHostName) -1);
+       XlaHostName[sizeof(XlaHostName) -1] = 0;
+       i = strlen(name) - 1;
+       if (i >= 0 && XlaHostName[i] == '.') XlaHostName[i] = 0;
+       for (i = 0; i < XlaNext; i++) {
+               if (XlaMatch(XlaRules[i].mask, XlaHostName)) {
+                       if (XlaCtr[i] < XlaRules[i].reject) {
+                               if (XlaRules[i].num++ == 0) {
+                                       XlaCtr[i]++;
+                                       lseek(fd, i*sizeof(XlaCtr[i]), SEEK_SET);
+                                       if (write(fd, &XlaCtr[i], sizeof(XlaCtr[i])) !=  sizeof(XlaCtr[i]))
+                                               XlaFname = NULL;
+                               }
+                               close(fd);
+                               return(TRUE);
+                       }
+                       close(fd);
+                       return(FALSE);
+               }
+       }
+       close(fd);
+       return(TRUE);
+}
+
+/*
+**  XLANOQUEUEOK -- Can we sent this message to the remote host
+**
+**     Check if we can send to the remote host
+**
+**     Parameters:
+**             name -- host name or IP# (string)
+**
+**     Returns:
+**             TRUE -- we can send the message to the remote site;
+**             FALSE -- we can't connect the remote host, queue.
+**
+**     Side Effects:
+**             Reads and writes a file, uses a lock.
+**             And still updates the sendmail.la file.
+*/
+
+bool
+xla_noqueue_ok(name)
+       char *name;
+{
+       int     fd, i;
+
+       if (tTd(59, 1))
+               printf("xla_noqueue_ok:\n");
+        if (XlaFname == NULL) return(TRUE);
+       fd = open(XlaFname, O_RDWR, 0644);
+       if (fd == -1) {
+               XlaFname = NULL;
+               syserr("xla_noqueue_ok: open failed");
+               return(TRUE);
+       }
+       if (!lockfile(fd, XlaFname, LOCK_EX)) {
+               close(fd);
+               XlaFname = NULL;
+               syserr("xla_noqueue_ok: can't set lock");
+               return(TRUE);
+       }
+       XlaPid = getpid();
+        if (read(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
+                close(fd);
+                XlaFname = NULL;
+                syserr("xla_noqueue_ok: can't read XlaFname");
+                return(TRUE);
+        }
+       strncpy(XlaHostName, name, sizeof(XlaHostName) -1);
+       XlaHostName[sizeof(XlaHostName) -1] = 0;
+       i = strlen(name) - 1;
+       if (i >= 0 && XlaHostName[i] == '.') XlaHostName[i] = 0;
+       for (i = 0; i < XlaNext; i++) {
+               if (XlaMatch(XlaRules[i].mask, XlaHostName)) {
+                       if (XlaCtr[i] < XlaRules[i].queue) {
+                               if (XlaRules[i].num++ == 0) {
+                                       XlaCtr[i]++;
+                                       lseek(fd, i*sizeof(XlaCtr[i]), SEEK_SET);
+                                       if (write(fd, &XlaCtr[i], sizeof(XlaCtr[i])) !=  sizeof(XlaCtr[i]))
+                                               XlaFname = NULL;
+                               }
+                               close(fd);
+                               return(TRUE);
+                       }
+                       close(fd);
+                       return(FALSE);
+               }
+       }
+       close(fd);
+       return(TRUE);
+}
+
+
+/*
+**  XLAHOSTEND -- Notice that a connection is terminated.
+**
+**     Updates the counters to reflect the end of an SMTP session
+**     (in or outgoing).
+**
+**     Parameters:
+**             name -- host name or IP# (string)
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Reads and writes a file, uses a lock.
+**             And still updates sendmail.la.
+*/
+
+xla_host_end(name)
+       char    *name;
+{
+       int     fd, i;
+
+       if (tTd(59, 1))
+               printf("xla_host_end:\n");
+       if (XlaFname == NULL || XlaPid != getpid()) return;
+       fd = open(XlaFname, O_RDWR, 0644);
+       if (fd == -1) {
+               XlaFname = NULL;
+               syserr("xla_host_end: open failed");
+               return;
+       }
+       if (!lockfile(fd, XlaFname, LOCK_EX)) {
+                close(fd);
+                XlaFname = NULL;
+               syserr("xla_host_end: can't set lock");
+               return;
+       }
+        if (read(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
+                close(fd);
+                XlaFname = NULL;
+                syserr("xla_host_end: can't read XlaFname");
+                return(TRUE);
+       }
+       strncpy(XlaHostName, name, sizeof(XlaHostName) -1);
+       XlaHostName[sizeof(XlaHostName) -1] = 0;
+       i = strlen(name) - 1;
+       if (i >= 0 && XlaHostName[i] == '.') XlaHostName[i] = 0;
+       for (i = 0; i < XlaNext; i++) {
+               if (XlaMatch(XlaRules[i].mask, XlaHostName)) {
+                       if (XlaRules[i].num > 0 && XlaRules[i].num-- == 1) {
+                               if (XlaCtr[i]) XlaCtr[i]--;
+                                lseek(fd, i*sizeof(XlaCtr[i]), SEEK_SET);
+                                if (write(fd, &XlaCtr[i], sizeof(XlaCtr[i]))
+                                        !=  sizeof(XlaCtr[i]))
+                                        XlaFname = NULL;
+                       }
+                       close(fd);
+                       return;
+               }
+       }
+       close(fd);
+}
+
+/*
+**  XLAALLEND -- Mark all connections as closed.
+**
+**     Generally due to an emergency exit.
+**
+**     Parameters:
+**             name -- host name or IP# (string)
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Reads and writes a file, uses a lock.
+**             And guess what: updates sendmail.la.
+*/
+
+xla_all_end()
+{
+       int     fd, i;
+
+       if (tTd(59, 1))
+               printf("xla_all_end:\n");
+       if (XlaFname == NULL || XlaPid != getpid()) return;
+       fd = open(XlaFname, O_RDWR, 0644);
+        if (fd == -1) {
+                XlaFname = NULL;
+               syserr("xla_all_end: open failed");
+                return;
+        }
+        if (!lockfile(fd, XlaFname, LOCK_EX)) {
+                close(fd);
+                XlaFname = NULL;
+                syserr("xla_all_end: can't set lock");
+                return;
+        }
+        if (read(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
+                close(fd);
+                XlaFname = NULL;
+                syserr("xla_all_end: can't read XlaFname");
+                return(TRUE);
+        }
+       for (i = 0; i < XlaNext; i++) {
+               if (XlaCtr[i] > 0 && XlaRules[i].num > 0) {
+                       XlaCtr[i]--; XlaRules[i].num = 0;
+               }
+       }
+       lseek(fd, 0, SEEK_SET);
+       if (write(fd, XlaCtr, sizeof(XlaCtr)) != sizeof(XlaCtr)) {
+               XlaFname = NULL;
+       }
+       close(fd);
+}
+#endif /* XLA */
diff --git a/usr.sbin/sendmail/doc/intro/intro.me b/usr.sbin/sendmail/doc/intro/intro.me
new file mode 100644 (file)
index 0000000..5907004
--- /dev/null
@@ -0,0 +1,1478 @@
+.\" Copyright (c) 1983 Eric P. Allman
+.\" Copyright (c) 1988, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)intro.me    8.1 (Berkeley) 6/8/93
+.\"
+.\"    pic -Pxx intro.me | ditroff -me -Pxx
+.eh 'SMM:9-%''SENDMAIL \*- An Internetwork Mail Router'
+.oh 'SENDMAIL \*- An Internetwork Mail Router''SMM:9-%'
+.nr si 3n
+.if n .ls 2
+.+c
+.(l C
+.sz 14
+SENDMAIL \*- An Internetwork Mail Router
+.sz
+.sp
+Eric Allman\(dg
+.sp 0.5
+.i
+University of California, Berkeley
+Mammoth Project
+.)l
+.sp
+.(l F
+.ce
+ABSTRACT
+.sp \n(psu
+Routing mail through a heterogenous internet presents many new
+problems.  Among the worst of these is that of address mapping.
+Historically, this has been handled on an
+.i "ad hoc"
+basis.  However,
+this approach has become unmanageable as internets grow.
+.sp \n(psu
+Sendmail acts a unified "post office" to which all mail can be
+submitted.  Address interpretation is controlled by a production
+system, which can parse both domain-based addressing and old-style
+.i "ad hoc"
+addresses.
+The production system is powerful
+enough to rewrite addresses in the message header to conform to the
+standards of a number of common target networks, including old
+(NCP/RFC733) Arpanet, new (TCP/RFC822) Arpanet, UUCP, and Phonenet.
+Sendmail also implements an SMTP server, message
+queueing, and aliasing.
+.)l
+.sp 2
+.(f
+\(dgA considerable part of this work
+was done while under the employ
+of the INGRES Project
+at the University of California at Berkeley
+and at Britton Lee.
+.)f
+.pp
+.i Sendmail
+implements a general internetwork mail routing facility,
+featuring aliasing and forwarding,
+automatic routing to network gateways,
+and flexible configuration.
+.pp
+In a simple network,
+each node has an address,
+and resources can be identified
+with a host-resource pair;
+in particular,
+the mail system can refer to users
+using a host-username pair.
+Host names and numbers have to be administered by a central authority,
+but usernames can be assigned locally to each host.
+.pp
+In an internet,
+multiple networks with different characterstics
+and managements
+must communicate.
+In particular,
+the syntax and semantics of resource identification change.
+Certain special cases can be handled trivially
+by
+.i "ad hoc"
+techniques,
+such as
+providing network names that appear local to hosts
+on other networks,
+as with the Ethernet at Xerox PARC.
+However,  the general case is extremely complex.
+For example,
+some networks require point-to-point routing,
+which simplifies the database update problem
+since only adjacent hosts must be entered
+into the system tables,
+while others use end-to-end addressing.
+Some networks use a left-associative syntax
+and others use a right-associative syntax,
+causing ambiguity in mixed addresses.
+.pp
+Internet standards seek to eliminate these problems.
+Initially, these proposed expanding the address pairs
+to address triples,
+consisting of
+{network, host, resource}
+triples.
+Network numbers must be universally agreed upon,
+and hosts can be assigned locally
+on each network.
+The user-level presentation was quickly expanded
+to address domains,
+comprised of a local resource identification
+and a hierarchical domain specification
+with a common static root.
+The domain technique
+separates the issue of physical versus logical addressing.
+For example,
+an address of the form
+.q "eric@a.cc.berkeley.arpa"
+describes only the logical
+organization of the address space.
+.pp
+.i Sendmail
+is intended to help bridge the gap
+between the totally
+.i "ad hoc"
+world
+of networks that know nothing of each other
+and the clean, tightly-coupled world
+of unique network numbers.
+It can accept old arbitrary address syntaxes,
+resolving ambiguities using heuristics
+specified by the system administrator,
+as well as domain-based addressing.
+It helps guide the conversion of message formats
+between disparate networks.
+In short,
+.i sendmail
+is designed to assist a graceful transition
+to consistent internetwork addressing schemes.
+.sp
+.pp
+Section 1 discusses the design goals for
+.i sendmail .
+Section 2 gives an overview of the basic functions of the system.
+In section 3,
+details of usage are discussed.
+Section 4 compares
+.i sendmail
+to other internet mail routers,
+and an evaluation of
+.i sendmail
+is given in section 5,
+including future plans.
+.sh 1 "DESIGN GOALS"
+.pp
+Design goals for
+.i sendmail
+include:
+.np
+Compatibility with the existing mail programs,
+including Bell version 6 mail,
+Bell version 7 mail
+[UNIX83],
+Berkeley
+.i Mail
+[Shoens79],
+BerkNet mail
+[Schmidt79],
+and hopefully UUCP mail
+[Nowitz78a, Nowitz78b].
+ARPANET mail
+[Crocker77a, Postel77]
+was also required.
+.np
+Reliability, in the sense of guaranteeing
+that every message is correctly delivered
+or at least brought to the attention of a human
+for correct disposal;
+no message should ever be completely lost.
+This goal was considered essential
+because of the emphasis on mail in our environment.
+It has turned out to be one of the hardest goals to satisfy,
+especially in the face of the many anomalous message formats
+produced by various ARPANET sites.
+For example,
+certain sites generate improperly formated addresses,
+occasionally
+causing error-message loops.
+Some hosts use blanks in names,
+causing problems with
+UNIX mail programs that assume that an address
+is one word.
+The semantics of some fields
+are interpreted slightly differently
+by different sites.
+In summary,
+the obscure features of the ARPANET mail protocol
+really
+.i are
+used and
+are difficult to support,
+but must be supported.
+.np
+Existing software to do actual delivery
+should be used whenever possible.
+This goal derives as much from political and practical considerations
+as technical.
+.np
+Easy expansion to
+fairly complex environments,
+including multiple
+connections to a single network type
+(such as with multiple UUCP or Ether nets
+[Metcalfe76]).
+This goal requires consideration of the contents of an address
+as well as its syntax
+in order to determine which gateway to use.
+For example,
+the ARPANET is bringing up the
+TCP protocol to replace the old NCP protocol.
+No host at Berkeley runs both TCP and NCP,
+so it is necessary to look at the ARPANET host name
+to determine whether to route mail to an NCP gateway
+or a TCP gateway.
+.np
+Configuration should not be compiled into the code.
+A single compiled program should be able to run as is at any site
+(barring such basic changes as the CPU type or the operating system).
+We have found this seemingly unimportant goal
+to be critical in real life.
+Besides the simple problems that occur when any program gets recompiled
+in a different environment,
+many sites like to
+.q fiddle
+with anything that they will be recompiling anyway.
+.np
+.i Sendmail
+must be able to let various groups maintain their own mailing lists,
+and let individuals specify their own forwarding,
+without modifying the system alias file.
+.np
+Each user should be able to specify which mailer to execute
+to process mail being delivered for him.
+This feature allows users who are using specialized mailers
+that use a different format to build their environment
+without changing the system,
+and facilitates specialized functions
+(such as returning an
+.q "I am on vacation"
+message).
+.np
+Network traffic should be minimized
+by batching addresses to a single host where possible,
+without assistance from the user.
+.pp
+These goals motivated the architecture illustrated in figure 1.
+.(z
+.hl
+.ie t \
+\{\
+.ie !"\*(.T"" \
+\{\
+.PS
+boxht = 0.5i
+boxwid = 1.0i
+
+       down
+S:     [
+               right
+       S1:     box "sender1"
+               move
+               box "sender2"
+               move
+       S3:     box "sender3"
+       ]
+       arrow
+SM:    box "sendmail" wid 2i ht boxht
+       arrow
+M:     [
+               right
+       M1:     box "mailer1"
+               move
+               box "mailer2"
+               move
+       M3:     box "mailer3"
+       ]
+
+       arrow from S.S1.s to 1/2 between SM.nw and SM.n
+       arrow from S.S3.s to 1/2 between SM.n and SM.ne
+
+       arrow from 1/2 between SM.sw and SM.s to M.M1.n
+       arrow from 1/2 between SM.s and SM.se to M.M3.n
+.PE
+.\}
+.el \
+.      sp 18
+.\}
+.el \{\
+.(c
++---------+   +---------+   +---------+
+| sender1 |   | sender2 |   | sender3 |
++---------+   +---------+   +---------+
+     |            |             |
+     +----------+  +  +----------+
+               |  |  |
+               v  v  v
+            +-------------+
+            |   sendmail  |
+            +-------------+
+               |  |  |
+     +----------+  +  +----------+
+     |            |             |
+     v             v             v
++---------+   +---------+   +---------+
+| mailer1 |   | mailer2 |   | mailer3 |
++---------+   +---------+   +---------+
+.)c
+.\}
+
+.ce
+Figure 1 \*- Sendmail System Structure.
+.hl
+.)z
+The user interacts with a mail generating and sending program.
+When the mail is created,
+the generator calls
+.i sendmail ,
+which routes the message to the correct mailer(s).
+Since some of the senders may be network servers
+and some of the mailers may be network clients,
+.i sendmail
+may be used as an internet mail gateway.
+.sh 1 "OVERVIEW"
+.sh 2 "System Organization"
+.pp
+.i Sendmail
+neither interfaces with the user
+nor does actual mail delivery.
+Rather,
+it collects a message
+generated by a user interface program (UIP)
+such as Berkeley
+.i Mail ,
+MS
+[Crocker77b],
+or MH
+[Borden79],
+edits the message as required by the destination network,
+and calls appropriate mailers
+to do mail delivery or queueing for network transmission\**.
+.(f
+\**except when mailing to a file,
+when
+.i sendmail
+does the delivery directly.
+.)f
+This discipline allows the insertion of new mailers
+at minimum cost.
+In this sense 
+.i sendmail
+resembles the Message Processing Module (MPM)
+of [Postel79b].
+.sh 2 "Interfaces to the Outside World"
+.pp
+There are three ways
+.i sendmail
+can communicate with the outside world,
+both in receiving and in sending mail.
+These are using the conventional UNIX
+argument vector/return status,
+speaking SMTP over a pair of UNIX pipes,
+and speaking SMTP over an interprocess(or) channel.
+.sh 3 "Argument vector/exit status"
+.pp
+This technique is the standard UNIX method
+for communicating with the process.
+A list of recipients is sent in the argument vector,
+and the message body is sent on the standard input.
+Anything that the mailer prints
+is simply collected and sent back to the sender
+if there were any problems.
+The exit status from the mailer is collected
+after the message is sent,
+and a diagnostic is printed if appropriate.
+.sh 3 "SMTP over pipes"
+.pp
+The SMTP protocol
+[Postel82]
+can be used to run an interactive lock-step interface
+with the mailer.
+A subprocess is still created,
+but no recipient addresses are passed to the mailer
+via the argument list.
+Instead, they are passed one at a time
+in commands sent to the processes standard input.
+Anything appearing on the standard output
+must be a reply code
+in a special format.
+.sh 3 "SMTP over an IPC connection"
+.pp
+This technique is similar to the previous technique,
+except that it uses a 4.2bsd IPC channel
+[UNIX83].
+This method is exceptionally flexible
+in that the mailer need not reside
+on the same machine.
+It is normally used to connect to a sendmail process
+on another machine.
+.sh 2 "Operational Description"
+.pp
+When a sender wants to send a message,
+it issues a request to
+.i sendmail
+using one of the three methods described above.
+.i Sendmail
+operates in two distinct phases.
+In the first phase,
+it collects and stores the message.
+In the second phase,
+message delivery occurs.
+If there were errors during processing
+during the second phase,
+.i sendmail
+creates and returns a new message describing the error
+and/or returns an status code
+telling what went wrong.
+.sh 3 "Argument processing and address parsing"
+.pp
+If
+.i sendmail
+is called using one of the two subprocess techniques,
+the arguments
+are first scanned
+and option specifications are processed.
+Recipient addresses are then collected,
+either from the command line
+or from the SMTP
+RCPT command,
+and a list of recipients is created.
+Aliases are expanded at this step,
+including mailing lists.
+As much validation as possible of the addresses
+is done at this step:
+syntax is checked, and local addresses are verified,
+but detailed checking of host names and addresses
+is deferred until delivery.
+Forwarding is also performed
+as the local addresses are verified.
+.pp
+.i Sendmail
+appends each address
+to the recipient list after parsing.
+When a name is aliased or forwarded,
+the old name is retained in the list,
+and a flag is set that tells the delivery phase
+to ignore this recipient.
+This list is kept free from duplicates,
+preventing alias loops
+and duplicate messages deliverd to the same recipient,
+as might occur if a person is in two groups.
+.sh 3 "Message collection"
+.pp
+.i Sendmail
+then collects the message.
+The message should have a header at the beginning.
+No formatting requirements are imposed on the message
+except that they must be lines of text
+(i.e., binary data is not allowed).
+The header is parsed and stored in memory,
+and the body of the message is saved
+in a temporary file.
+.pp
+To simplify the program interface,
+the message is collected even if no addresses were valid.
+The message will be returned with an error.
+.sh 3 "Message delivery"
+.pp
+For each unique mailer and host in the recipient list,
+.i sendmail
+calls the appropriate mailer.
+Each mailer invocation sends to all users receiving the message on one host.
+Mailers that only accept one recipient at a time
+are handled properly.
+.pp
+The message is sent to the mailer
+using one of the same three interfaces
+used to submit a message to sendmail.
+Each copy of the message is
+prepended by a customized header.
+The mailer status code is caught and checked,
+and a suitable error message given as appropriate.
+The exit code must conform to a system standard
+or a generic message
+(\c
+.q "Service unavailable" )
+is given.
+.sh 3 "Queueing for retransmission"
+.pp
+If the mailer returned an status that
+indicated that it might be able to handle the mail later,
+.i sendmail
+will queue the mail and try again later.
+.sh 3 "Return to sender"
+.pp
+If errors occur during processing,
+.i sendmail
+returns the message to the sender for retransmission.
+The letter can be mailed back
+or written in the file
+.q dead.letter
+in the sender's home directory\**.
+.(f
+\**Obviously, if the site giving the error is not the originating
+site, the only reasonable option is to mail back to the sender.
+Also, there are many more error disposition options,
+but they only effect the error message \*- the
+.q "return to sender"
+function is always handled in one of these two ways.
+.)f
+.sh 2 "Message Header Editing"
+.pp
+Certain editing of the message header
+occurs automatically.
+Header lines can be inserted
+under control of the configuration file.
+Some lines can be merged;
+for example,
+a
+.q From:
+line and a
+.q Full-name:
+line can be merged under certain circumstances.
+.sh 2 "Configuration File"
+.pp
+Almost all configuration information is read at runtime
+from an ASCII file,
+encoding
+macro definitions
+(defining the value of macros used internally),
+header declarations
+(telling sendmail the format of header lines that it will process specially,
+i.e., lines that it will add or reformat),
+mailer definitions
+(giving information such as the location and characteristics
+of each mailer),
+and address rewriting rules
+(a limited production system to rewrite addresses
+which is used to parse and rewrite the addresses).
+.pp
+To improve performance when reading the configuration file,
+a memory image can be provided.
+This provides a
+.q compiled
+form of the configuration file.
+.sh 1 "USAGE AND IMPLEMENTATION"
+.sh 2 "Arguments"
+.pp
+Arguments may be flags and addresses.
+Flags set various processing options.
+Following flag arguments,
+address arguments may be given,
+unless we are running in SMTP mode.
+Addresses follow the syntax in RFC822
+[Crocker82]
+for ARPANET
+address formats.
+In brief, the format is:
+.np
+Anything in parentheses is thrown away
+(as a comment).
+.np
+Anything in angle brackets (\c
+.q "<\|>" )
+is preferred
+over anything else.
+This rule implements the ARPANET standard that addresses of the form
+.(b
+user name <machine-address>
+.)b
+will send to the electronic
+.q machine-address
+rather than the human
+.q "user name."
+.np
+Double quotes
+(\ "\ )
+quote phrases;
+backslashes quote characters.
+Backslashes are more powerful
+in that they will cause otherwise equivalent phrases
+to compare differently \*- for example,
+.i user
+and
+.i
+"user"
+.r
+are equivalent,
+but
+.i \euser
+is different from either of them.
+.pp
+Parentheses, angle brackets, and double quotes
+must be properly balanced and nested.
+The rewriting rules control remaining parsing\**.
+.(f
+\**Disclaimer: Some special processing is done
+after rewriting local names; see below.
+.)f
+.sh 2 "Mail to Files and Programs"
+.pp
+Files and programs are legitimate message recipients.
+Files provide archival storage of messages,
+useful for project administration and history.
+Programs are useful as recipients in a variety of situations,
+for example,
+to maintain a public repository of systems messages
+(such as the Berkeley
+.i msgs
+program,
+or the MARS system
+[Sattley78]).
+.pp
+Any address passing through the initial parsing algorithm
+as a local address
+(i.e, not appearing to be a valid address for another mailer)
+is scanned for two special cases.
+If prefixed by a vertical bar (\c
+.q \^|\^ )
+the rest of the address is processed as a shell command.
+If the user name begins with a slash mark (\c
+.q /\^ )
+the name is used as a file name,
+instead of a login name.
+.pp
+Files that have setuid or setgid bits set
+but no execute bits set
+have those bits honored if
+.i sendmail
+is running as root.
+.sh 2 "Aliasing, Forwarding, Inclusion"
+.pp
+.i Sendmail
+reroutes mail three ways.
+Aliasing applies system wide.
+Forwarding allows each user to reroute incoming mail
+destined for that account.
+Inclusion directs
+.i sendmail
+to read a file for a list of addresses,
+and is normally used
+in conjunction with aliasing.
+.sh 3 "Aliasing"
+.pp
+Aliasing maps names to address lists using a system-wide file.
+This file is indexed to speed access.
+Only names that parse as local
+are allowed as aliases;
+this guarantees a unique key
+(since there are no nicknames for the local host).
+.sh 3 "Forwarding"
+.pp
+After aliasing,
+recipients that are local and valid
+are checked for the existence of a
+.q .forward
+file in their home directory.
+If it exists,
+the message is
+.i not
+sent to that user,
+but rather to the list of users in that file.
+Often
+this list will contain only one address,
+and the feature will be used for network mail forwarding.
+.pp
+Forwarding also permits a user to specify a private incoming mailer.
+For example,
+forwarding to:
+.(b
+"\^|\|/usr/local/newmail myname"
+.)b
+will use a different incoming mailer.
+.sh 3 "Inclusion"
+.pp
+Inclusion is specified in RFC 733 [Crocker77a] syntax:
+.(b
+:Include: pathname
+.)b
+An address of this form reads the file specified by
+.i pathname
+and sends to all users listed in that file.
+.pp
+The intent is
+.i not
+to support direct use of this feature,
+but rather to use this as a subset of aliasing.
+For example,
+an alias of the form:
+.(b
+project: :include:/usr/project/userlist
+.)b
+is a method of letting a project maintain a mailing list
+without interaction with the system administration,
+even if the alias file is protected.
+.pp
+It is not necessary to rebuild the index on the alias database
+when a :include: list is changed.
+.sh 2 "Message Collection"
+.pp
+Once all recipient addresses are parsed and verified,
+the message is collected.
+The message comes in two parts:
+a message header and a message body,
+separated by a blank line.
+.pp
+The header is formatted as a series of lines
+of the form
+.(b
+       field-name: field-value
+.)b
+Field-value can be split across lines by starting the following
+lines with a space or a tab.
+Some header fields have special internal meaning,
+and have appropriate special processing.
+Other headers are simply passed through.
+Some header fields may be added automatically,
+such as time stamps.
+.pp
+The body is a series of text lines.
+It is completely uninterpreted and untouched,
+except that lines beginning with a dot
+have the dot doubled
+when transmitted over an SMTP channel.
+This extra dot is stripped by the receiver.
+.sh 2 "Message Delivery"
+.pp
+The send queue is ordered by receiving host
+before transmission
+to implement message batching.
+Each address is marked as it is sent
+so rescanning the list is safe.
+An argument list is built as the scan proceeds.
+Mail to files is detected during the scan of the send list.
+The interface to the mailer
+is performed using one of the techniques
+described in section 2.2.
+.pp
+After a connection is established,
+.i sendmail
+makes the per-mailer changes to the header
+and sends the result to the mailer.
+If any mail is rejected by the mailer,
+a flag is set to invoke the return-to-sender function
+after all delivery completes.
+.sh 2 "Queued Messages"
+.pp
+If the mailer returns a
+.q "temporary failure"
+exit status,
+the message is queued.
+A control file is used to describe the recipients to be sent to
+and various other parameters.
+This control file is formatted as a series of lines,
+each describing a sender,
+a recipient,
+the time of submission,
+or some other salient parameter of the message.
+The header of the message is stored
+in the control file,
+so that the associated data file in the queue
+is just the temporary file that was originally collected.
+.sh 2 "Configuration"
+.pp
+Configuration is controlled primarily by a configuration file
+read at startup.
+.i Sendmail
+should not need to be recomplied except
+.np
+To change operating systems
+(V6, V7/32V, 4BSD).
+.np
+To remove or insert the DBM
+(UNIX database)
+library.
+.np
+To change ARPANET reply codes.
+.np
+To add headers fields requiring special processing.
+.lp
+Adding mailers or changing parsing
+(i.e., rewriting)
+or routing information
+does not require recompilation.
+.pp
+If the mail is being sent by a local user,
+and the file
+.q .mailcf
+exists in the sender's home directory,
+that file is read as a configuration file
+after the system configuration file.
+The primary use of this feature is to add header lines.
+.pp
+The configuration file encodes macro definitions,
+header definitions,
+mailer definitions,
+rewriting rules,
+and options.
+.sh 3 Macros
+.pp
+Macros can be used in three ways.
+Certain macros transmit
+unstructured textual information
+into the mail system,
+such as the name
+.i sendmail
+will use to identify itself in error messages.
+Other macros transmit information from
+.i sendmail
+to the configuration file
+for use in creating other fields
+(such as argument vectors to mailers);
+e.g., the name of the sender,
+and the host and user
+of the recipient.
+Other macros are unused internally,
+and can be used as shorthand in the configuration file.
+.sh 3 "Header declarations"
+.pp
+Header declarations inform
+.i sendmail
+of the format of known header lines.
+Knowledge of a few header lines
+is built into
+.i sendmail ,
+such as the
+.q From:
+and
+.q Date:
+lines.
+.pp
+Most configured headers
+will be automatically inserted
+in the outgoing message
+if they don't exist in the incoming message.
+Certain headers are suppressed by some mailers.
+.sh 3 "Mailer declarations"
+.pp
+Mailer declarations tell
+.i sendmail
+of the various mailers available to it.
+The definition specifies the internal name of the mailer,
+the pathname of the program to call,
+some flags associated with the mailer,
+and an argument vector to be used on the call;
+this vector is macro-expanded before use.
+.sh 3 "Address rewriting rules"
+.pp
+The heart of address parsing in
+.i sendmail
+is a set of rewriting rules.
+These are an ordered list of pattern-replacement rules,
+(somewhat like a production system,
+except that order is critical),
+which are applied to each address.
+The address is rewritten textually until it is either rewritten
+into a special canonical form
+(i.e.,
+a (mailer, host, user)
+3-tuple,
+such as {arpanet, usc-isif, postel}
+representing the address
+.q "postel@usc-isif" ),
+or it falls off the end.
+When a pattern matches,
+the rule is reapplied until it fails.
+.pp
+The configuration file also supports the editing of addresses
+into different formats.
+For example,
+an address of the form:
+.(b
+ucsfcgl!tef
+.)b
+might be mapped into:
+.(b
+tef@ucsfcgl.UUCP
+.)b
+to conform to the domain syntax.
+Translations can also be done in the other direction.
+.sh 3 "Option setting"
+.pp
+There are several options that can be set
+from the configuration file.
+These include the pathnames of various support files,
+timeouts,
+default modes,
+etc.
+.sh 1 "COMPARISON WITH OTHER MAILERS"
+.sh 2 "Delivermail"
+.pp
+.i Sendmail
+is an outgrowth of
+.i delivermail .
+The primary differences are:
+.np
+Configuration information is not compiled in.
+This change simplifies many of the problems
+of moving to other machines.
+It also allows easy debugging of new mailers.
+.np
+Address parsing is more flexible.
+For example,
+.i delivermail
+only supported one gateway to any network,
+whereas
+.i sendmail
+can be sensitive to host names
+and reroute to different gateways.
+.np
+Forwarding and
+:include:
+features eliminate the requirement that the system alias file
+be writable by any user
+(or that an update program be written,
+or that the system administration make all changes).
+.np
+.i Sendmail
+supports message batching across networks
+when a message is being sent to multiple recipients.
+.np
+A mail queue is provided in
+.i sendmail.
+Mail that cannot be delivered immediately
+but can potentially be delivered later
+is stored in this queue for a later retry.
+The queue also provides a buffer against system crashes;
+after the message has been collected
+it may be reliably redelivered
+even if the system crashes during the initial delivery.
+.np
+.i Sendmail
+uses the networking support provided by 4.2BSD
+to provide a direct interface networks such as the ARPANET
+and/or Ethernet
+using SMTP (the Simple Mail Transfer Protocol)
+over a TCP/IP connection.
+.sh 2 "MMDF"
+.pp
+MMDF
+[Crocker79]
+spans a wider problem set than
+.i sendmail .
+For example,
+the domain of
+MMDF includes a
+.q "phone network"
+mailer, whereas
+.i sendmail
+calls on preexisting mailers in most cases.
+.pp
+MMDF and
+.i sendmail
+both support aliasing,
+customized mailers,
+message batching,
+automatic forwarding to gateways,
+queueing,
+and retransmission.
+MMDF supports two-stage timeout,
+which
+.i sendmail
+does not support.
+.pp
+The configuration for MMDF
+is compiled into the code\**.
+.(f
+\**Dynamic configuration tables are currently being considered
+for MMDF;
+allowing the installer to select either compiled
+or dynamic tables.
+.)f
+.pp
+Since MMDF does not consider backwards compatibility
+as a design goal,
+the address parsing is simpler but much less flexible.
+.pp
+It is somewhat harder to integrate a new channel\**
+.(f
+\**The MMDF equivalent of a
+.i sendmail
+.q mailer.
+.)f
+into MMDF.
+In particular,
+MMDF must know the location and format
+of host tables for all channels,
+and the channel must speak a special protocol.
+This allows MMDF to do additional verification
+(such as verifying host names)
+at submission time.
+.pp
+MMDF strictly separates the submission and delivery phases.
+Although
+.i sendmail
+has the concept of each of these stages,
+they are integrated into one program,
+whereas in MMDF they are split into two programs.
+.sh 2 "Message Processing Module"
+.pp
+The Message Processing Module (MPM)
+discussed by Postel [Postel79b]
+matches
+.i sendmail
+closely in terms of its basic architecture.
+However,
+like MMDF,
+the MPM includes the network interface software
+as part of its domain.
+.pp
+MPM also postulates a duplex channel to the receiver,
+as does MMDF,
+thus allowing simpler handling of errors
+by the mailer
+than is possible in
+.i sendmail .
+When a message queued by
+.i sendmail
+is sent,
+any errors must be returned to the sender
+by the mailer itself.
+Both MPM and MMDF mailers
+can return an immediate error response,
+and a single error processor can create an appropriate response.
+.pp
+MPM prefers passing the message as a structured object,
+with type-length-value tuples\**.
+.(f
+\**This is similar to the NBS standard.
+.)f
+Such a convention requires a much higher degree of cooperation
+between mailers than is required by
+.i sendmail .
+MPM also assumes a universally agreed upon internet name space
+(with each address in the form of a net-host-user tuple),
+which
+.i sendmail
+does not.
+.sh 1 "EVALUATIONS AND FUTURE PLANS"
+.pp
+.i Sendmail
+is designed to work in a nonhomogeneous environment.
+Every attempt is made to avoid imposing unnecessary constraints
+on the underlying mailers.
+This goal has driven much of the design.
+One of the major problems
+has been the lack of a uniform address space,
+as postulated in [Postel79a]
+and [Postel79b].
+.pp
+A nonuniform address space implies that a path will be specified
+in all addresses,
+either explicitly (as part of the address)
+or implicitly
+(as with implied forwarding to gateways).
+This restriction has the unpleasant effect of making replying to messages
+exceedingly difficult,
+since there is no one
+.q address
+for any person,
+but only a way to get there from wherever you are.
+.pp
+Interfacing to mail programs
+that were not initially intended to be applied
+in an internet environment
+has been amazingly successful,
+and has reduced the job to a manageable task.
+.pp
+.i Sendmail
+has knowledge of a few difficult environments
+built in.
+It generates ARPANET FTP/SMTP compatible error messages
+(prepended with three-digit numbers
+[Neigus73, Postel74, Postel82])
+as necessary,
+optionally generates UNIX-style
+.q From
+lines on the front of messages for some mailers,
+and knows how to parse the same lines on input.
+Also,
+error handling has an option customized for BerkNet.
+.pp
+The decision to avoid doing any type of delivery where possible
+(even, or perhaps especially, local delivery)
+has turned out to be a good idea.
+Even with local delivery,
+there are issues of the location of the mailbox,
+the format of the mailbox,
+the locking protocol used,
+etc.,
+that are best decided by other programs.
+One surprisingly major annoyance in many internet mailers
+is that the location and format of local mail is built in.
+The feeling seems to be that local mail is so common
+that it should be efficient.
+This feeling is not born out by
+our experience;
+on the contrary,
+the location and format of mailboxes seems to vary widely
+from system to system.
+.pp
+The ability to automatically generate a response to incoming mail
+(by forwarding mail to a program)
+seems useful
+(\c
+.q "I am on vacation until late August...." )
+but can create problems
+such as forwarding loops
+(two people on vacation whose programs send notes back and forth,
+for instance)
+if these programs are not well written.
+A program could be written to do standard tasks correctly,
+but this would solve the general case.
+.pp
+It might be desirable to implement some form of load limiting.
+I am unaware of any mail system that addresses this problem,
+nor am I aware of any reasonable solution at this time.
+.pp
+The configuration file is currently practically inscrutable;
+considerable convenience could be realized
+with a higher-level format.
+.pp
+It seems clear that common protocols will be changing soon
+to accommodate changing requirements and environments.
+These changes will include modifications to the message header
+(e.g., [NBS80])
+or to the body of the message itself
+(such as for multimedia messages
+[Postel80]).
+Experience indicates that
+these changes should be relatively trivial to integrate
+into the existing system.
+.pp
+In tightly coupled environments,
+it would be nice to have a name server
+such as Grapvine
+[Birrell82]
+integrated into the mail system.
+This would allow a site such as
+.q Berkeley
+to appear as a single host,
+rather than as a collection of hosts,
+and would allow people to move transparently among machines
+without having to change their addresses.
+Such a facility
+would require an automatically updated database
+and some method of resolving conflicts.
+Ideally this would be effective even without
+all hosts being under
+a single management.
+However,
+it is not clear whether this feature
+should be integrated into the
+aliasing facility
+or should be considered a
+.q "value added"
+feature outside
+.i sendmail
+itself.
+.pp
+As a more interesting case,
+the CSNET name server
+[Solomon81]
+provides an facility that goes beyond a single
+tightly-coupled environment.
+Such a facility would normally exist outside of
+.i sendmail
+however.
+.sh 0 "ACKNOWLEDGEMENTS"
+.pp
+Thanks are due to Kurt Shoens for his continual cheerful
+assistance and good advice,
+Bill Joy for pointing me in the correct direction
+(over and over),
+and Mark Horton for more advice,
+prodding,
+and many of the good ideas.
+Kurt and Eric Schmidt are to be credited
+for using
+.i delivermail
+as a server for their programs
+(\c
+.i Mail
+and BerkNet respectively)
+before any sane person should have,
+and making the necessary modifications
+promptly and happily.
+Eric gave me considerable advice about the perils
+of network software which saved me an unknown
+amount of work and grief.
+Mark did the original implementation of the DBM version
+of aliasing, installed the VFORK code,
+wrote the current version of
+.i rmail ,
+and was the person who really convinced me
+to put the work into
+.i delivermail
+to turn it into
+.i sendmail .
+Kurt deserves accolades for using
+.i sendmail
+when I was myself afraid to take the risk;
+how a person can continue to be so enthusiastic
+in the face of so much bitter reality is beyond me.
+.pp
+Kurt,
+Mark,
+Kirk McKusick,
+Marvin Solomon,
+and many others have reviewed this paper,
+giving considerable useful advice.
+.pp
+Special thanks are reserved for Mike Stonebraker at Berkeley
+and Bob Epstein at Britton-Lee,
+who both knowingly allowed me to put so much work into this
+project
+when there were so many other things I really should
+have been working on.
+.+c
+.ce
+REFERENCES
+.nr ii 1.5i
+.ip [Birrell82]
+Birrell, A. D.,
+Levin, R.,
+Needham, R. M.,
+and
+Schroeder, M. D.,
+.q "Grapevine: An Exercise in Distributed Computing."
+In
+.ul
+Comm. A.C.M. 25,
+4,
+April 82.
+.ip [Borden79]
+Borden, S.,
+Gaines, R. S.,
+and
+Shapiro, N. Z.,
+.ul
+The MH Message Handling System: Users' Manual.
+R-2367-PAF.
+Rand Corporation.
+October 1979.
+.ip [Crocker77a]
+Crocker, D. H.,
+Vittal, J. J.,
+Pogran, K. T.,
+and
+Henderson, D. A. Jr.,
+.ul
+Standard for the Format of ARPA Network Text Messages.
+RFC 733,
+NIC 41952.
+In [Feinler78].
+November 1977.
+.ip [Crocker77b]
+Crocker, D. H.,
+.ul
+Framework and Functions of the MS Personal Message System.
+R-2134-ARPA,
+Rand Corporation,
+Santa Monica, California.
+1977.
+.ip [Crocker79]
+Crocker, D. H.,
+Szurkowski, E. S.,
+and
+Farber, D. J.,
+.ul
+An Internetwork Memo Distribution Facility \*- MMDF.
+6th Data Communication Symposium,
+Asilomar.
+November 1979.
+.ip [Crocker82]
+Crocker, D. H.,
+.ul
+Standard for the Format of Arpa Internet Text Messages.
+RFC 822.
+Network Information Center,
+SRI International,
+Menlo Park, California.
+August 1982.
+.ip [Metcalfe76]
+Metcalfe, R.,
+and
+Boggs, D.,
+.q "Ethernet: Distributed Packet Switching for Local Computer Networks" ,
+.ul
+Communications of the ACM 19,
+7.
+July 1976.
+.ip [Feinler78]
+Feinler, E.,
+and
+Postel, J.
+(eds.),
+.ul
+ARPANET Protocol Handbook.
+NIC 7104,
+Network Information Center,
+SRI International,
+Menlo Park, California.
+1978.
+.ip [NBS80]
+National Bureau of Standards,
+.ul
+Specification of a Draft Message Format Standard.
+Report No. ICST/CBOS 80-2.
+October 1980.
+.ip [Neigus73]
+Neigus, N.,
+.ul
+File Transfer Protocol for the ARPA Network.
+RFC 542, NIC 17759.
+In [Feinler78].
+August, 1973.
+.ip [Nowitz78a]
+Nowitz, D. A.,
+and
+Lesk, M. E.,
+.ul
+A Dial-Up Network of UNIX Systems.
+Bell Laboratories.
+In
+UNIX Programmer's Manual, Seventh Edition,
+Volume 2.
+August, 1978.
+.ip [Nowitz78b]
+Nowitz, D. A.,
+.ul
+Uucp Implementation Description.
+Bell Laboratories.
+In
+UNIX Programmer's Manual, Seventh Edition,
+Volume 2.
+October, 1978.
+.ip [Postel74]
+Postel, J.,
+and
+Neigus, N.,
+Revised FTP Reply Codes.
+RFC 640, NIC 30843.
+In [Feinler78].
+June, 1974.
+.ip [Postel77]
+Postel, J.,
+.ul
+Mail Protocol.
+NIC 29588.
+In [Feinler78].
+November 1977.
+.ip [Postel79a]
+Postel, J.,
+.ul
+Internet Message Protocol.
+RFC 753,
+IEN 85.
+Network Information Center,
+SRI International,
+Menlo Park, California.
+March 1979.
+.ip [Postel79b]
+Postel, J. B.,
+.ul
+An Internetwork Message Structure.
+In
+.ul
+Proceedings of the Sixth Data Communications Symposium,
+IEEE.
+New York.
+November 1979.
+.ip [Postel80]
+Postel, J. B.,
+.ul
+A Structured Format for Transmission of Multi-Media Documents.
+RFC 767.
+Network Information Center,
+SRI International,
+Menlo Park, California.
+August 1980.
+.ip [Postel82]
+Postel, J. B.,
+.ul
+Simple Mail Transfer Protocol.
+RFC821
+(obsoleting RFC788).
+Network Information Center,
+SRI International,
+Menlo Park, California.
+August 1982.
+.ip [Schmidt79]
+Schmidt, E.,
+.ul
+An Introduction to the Berkeley Network.
+University of California, Berkeley California.
+1979.
+.ip [Shoens79]
+Shoens, K.,
+.ul
+Mail Reference Manual.
+University of California, Berkeley.
+In UNIX Programmer's Manual,
+Seventh Edition,
+Volume 2C.
+December 1979.
+.ip [Sluizer81]
+Sluizer, S.,
+and
+Postel, J. B.,
+.ul
+Mail Transfer Protocol.
+RFC 780.
+Network Information Center,
+SRI International,
+Menlo Park, California.
+May 1981.
+.ip [Solomon81]
+Solomon, M., Landweber, L., and Neuhengen, D.,
+.q "The Design of the CSNET Name Server."
+CS-DN-2,
+University of Wisconsin, Madison.
+November 1981.
+.ip [Su82]
+Su, Zaw-Sing,
+and
+Postel, Jon,
+.ul
+The Domain Naming Convention for Internet User Applications.
+RFC819.
+Network Information Center,
+SRI International,
+Menlo Park, California.
+August 1982.
+.ip [UNIX83]
+.ul
+The UNIX Programmer's Manual, Seventh Edition,
+Virtual VAX-11 Version,
+Volume 1.
+Bell Laboratories,
+modified by the University of California,
+Berkeley, California.
+March, 1983.
diff --git a/usr.sbin/sendmail/doc/intro/intro.ps b/usr.sbin/sendmail/doc/intro/intro.ps
new file mode 100644 (file)
index 0000000..8514f59
--- /dev/null
@@ -0,0 +1,1295 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Italic
+%%+ font Times-Bold
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 13
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Times-Bold
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Italic@0 ENC0/Times-Italic RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 14/Times-Roman@0 SF(SENDMAIL \212 An Internetw)159.172 141 Q
+(ork Mail Router)-.14 E/F1 10/Times-Roman@0 SF(Eric Allman\207)260.92 165 Q/F2
+10/Times-Italic@0 SF(Univer)220.2 183 Q(sity of California, Berk)-.1 E(ele)-.1
+E(y)-.3 E(Mammoth Pr)251.98 195 Q(oject)-.45 E F1(ABSTRA)262.085 227.4 Q(CT)-.4
+E 1.41(Routing mail through a heterogenous internet presents man)112 243.6 R
+3.91(yn)-.15 G 1.91 -.25(ew p)372.55 243.6 T 3.91(roblems. Among).25 F .297
+(the w)112 255.6 R .297(orst of these is that of address mapping.)-.1 F
+(Historically)5.297 E 2.797(,t)-.65 G .298(his has been handled on an)355.03
+255.6 R F2(ad hoc)112 267.6 Q F1 2.5(basis. Ho)2.5 F(we)-.25 E -.15(ve)-.25 G
+.8 -.4(r, t).15 H(his approach has become unmanageable as internets gro).4 E
+-.65(w.)-.25 G .15(Sendmail acts a uni\214ed "post of)112 283.8 R .15
+(\214ce" to which all mail can be submitted.)-.25 F .15(Address inter)5.15 F(-)
+-.2 E .426(pretation is controlled by a production system, which can parse bot\
+h domain-based ad-)112 295.8 R .423(dressing and old-style)112 307.8 R F2 .423
+(ad hoc)2.923 F F1 2.923(addresses. The)2.923 F .422(production system is po)
+2.922 F .422(werful enough to)-.25 F(re)112 319.8 Q 1.357(write addresses in t\
+he message header to conform to the standards of a number of)-.25 F 1.15
+(common tar)112 331.8 R 1.15(get netw)-.18 F 1.15
+(orks, including old \(NCP/RFC733\) Arpanet, ne)-.1 F 3.65(w\()-.25 G
+(TCP/RFC822\))405.65 331.8 Q 1.119(Arpanet, UUCP)112 343.8 R 3.619(,a)-1.11 G
+1.119(nd Phonenet.)186.448 343.8 R 1.119(Sendmail also implements an SMTP serv)
+6.119 F(er)-.15 E 3.619(,m)-.4 G(essage)437.9 343.8 Q(queueing, and aliasing.)
+112 355.8 Q F2(Sendmail)97 400.2 Q F1 .501(implements a general internetw)3 F
+.501(ork mail routing f)-.1 F(acility)-.1 E 3.001(,f)-.65 G .501
+(eaturing aliasing and forw)369.847 400.2 R(arding,)-.1 E
+(automatic routing to netw)72 412.2 Q(ork g)-.1 E(ate)-.05 E -.1(wa)-.25 G
+(ys, and \215e).1 E(xible con\214guration.)-.15 E .624(In a simple netw)97
+428.4 R .624(ork, each node has an address, and resources can be identi\214ed \
+with a host-resource)-.1 F .374(pair; in particular)72 440.4 R 2.874(,t)-.4 G
+.374(he mail system can refer to users using a host-username pair)149.932 440.4
+R 5.374(.H)-.55 G .375(ost names and numbers)409.276 440.4 R(ha)72 452.4 Q .3
+-.15(ve t)-.2 H 2.5(ob).15 G 2.5(ea)108.31 452.4 S
+(dministered by a central authority)119.69 452.4 Q 2.5(,b)-.65 G
+(ut usernames can be assigned locally to each host.)263.82 452.4 Q .649
+(In an internet, multiple netw)97 468.6 R .649(orks with dif)-.1 F .649
+(ferent characterstics and managements must communicate.)-.25 F .389
+(In particular)72 480.6 R 2.889(,t)-.4 G .389
+(he syntax and semantics of resource identi\214cation change.)129.308 480.6 R
+.39(Certain special cases can be han-)5.389 F 1.033(dled tri)72 492.6 R 1.033
+(vially by)-.25 F F2 1.033(ad hoc)3.533 F F1 1.032(techniques, such as pro)
+3.533 F 1.032(viding netw)-.15 F 1.032
+(ork names that appear local to hosts on other)-.1 F(netw)72 504.6 Q 1.454
+(orks, as with the Ethernet at Xerox P)-.1 F 3.955(ARC. Ho)-.92 F(we)-.25 E
+-.15(ve)-.25 G 4.755 -.4(r, t).15 H 1.455(he general case is e).4 F 1.455
+(xtremely comple)-.15 F 3.955(x. F)-.15 F(or)-.15 E -.15(ex)72 516.6 S .192
+(ample, some netw).15 F .192(orks require point-to-point routing, which simpli\
+\214es the database update problem since)-.1 F .618(only adjacent hosts must b\
+e entered into the system tables, while others use end-to-end addressing.)72
+528.6 R(Some)5.618 E(netw)72 540.6 Q .123(orks use a left-associati)-.1 F .423
+-.15(ve s)-.25 H .123(yntax and others use a right-associati).15 F .423 -.15
+(ve s)-.25 H .123(yntax, causing ambiguity in mix).15 F(ed)-.15 E(addresses.)72
+552.6 Q .678(Internet standards seek to eliminate these problems.)97 568.8 R
+(Initially)5.678 E 3.178(,t)-.65 G .679(hese proposed e)353.134 568.8 R .679
+(xpanding the address)-.15 F .65(pairs to address triples, consisting of {netw)
+72 580.8 R .649(ork, host, resource} triples.)-.1 F(Netw)5.649 E .649
+(ork numbers must be uni)-.1 F -.15(ve)-.25 G -.2(r-).15 G 1.452
+(sally agreed upon, and hosts can be assigned locally on each netw)72 592.8 R
+3.952(ork. The)-.1 F(user)3.952 E(-le)-.2 E -.15(ve)-.25 G 3.952(lp).15 G 1.452
+(resentation w)440.718 592.8 R(as)-.1 E 2.352(quickly e)72 604.8 R 2.352(xpand\
+ed to address domains, comprised of a local resource identi\214cation and a hi\
+erarchical)-.15 F .256(domain speci\214cation with a common static root.)72
+616.8 R .257(The domain technique separates the issue of ph)5.257 F .257
+(ysical v)-.05 F(er)-.15 E(-)-.2 E .807(sus logical addressing.)72 628.8 R -.15
+(Fo)5.807 G 3.307(re).15 G .807
+(xample, an address of the form \231eric@a.cc.berk)191.028 628.8 R(ele)-.1 E
+-.65(y.)-.15 G .807(arpa\232 describes only the).65 F(logical or)72 640.8 Q
+-.05(ga)-.18 G(nization of the address space.).05 E F2(Sendmail)97 657 Q F1
+.493(is intended to help bridge the g)2.992 F .493(ap between the totally)-.05
+F F2 .493(ad hoc)2.993 F F1 -.1(wo)2.993 G .493(rld of netw).1 F .493
+(orks that kno)-.1 F(w)-.25 E .855
+(nothing of each other and the clean, tightly-coupled w)72 669 R .854
+(orld of unique netw)-.1 F .854(ork numbers.)-.1 F .854(It can accept old)5.854
+F .32 LW 76 678.6 72 678.6 DL 80 678.6 76 678.6 DL 84 678.6 80 678.6 DL 88
+678.6 84 678.6 DL 92 678.6 88 678.6 DL 96 678.6 92 678.6 DL 100 678.6 96 678.6
+DL 104 678.6 100 678.6 DL 108 678.6 104 678.6 DL 112 678.6 108 678.6 DL 116
+678.6 112 678.6 DL 120 678.6 116 678.6 DL 124 678.6 120 678.6 DL 128 678.6 124
+678.6 DL 132 678.6 128 678.6 DL 136 678.6 132 678.6 DL 140 678.6 136 678.6 DL
+144 678.6 140 678.6 DL 148 678.6 144 678.6 DL 152 678.6 148 678.6 DL 156 678.6
+152 678.6 DL 160 678.6 156 678.6 DL 164 678.6 160 678.6 DL 168 678.6 164 678.6
+DL 172 678.6 168 678.6 DL 176 678.6 172 678.6 DL 180 678.6 176 678.6 DL 184
+678.6 180 678.6 DL 188 678.6 184 678.6 DL 192 678.6 188 678.6 DL 196 678.6 192
+678.6 DL 200 678.6 196 678.6 DL 204 678.6 200 678.6 DL 208 678.6 204 678.6 DL
+212 678.6 208 678.6 DL 216 678.6 212 678.6 DL/F3 8/Times-Roman@0 SF .557
+(\207A considerable part of this w)93.6 690.6 R .557(ork w)-.08 F .557
+(as done while under the emplo)-.08 F 2.557(yo)-.08 G 2.556(ft)323.116 690.6 S
+.556(he INGRES Project at the Uni)330.56 690.6 R -.12(ve)-.2 G .556
+(rsity of California at).12 F(Berk)72 700.2 Q(ele)-.08 E 2(ya)-.12 G
+(nd at Britton Lee.)106.232 700.2 Q/F4 10/Times-Bold@0 SF
+(SENDMAIL \212 An Inter)72 756 Q(netw)-.15 E(ork Mail Router)-.1 E(SMM:9-1)
+462.9 756 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 192.28(SMM:9-2 SENDMAIL)72 60 R 2.5<8a41>2.5 G 2.5(nI)
+383.99 60 S(nter)395.94 60 Q(netw)-.15 E(ork Mail Router)-.1 E/F1 10
+/Times-Roman@0 SF .632(arbitrary address syntax)72 96 R .633(es, resolving amb\
+iguities using heuristics speci\214ed by the system administrator)-.15 F 3.133
+(,a)-.4 G(s)500.11 96 Q .348(well as domain-based addressing.)72 108 R .347
+(It helps guide the con)5.347 F -.15(ve)-.4 G .347
+(rsion of message formats between disparate net-).15 F -.1(wo)72 120 S 3.394
+(rks. In).1 F(short,)3.394 E/F2 10/Times-Italic@0 SF(sendmail)3.394 E F1 .894
+(is designed to assist a graceful transition to consistent internetw)3.394 F
+.895(ork addressing)-.1 F(schemes.)72 132 Q .153
+(Section 1 discusses the design goals for)97 160.2 R F2(sendmail)2.653 E F1
+5.153(.S)C .152(ection 2 gi)308.214 160.2 R -.15(ve)-.25 G 2.652(sa).15 G 2.652
+(no)370.76 160.2 S -.15(ve)383.262 160.2 S(rvie).15 E 2.652(wo)-.25 G 2.652(ft)
+422.724 160.2 S .152(he basic functions)431.486 160.2 R .644(of the system.)72
+172.2 R .644(In section 3, details of usage are discussed.)5.644 F .644
+(Section 4 compares)5.644 F F2(sendmail)3.144 E F1 .645(to other internet)3.144
+F(mail routers, and an e)72 184.2 Q -.25(va)-.25 G(luation of).25 E F2
+(sendmail)2.5 E F1(is gi)2.5 E -.15(ve)-.25 G 2.5(ni).15 G 2.5(ns)283.3 184.2 S
+(ection 5, including future plans.)294.69 184.2 Q F0 2.5(1. DESIGN)72 208.2 R
+(GO)2.5 E(ALS)-.4 E F1(Design goals for)112 224.4 Q F2(sendmail)2.5 E F1
+(include:)2.5 E 12.5(\(1\) Compatibility)92 240.6 R 1.363(with the e)3.864 F
+1.363(xisting mail programs, including Bell v)-.15 F 1.363
+(ersion 6 mail, Bell v)-.15 F 1.363(ersion 7)-.15 F 1.202(mail [UNIX83], Berk)
+118.66 252.6 R(ele)-.1 E(y)-.15 E F2(Mail)3.702 E F1 1.202
+([Shoens79], BerkNet mail [Schmidt79], and hopefully UUCP)3.702 F(mail [No)
+118.66 264.6 Q(witz78a, No)-.25 E 2.5(witz78b]. ARP)-.25 F(ANET mail [Crock)
+-.92 E(er77a, Postel77] w)-.1 E(as also required.)-.1 E 12.5(\(2\) Reliability)
+92 280.8 R 4.003(,i)-.65 G 4.003(nt)169.523 280.8 S 1.502
+(he sense of guaranteeing that e)181.306 280.8 R -.15(ve)-.25 G 1.502
+(ry message is correctly deli).15 F -.15(ve)-.25 G 1.502(red or at least).15 F
+.368
+(brought to the attention of a human for correct disposal; no message should e)
+118.66 292.8 R -.15(ve)-.25 G 2.868(rb).15 G 2.868(ec)452.252 292.8 S
+(ompletely)464 292.8 Q 2.541(lost. This)118.66 304.8 R .041(goal w)2.541 F .041
+(as considered essential because of the emphasis on mail in our en)-.1 F 2.54
+(vironment. It)-.4 F 1.754
+(has turned out to be one of the hardest goals to satisfy)118.66 316.8 R 4.255
+(,e)-.65 G 1.755(specially in the f)363.75 316.8 R 1.755(ace of the man)-.1 F
+(y)-.15 E .978(anomalous message formats produced by v)118.66 328.8 R .977
+(arious ARP)-.25 F .977(ANET sites.)-.92 F -.15(Fo)5.977 G 3.477(re).15 G .977
+(xample, certain sites)420.116 328.8 R .069
+(generate improperly formated addresses, occasionally causing error)118.66
+340.8 R .069(-message loops.)-.2 F .069(Some hosts)5.069 F .063(use blanks in \
+names, causing problems with UNIX mail programs that assume that an address is)
+118.66 352.8 R .111(one w)118.66 364.8 R 2.611(ord. The)-.1 F .111
+(semantics of some \214elds are interpreted slightly dif)2.611 F .112
+(ferently by dif)-.25 F .112(ferent sites.)-.25 F(In)5.112 E(summary)118.66
+376.8 Q 3.023(,t)-.65 G .523(he obscure features of the ARP)163.533 376.8 R
+.523(ANET mail protocol really)-.92 F F2(ar)3.023 E(e)-.37 E F1 .522
+(used and are dif)3.023 F(\214cult)-.25 E(to support, b)118.66 388.8 Q
+(ut must be supported.)-.2 E 12.5(\(3\) Existing)92 405 R(softw)2.938 E .438
+(are to do actual deli)-.1 F -.15(ve)-.25 G .439(ry should be used whene).15 F
+-.15(ve)-.25 G 2.939(rp).15 G 2.939(ossible. This)387.654 405 R .439(goal deri)
+2.939 F -.15(ve)-.25 G 2.939(sa).15 G(s)500.11 405 Q
+(much from political and practical considerations as technical.)118.66 417 Q
+12.5(\(4\) Easy)92 433.2 R -.15(ex)2.899 G .399(pansion to f).15 F .399
+(airly comple)-.1 F 2.898(xe)-.15 G -.4(nv)261.064 433.2 S .398
+(ironments, including multiple connections to a single net-).4 F -.1(wo)118.66
+445.2 S .115
+(rk type \(such as with multiple UUCP or Ether nets [Metcalfe76]\).).1 F .115
+(This goal requires consid-)5.115 F .587(eration of the contents of an address\
+ as well as its syntax in order to determine which g)118.66 457.2 R(ate)-.05 E
+-.1(wa)-.25 G(y).1 E 1.018(to use.)118.66 469.2 R -.15(Fo)6.018 G 3.518(re).15
+G 1.018(xample, the ARP)173.354 469.2 R 1.019
+(ANET is bringing up the TCP protocol to replace the old NCP)-.92 F 4.791
+(protocol. No)118.66 481.2 R 2.291(host at Berk)4.791 F(ele)-.1 E 4.791(yr)-.15
+G 2.291(uns both TCP and NCP)256.235 481.2 R 4.791(,s)-1.11 G 4.79(oi)369.37
+481.2 S 4.79(ti)381.94 481.2 S 4.79(sn)392.29 481.2 S 2.29
+(ecessary to look at the)405.97 481.2 R(ARP)118.66 493.2 Q .016
+(ANET host name to determine whether to route mail to an NCP g)-.92 F(ate)-.05
+E -.1(wa)-.25 G 2.517(yo).1 G 2.517(raT)435.569 493.2 S .017(CP g)454.483 493.2
+R(ate)-.05 E -.1(wa)-.25 G -.65(y.).1 G 12.5(\(5\) Con\214guration)92 509.4 R
+.145(should not be compiled into the code.)2.645 F 2.645(As)5.145 G .145
+(ingle compiled program should be able)346.905 509.4 R .91(to run as is at an)
+118.66 521.4 R 3.41(ys)-.15 G .91
+(ite \(barring such basic changes as the CPU type or the operating system\).)
+200.63 521.4 R 2.61 -.8(We h)118.66 533.4 T -2.25 -.2(av e).8 H 1.009
+(found this seemingly unimportant goal to be critical in real life.)3.71 F
+1.009(Besides the simple)6.009 F .66(problems that occur when an)118.66 545.4 R
+3.16(yp)-.15 G .66(rogram gets recompiled in a dif)249.84 545.4 R .66
+(ferent en)-.25 F .66(vironment, man)-.4 F 3.16(ys)-.15 G(ites)490.11 545.4 Q
+(lik)118.66 557.4 Q 2.5(et)-.1 G 2.5<6f99>138.84 557.4 S(\214ddle\232 with an)
+150.78 557.4 Q(ything that the)-.15 E 2.5(yw)-.15 G(ill be recompiling an)
+282.42 557.4 Q(yw)-.15 E(ay)-.1 E(.)-.65 E(\(6\))92 573.6 Q F2(Sendmail)118.66
+573.6 Q F1 .184(must be able to let v)2.684 F .184
+(arious groups maintain their o)-.25 F .184(wn mailing lists, and let indi)-.25
+F(viduals)-.25 E(specify their o)118.66 585.6 Q(wn forw)-.25 E
+(arding, without modifying the system alias \214le.)-.1 E 12.5(\(7\) Each)92
+601.8 R .313(user should be able to specify which mailer to e)2.813 F -.15(xe)
+-.15 G .313(cute to process mail being deli).15 F -.15(ve)-.25 G .314(red for)
+.15 F 3.098(him. This)118.66 613.8 R .598(feature allo)3.098 F .598
+(ws users who are using specialized mailers that use a dif)-.25 F .598
+(ferent format to)-.25 F -.2(bu)118.66 625.8 S .25(ild their en).2 F .25
+(vironment without changing the system, and f)-.4 F .25
+(acilitates specialized functions \(such)-.1 F(as returning an \231I am on v)
+118.66 637.8 Q(acation\232 message\).)-.25 E 12.5(\(8\) Netw)92 654 R 1.553
+(ork traf)-.1 F 1.552(\214c should be minimized by batching addresses to a sin\
+gle host where possible,)-.25 F(without assistance from the user)118.66 666 Q
+(.)-.55 E .374(These goals moti)112 682.2 R -.25(va)-.25 G .374
+(ted the architecture illustrated in \214gure 1.).25 F .375
+(The user interacts with a mail gen-)5.375 F .491(erating and sending program.)
+87 694.2 R .491(When the mail is created, the generator calls)5.491 F F2
+(sendmail)2.99 E F1 2.99(,w)C .49(hich routes the)444.14 694.2 R .84
+(message to the correct mailer\(s\).)87 706.2 R .841
+(Since some of the senders may be netw)5.84 F .841(ork serv)-.1 F .841
+(ers and some of the)-.15 F(mailers may be netw)87 718.2 Q(ork clients,)-.1 E
+F2(sendmail)2.5 E F1(may be used as an internet mail g)2.5 E(ate)-.05 E -.1(wa)
+-.25 G -.65(y.).1 G EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(SENDMAIL \212 An Inter)72 60 Q(netw)-.15 E
+(ork Mail Router)-.1 E(SMM:9-3)462.9 60 Q .4 LW 77 108 72 108 DL 79 108 74 108
+DL 84 108 79 108 DL 89 108 84 108 DL 94 108 89 108 DL 99 108 94 108 DL 104 108
+99 108 DL 109 108 104 108 DL 114 108 109 108 DL 119 108 114 108 DL 124 108 119
+108 DL 129 108 124 108 DL 134 108 129 108 DL 139 108 134 108 DL 144 108 139 108
+DL 149 108 144 108 DL 154 108 149 108 DL 159 108 154 108 DL 164 108 159 108 DL
+169 108 164 108 DL 174 108 169 108 DL 179 108 174 108 DL 184 108 179 108 DL 189
+108 184 108 DL 194 108 189 108 DL 199 108 194 108 DL 204 108 199 108 DL 209 108
+204 108 DL 214 108 209 108 DL 219 108 214 108 DL 224 108 219 108 DL 229 108 224
+108 DL 234 108 229 108 DL 239 108 234 108 DL 244 108 239 108 DL 249 108 244 108
+DL 254 108 249 108 DL 259 108 254 108 DL 264 108 259 108 DL 269 108 264 108 DL
+274 108 269 108 DL 279 108 274 108 DL 284 108 279 108 DL 289 108 284 108 DL 294
+108 289 108 DL 299 108 294 108 DL 304 108 299 108 DL 309 108 304 108 DL 314 108
+309 108 DL 319 108 314 108 DL 324 108 319 108 DL 329 108 324 108 DL 334 108 329
+108 DL 339 108 334 108 DL 344 108 339 108 DL 349 108 344 108 DL 354 108 349 108
+DL 359 108 354 108 DL 364 108 359 108 DL 369 108 364 108 DL 374 108 369 108 DL
+379 108 374 108 DL 384 108 379 108 DL 389 108 384 108 DL 394 108 389 108 DL 399
+108 394 108 DL 404 108 399 108 DL 409 108 404 108 DL 414 108 409 108 DL 419 108
+414 108 DL 424 108 419 108 DL 429 108 424 108 DL 434 108 429 108 DL 439 108 434
+108 DL 444 108 439 108 DL 449 108 444 108 DL 454 108 449 108 DL 459 108 454 108
+DL 464 108 459 108 DL 469 108 464 108 DL 474 108 469 108 DL 479 108 474 108 DL
+484 108 479 108 DL 489 108 484 108 DL 494 108 489 108 DL 499 108 494 108 DL 504
+108 499 108 DL/F1 10/Times-Roman@0 SF(sender1)164.45 155.6 Q 144 135.6 144
+171.6 DL 216 135.6 144 135.6 DL 216 171.6 216 135.6 DL 144 171.6 216 171.6 DL
+(sender2)272.45 155.6 Q 252 135.6 252 171.6 DL 324 135.6 252 135.6 DL 324 171.6
+324 135.6 DL 252 171.6 324 171.6 DL(sender3)380.45 155.6 Q 360 135.6 360 171.6
+DL 432 135.6 360 135.6 DL 432 171.6 432 135.6 DL 360 171.6 432 171.6 DL 288
+207.6 288 171.6 DL 288 207.6 286.2 200.4 DL 288 207.6 289.8 200.4 DL(sendmail)
+269.945 227.6 Q 216 207.6 216 243.6 DL 360 207.6 216 207.6 DL 360 243.6 360
+207.6 DL 216 243.6 360 243.6 DL 288 279.6 288 243.6 DL 288 279.6 286.2 272.4 DL
+288 279.6 289.8 272.4 DL(mailer1)164.725 299.6 Q 144 279.6 144 315.6 DL 216
+279.6 144 279.6 DL 216 315.6 216 279.6 DL 144 315.6 216 315.6 DL(mailer2)
+272.725 299.6 Q 252 279.6 252 315.6 DL 324 279.6 252 279.6 DL 324 315.6 324
+279.6 DL 252 315.6 324 315.6 DL(mailer3)380.725 299.6 Q 360 279.6 360 315.6 DL
+432 279.6 360 279.6 DL 432 315.6 432 279.6 DL 360 315.6 432 315.6 DL 252 207.6
+180 171.6 DL 252 207.6 244.728 206.016 DL 252 207.6 246.384 202.776 DL 324
+207.6 396 171.6 DL 324 207.6 329.616 202.776 DL 324 207.6 331.272 206.016 DL
+180 279.6 252 243.6 DL 180 279.6 185.616 274.776 DL 180 279.6 187.272 278.016
+DL 396 279.6 324 243.6 DL 396 279.6 388.728 278.016 DL 396 279.6 390.384
+274.776 DL(Figure 1 \212 Sendmail System Structure.)208 346.8 Q 77 358.8 72
+358.8 DL 79 358.8 74 358.8 DL 84 358.8 79 358.8 DL 89 358.8 84 358.8 DL 94
+358.8 89 358.8 DL 99 358.8 94 358.8 DL 104 358.8 99 358.8 DL 109 358.8 104
+358.8 DL 114 358.8 109 358.8 DL 119 358.8 114 358.8 DL 124 358.8 119 358.8 DL
+129 358.8 124 358.8 DL 134 358.8 129 358.8 DL 139 358.8 134 358.8 DL 144 358.8
+139 358.8 DL 149 358.8 144 358.8 DL 154 358.8 149 358.8 DL 159 358.8 154 358.8
+DL 164 358.8 159 358.8 DL 169 358.8 164 358.8 DL 174 358.8 169 358.8 DL 179
+358.8 174 358.8 DL 184 358.8 179 358.8 DL 189 358.8 184 358.8 DL 194 358.8 189
+358.8 DL 199 358.8 194 358.8 DL 204 358.8 199 358.8 DL 209 358.8 204 358.8 DL
+214 358.8 209 358.8 DL 219 358.8 214 358.8 DL 224 358.8 219 358.8 DL 229 358.8
+224 358.8 DL 234 358.8 229 358.8 DL 239 358.8 234 358.8 DL 244 358.8 239 358.8
+DL 249 358.8 244 358.8 DL 254 358.8 249 358.8 DL 259 358.8 254 358.8 DL 264
+358.8 259 358.8 DL 269 358.8 264 358.8 DL 274 358.8 269 358.8 DL 279 358.8 274
+358.8 DL 284 358.8 279 358.8 DL 289 358.8 284 358.8 DL 294 358.8 289 358.8 DL
+299 358.8 294 358.8 DL 304 358.8 299 358.8 DL 309 358.8 304 358.8 DL 314 358.8
+309 358.8 DL 319 358.8 314 358.8 DL 324 358.8 319 358.8 DL 329 358.8 324 358.8
+DL 334 358.8 329 358.8 DL 339 358.8 334 358.8 DL 344 358.8 339 358.8 DL 349
+358.8 344 358.8 DL 354 358.8 349 358.8 DL 359 358.8 354 358.8 DL 364 358.8 359
+358.8 DL 369 358.8 364 358.8 DL 374 358.8 369 358.8 DL 379 358.8 374 358.8 DL
+384 358.8 379 358.8 DL 389 358.8 384 358.8 DL 394 358.8 389 358.8 DL 399 358.8
+394 358.8 DL 404 358.8 399 358.8 DL 409 358.8 404 358.8 DL 414 358.8 409 358.8
+DL 419 358.8 414 358.8 DL 424 358.8 419 358.8 DL 429 358.8 424 358.8 DL 434
+358.8 429 358.8 DL 439 358.8 434 358.8 DL 444 358.8 439 358.8 DL 449 358.8 444
+358.8 DL 454 358.8 449 358.8 DL 459 358.8 454 358.8 DL 464 358.8 459 358.8 DL
+469 358.8 464 358.8 DL 474 358.8 469 358.8 DL 479 358.8 474 358.8 DL 484 358.8
+479 358.8 DL 489 358.8 484 358.8 DL 494 358.8 489 358.8 DL 499 358.8 494 358.8
+DL 504 358.8 499 358.8 DL F0 2.5(2. O)72 394.8 R(VER)-.5 E(VIEW)-.55 E 2.5
+(2.1. System)87 418.8 R(Or)2.5 E(ganization)-.1 E/F2 10/Times-Italic@0 SF
+(Sendmail)127 435 Q F1 .874(neither interf)3.374 F .874
+(aces with the user nor does actual mail deli)-.1 F -.15(ve)-.25 G(ry).15 E
+5.873(.R)-.65 G(ather)431.241 435 Q 3.373(,i)-.4 G 3.373(tc)459.484 435 S .873
+(ollects a)470.077 435 R .619(message generated by a user interf)102 447 R .619
+(ace program \(UIP\) such as Berk)-.1 F(ele)-.1 E(y)-.15 E F2(Mail)3.12 E F1
+3.12(,M)C 3.12(S[)427.6 447 S(Crock)439.61 447 Q .62(er77b], or)-.1 F 1.428
+(MH [Borden79], edits the message as required by the destination netw)102 459 R
+1.427(ork, and calls appropriate)-.1 F .28(mailers to do mail deli)102 473 R
+-.15(ve)-.25 G .281(ry or queueing for netw).15 F .281(ork transmission)-.1 F
+/F3 7/Times-Roman@0 SF(1)364.275 469 Q F1 5.281(.T)367.775 473 S .281
+(his discipline allo)381.666 473 R .281(ws the inser)-.25 F(-)-.2 E 1.354
+(tion of ne)102 485 R 3.854(wm)-.25 G 1.354(ailers at minimum cost.)161.642 485
+R 1.354(In this sense)6.354 F F2(sendmail)3.853 E F1 1.353
+(resembles the Message Processing)3.853 F(Module \(MPM\) of [Postel79b].)102
+497 Q F0 2.5(2.2. Interfaces)87 521 R(to the Outside W)2.5 E(orld)-.75 E F1
+.041(There are three w)127 537.2 R(ays)-.1 E F2(sendmail)2.541 E F1 .041
+(can communicate with the outside w)2.541 F .042(orld, both in recei)-.1 F .042
+(ving and)-.25 F 1.195(in sending mail.)102 549.2 R 1.194
+(These are using the con)6.194 F -.15(ve)-.4 G 1.194(ntional UNIX ar).15 F
+1.194(gument v)-.18 F 1.194(ector/return status, speaking)-.15 F(SMTP o)102
+561.2 Q -.15(ve)-.15 G 2.5(rap).15 G(air of UNIX pipes, and speaking SMTP o)
+162.53 561.2 Q -.15(ve)-.15 G 2.5(ra).15 G 2.5(ni)348.03 561.2 S
+(nterprocess\(or\) channel.)358.31 561.2 Q F0 2.5(2.2.1. Ar)102 585.2 R
+(gument v)-.1 E(ector/exit status)-.1 E F1 .52(This technique is the standard \
+UNIX method for communicating with the process.)142 601.4 R 3.02(Al)5.52 G(ist)
+494.55 601.4 Q .442(of recipients is sent in the ar)117 613.4 R .441(gument v)
+-.18 F(ector)-.15 E 2.941(,a)-.4 G .441
+(nd the message body is sent on the standard input.)299.491 613.4 R(An)117
+625.4 Q .351(ything that the mailer prints is simply collected and sent back t\
+o the sender if there were an)-.15 F(y)-.15 E 2.621(problems. The)117 637.4 R
+-.15(ex)2.621 G .121(it status from the mailer is collected after the message \
+is sent, and a diagnostic).15 F(is printed if appropriate.)117 649.4 Q .32 LW
+76 678.8 72 678.8 DL 80 678.8 76 678.8 DL 84 678.8 80 678.8 DL 88 678.8 84
+678.8 DL 92 678.8 88 678.8 DL 96 678.8 92 678.8 DL 100 678.8 96 678.8 DL 104
+678.8 100 678.8 DL 108 678.8 104 678.8 DL 112 678.8 108 678.8 DL 116 678.8 112
+678.8 DL 120 678.8 116 678.8 DL 124 678.8 120 678.8 DL 128 678.8 124 678.8 DL
+132 678.8 128 678.8 DL 136 678.8 132 678.8 DL 140 678.8 136 678.8 DL 144 678.8
+140 678.8 DL 148 678.8 144 678.8 DL 152 678.8 148 678.8 DL 156 678.8 152 678.8
+DL 160 678.8 156 678.8 DL 164 678.8 160 678.8 DL 168 678.8 164 678.8 DL 172
+678.8 168 678.8 DL 176 678.8 172 678.8 DL 180 678.8 176 678.8 DL 184 678.8 180
+678.8 DL 188 678.8 184 678.8 DL 192 678.8 188 678.8 DL 196 678.8 192 678.8 DL
+200 678.8 196 678.8 DL 204 678.8 200 678.8 DL 208 678.8 204 678.8 DL 212 678.8
+208 678.8 DL 216 678.8 212 678.8 DL/F4 5/Times-Roman@0 SF(1)93.6 689.2 Q/F5 8
+/Times-Roman@0 SF -.12(ex)3.2 K(cept when mailing to a \214le, when).12 E/F6 8
+/Times-Italic@0 SF(sendmail)2 E F5(does the deli)2 E -.12(ve)-.2 G(ry directly)
+.12 E(.)-.52 E EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 192.28(SMM:9-4 SENDMAIL)72 60 R 2.5<8a41>2.5 G 2.5(nI)
+383.99 60 S(nter)395.94 60 Q(netw)-.15 E(ork Mail Router)-.1 E 2.5(2.2.2. SMTP)
+102 96 R -.1(ove)2.5 G 2.5(rp).1 G(ipes)186.52 96 Q/F1 10/Times-Roman@0 SF .774
+(The SMTP protocol [Postel82] can be used to run an interacti)142 112.2 R 1.074
+-.15(ve l)-.25 H .774(ock-step interf).15 F .774(ace with)-.1 F .507
+(the mailer)117 124.2 R 5.507(.A)-.55 G .506(subprocess is still created, b)
+175.461 124.2 R .506(ut no recipient addresses are passed to the mailer via)-.2
+F .075(the ar)117 136.2 R .075(gument list.)-.18 F .075(Instead, the)5.075 F
+2.575(ya)-.15 G .075
+(re passed one at a time in commands sent to the processes stan-)249.805 136.2
+R .19(dard input.)117 148.2 R(An)5.19 E .19(ything appearing on the standard o\
+utput must be a reply code in a special format.)-.15 F F0 2.5(2.2.3. SMTP)102
+172.2 R -.1(ove)2.5 G 2.5(ra).1 G 2.5(nI)185.96 172.2 S(PC connection)197.91
+172.2 Q F1 .366(This technique is similar to the pre)142 188.4 R .366
+(vious technique, e)-.25 F .366(xcept that it uses a 4.2bsd IPC chan-)-.15 F
+.953(nel [UNIX83].)117 200.4 R .953(This method is e)5.953 F .953
+(xceptionally \215e)-.15 F .952
+(xible in that the mailer need not reside on the)-.15 F(same machine.)117 212.4
+Q(It is normally used to connect to a sendmail process on another machine.)5 E
+F0 2.5(2.3. Operational)87 236.4 R(Description)2.5 E F1 .228(When a sender w)
+127 252.6 R .228(ants to send a message, it issues a request to)-.1 F/F2 10
+/Times-Italic@0 SF(sendmail)2.729 E F1 .229(using one of the three)2.729 F
+1.028(methods described abo)102 264.6 R -.15(ve)-.15 G(.).15 E F2(Sendmail)
+6.028 E F1 1.028(operates in tw)3.528 F 3.528(od)-.1 G 1.028(istinct phases.)
+325.706 264.6 R 1.028(In the \214rst phase, it collects)6.028 F .612
+(and stores the message.)102 276.6 R .612(In the second phase, message deli)
+5.612 F -.15(ve)-.25 G .612(ry occurs.).15 F .612(If there were errors during)
+5.612 F 1.59(processing during the second phase,)102 288.6 R F2(sendmail)4.09 E
+F1 1.59(creates and returns a ne)4.09 F 4.09(wm)-.25 G 1.59
+(essage describing the)415.84 288.6 R
+(error and/or returns an status code telling what went wrong.)102 300.6 Q F0
+2.5(2.3.1. Ar)102 324.6 R(gument pr)-.1 E(ocessing and addr)-.18 E(ess parsing)
+-.18 E F1(If)142 340.8 Q F2(sendmail)3.321 E F1 .821
+(is called using one of the tw)3.321 F 3.322(os)-.1 G .822
+(ubprocess techniques, the ar)320.66 340.8 R .822(guments are \214rst)-.18 F
+.797(scanned and option speci\214cations are processed.)117 352.8 R .796
+(Recipient addresses are then collected, either)5.796 F .717(from the command \
+line or from the SMTP RCPT command, and a list of recipients is created.)117
+364.8 R .347(Aliases are e)117 376.8 R .347
+(xpanded at this step, including mailing lists.)-.15 F .347(As much v)5.347 F
+.346(alidation as possible of the)-.25 F 1.001
+(addresses is done at this step: syntax is check)117 388.8 R 1.002
+(ed, and local addresses are v)-.1 F 1.002(eri\214ed, b)-.15 F 1.002
+(ut detailed)-.2 F .709
+(checking of host names and addresses is deferred until deli)117 400.8 R -.15
+(ve)-.25 G(ry).15 E 5.708(.F)-.65 G(orw)388.946 400.8 Q .708
+(arding is also performed)-.1 F(as the local addresses are v)117 412.8 Q
+(eri\214ed.)-.15 E F2(Sendmail)142 429 Q F1 .307
+(appends each address to the recipient list after parsing.)2.807 F .307
+(When a name is aliased)5.307 F .322(or forw)117 441 R .322(arded, the old nam\
+e is retained in the list, and a \215ag is set that tells the deli)-.1 F -.15
+(ve)-.25 G .322(ry phase to).15 F .479(ignore this recipient.)117 453 R .479
+(This list is k)5.479 F .479(ept free from duplicates, pre)-.1 F -.15(ve)-.25 G
+.48(nting alias loops and duplicate).15 F(messages deli)117 465 Q -.15(ve)-.25
+G(rd to the same recipient, as might occur if a person is in tw).15 E 2.5(og)
+-.1 G(roups.)428.12 465 Q F0 2.5(2.3.2. Message)102 489 R(collection)2.5 E F2
+(Sendmail)142 505.2 Q F1 .454(then collects the message.)2.954 F .454
+(The message should ha)5.454 F .754 -.15(ve a h)-.2 H .453(eader at the be).15
+F(ginning.)-.15 E .778(No formatting requirements are imposed on the message e)
+117 517.2 R .778(xcept that the)-.15 F 3.278(ym)-.15 G .778(ust be lines of te)
+427.708 517.2 R(xt)-.15 E .78(\(i.e., binary data is not allo)117 529.2 R 3.28
+(wed\). The)-.25 F .779(header is parsed and stored in memory)3.28 F 3.279(,a)
+-.65 G .779(nd the body of)443.613 529.2 R(the message is sa)117 541.2 Q -.15
+(ve)-.2 G 2.5(di).15 G 2.5(nat)204.97 541.2 S(emporary \214le.)222.19 541.2 Q
+3.227 -.8(To s)142 557.4 T 1.627(implify the program interf).8 F 1.628
+(ace, the message is collected e)-.1 F -.15(ve)-.25 G 4.128(ni).15 G 4.128(fn)
+420.536 557.4 S 4.128(oa)432.994 557.4 S 1.628(ddresses were)446.562 557.4 R
+-.25(va)117 569.4 S 2.5(lid. The).25 F(message will be returned with an error)
+2.5 E(.)-.55 E F0 2.5(2.3.3. Message)102 593.4 R(deli)2.5 E -.1(ve)-.1 G(ry).1
+E F1 -.15(Fo)142 609.6 S 2.618(re).15 G .117
+(ach unique mailer and host in the recipient list,)162.798 609.6 R F2(sendmail)
+2.617 E F1 .117(calls the appropriate mailer)2.617 F(.)-.55 E .619
+(Each mailer in)117 621.6 R -.2(vo)-.4 G .619(cation sends to all users recei)
+.2 F .619(ving the message on one host.)-.25 F .62(Mailers that only)5.62 F
+(accept one recipient at a time are handled properly)117 633.6 Q(.)-.65 E .47
+(The message is sent to the mailer using one of the same three interf)142 649.8
+R .47(aces used to submit a)-.1 F 1.465(message to sendmail.)117 661.8 R 1.465
+(Each cop)6.465 F 3.965(yo)-.1 G 3.965(ft)263.925 661.8 S 1.465
+(he message is prepended by a customized header)274 661.8 R 6.465(.T)-.55 G(he)
+494.56 661.8 Q 1.455(mailer status code is caught and check)117 673.8 R 1.455
+(ed, and a suitable error message gi)-.1 F -.15(ve)-.25 G 3.955(na).15 G 3.955
+(sa)448.115 673.8 S(ppropriate.)460.4 673.8 Q .589(The e)117 685.8 R .589(xit \
+code must conform to a system standard or a generic message \(\231Service una)
+-.15 F -.25(va)-.2 G(ilable\232\)).25 E(is gi)117 697.8 Q -.15(ve)-.25 G(n.).15
+E EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(SENDMAIL \212 An Inter)72 60 Q(netw)-.15 E
+(ork Mail Router)-.1 E(SMM:9-5)462.9 60 Q 2.5(2.3.4. Queueing)102 96 R -.25(fo)
+2.5 G 2.5(rr).25 G(etransmission)192.4 96 Q/F1 10/Times-Roman@0 SF .209(If the\
+ mailer returned an status that indicated that it might be able to handle the \
+mail later)142 112.2 R(,)-.4 E/F2 10/Times-Italic@0 SF(sendmail)117 124.2 Q F1
+(will queue the mail and try ag)2.5 E(ain later)-.05 E(.)-.55 E F0 2.5
+(2.3.5. Retur)102 148.2 R 2.5(nt)-.15 G 2.5(os)165.73 148.2 S(ender)177.12
+148.2 Q F1 .588(If errors occur during processing,)142 164.4 R F2(sendmail)
+3.088 E F1 .589(returns the message to the sender for retrans-)3.088 F 3.133
+(mission. The)117 176.4 R .632(letter can be mailed back or written in the \
+\214le \231dead.letter\232 in the sender')3.133 F 3.132(sh)-.55 G(ome)486.78
+176.4 Q(directory)117 190.4 Q/F3 7/Times-Roman@0 SF(2)153.1 186.4 Q F1(.)156.6
+190.4 Q F0 2.5(2.4. Message)87 214.4 R(Header Editing)2.5 E F1 1.756
+(Certain editing of the message header occurs automatically)127 230.6 R 6.756
+(.H)-.65 G 1.756(eader lines can be inserted)391.456 230.6 R .41
+(under control of the con\214guration \214le.)102 242.6 R .41
+(Some lines can be mer)5.41 F .41(ged; for e)-.18 F .41
+(xample, a \231From:\232 line and)-.15 F 2.5<6199>102 254.6 S
+(Full-name:\232 line can be mer)113.38 254.6 Q
+(ged under certain circumstances.)-.18 E F0 2.5(2.5. Con\214guration)87 278.6 R
+(File)2.5 E F1 .798(Almost all con\214guration information is read at runtime \
+from an ASCII \214le, encoding macro)127 294.8 R .679
+(de\214nitions \(de\214ning the v)102 306.8 R .678
+(alue of macros used internally\), header declarations \(telling sendmail the)
+-.25 F 1.009(format of header lines that it will process specially)102 318.8 R
+3.509(,i)-.65 G 1.009(.e., lines that it will add or reformat\), mailer)320.398
+318.8 R .478(de\214nitions \(gi)102 330.8 R .478(ving information such as the \
+location and characteristics of each mailer\), and address)-.25 F(re)102 342.8
+Q .428(writing rules \(a limited production system to re)-.25 F .429
+(write addresses which is used to parse and re)-.25 F(write)-.25 E
+(the addresses\).)102 354.8 Q 2.828 -.8(To i)127 371 T(mpro).8 E 1.528 -.15
+(ve p)-.15 H 1.228(erformance when reading the con\214guration \214le, a memor\
+y image can be pro-).15 F 2.5(vided. This)102 383 R(pro)2.5 E
+(vides a \231compiled\232 form of the con\214guration \214le.)-.15 E F0 2.5
+(3. USA)72 407 R(GE AND IMPLEMENT)-.55 E -.95(AT)-.9 G(ION).95 E 2.5(3.1. Ar)87
+431 R(guments)-.1 E F1(Ar)127 447.2 Q .376
+(guments may be \215ags and addresses.)-.18 F .377(Flags set v)5.377 F .377
+(arious processing options.)-.25 F -.15(Fo)5.377 G(llo).15 E .377(wing \215ag)
+-.25 F(ar)102 459.2 Q .281(guments, address ar)-.18 F .281(guments may be gi)
+-.18 F -.15(ve)-.25 G .281(n, unless we are running in SMTP mode.).15 F .28
+(Addresses fol-)5.28 F(lo)102 471.2 Q 2.5(wt)-.25 G(he syntax in RFC822 [Crock)
+122.03 471.2 Q(er82] for ARP)-.1 E(ANET address formats.)-.92 E
+(In brief, the format is:)5 E 12.5(\(1\) An)107 487.4 R
+(ything in parentheses is thro)-.15 E(wn a)-.25 E -.1(wa)-.15 G 2.5(y\().1 G
+(as a comment\).)299.65 487.4 Q 12.5(\(2\) An)107 503.6 R .051
+(ything in angle brack)-.15 F .051(ets \(\231<)-.1 F .051
+(>\232\) is preferred o)1.666 F -.15(ve)-.15 G 2.551(ra).15 G -.15(ny)348.064
+503.6 S .051(thing else.).15 F .051(This rule implements the)5.051 F(ARP)133.66
+515.6 Q(ANET standard that addresses of the form)-.92 E
+(user name <machine-address>)173.66 531.8 Q(will send to the electronic \231ma\
+chine-address\232 rather than the human \231user name.)133.66 548 Q<9a>-.7 E
+12.5(\(3\) Double)107 564.2 R 2.246(quotes \()4.746 F -2.754 2.5("\) q)2.5 H
+2.246(uote phrases; backslashes quote characters.)224.188 564.2 R 2.246
+(Backslashes are more)7.246 F(po)133.66 576.2 Q .654(werful in that the)-.25 F
+3.154(yw)-.15 G .655(ill cause otherwise equi)229.196 576.2 R -.25(va)-.25 G
+.655(lent phrases to compare dif).25 F .655(ferently \212 for)-.25 F -.15(ex)
+133.66 588.2 S(ample,).15 E F2(user)2.5 E F1(and)2.5 E F2("user")2.5 E F1
+(are equi)2.5 E -.25(va)-.25 G(lent, b).25 E(ut)-.2 E F2(\\user)2.5 E F1
+(is dif)2.5 E(ferent from either of them.)-.25 E -.15(Pa)127 604.4 S 1.12
+(rentheses, angle brack).15 F 1.12
+(ets, and double quotes must be properly balanced and nested.)-.1 F(The)6.12 E
+(re)102 618.4 Q(writing rules control remaining parsing)-.25 E F3(3)266.17
+614.4 Q F1(.)269.67 618.4 Q .32 LW 76 646 72 646 DL 80 646 76 646 DL 84 646 80
+646 DL 88 646 84 646 DL 92 646 88 646 DL 96 646 92 646 DL 100 646 96 646 DL 104
+646 100 646 DL 108 646 104 646 DL 112 646 108 646 DL 116 646 112 646 DL 120 646
+116 646 DL 124 646 120 646 DL 128 646 124 646 DL 132 646 128 646 DL 136 646 132
+646 DL 140 646 136 646 DL 144 646 140 646 DL 148 646 144 646 DL 152 646 148 646
+DL 156 646 152 646 DL 160 646 156 646 DL 164 646 160 646 DL 168 646 164 646 DL
+172 646 168 646 DL 176 646 172 646 DL 180 646 176 646 DL 184 646 180 646 DL 188
+646 184 646 DL 192 646 188 646 DL 196 646 192 646 DL 200 646 196 646 DL 204 646
+200 646 DL 208 646 204 646 DL 212 646 208 646 DL 216 646 212 646 DL/F4 5
+/Times-Roman@0 SF(2)93.6 656.4 Q/F5 8/Times-Roman@0 SF(Ob)3.2 I(viously)-.12 E
+2.226(,i)-.52 G 2.226(ft)135.246 659.6 S .226(he site gi)142.36 659.6 R .226(v\
+ing the error is not the originating site, the only reasonable option is to ma\
+il back to the sender)-.2 F 4.227(.A)-.44 G(lso,)492.664 659.6 Q .191
+(there are man)72 669.2 R 2.191(ym)-.12 G .19(ore error disposition options, b)
+128.213 669.2 R .19(ut the)-.16 F 2.19(yo)-.12 G .19(nly ef)255.514 669.2 R .19
+(fect the error message \212 the \231return to sender\232 function is al)-.2 F
+-.08(wa)-.08 G .19(ys han-).08 F(dled in one of these tw)72 678.8 Q 2(ow)-.08 G
+(ays.)156.272 678.8 Q F4(3)93.6 689.2 Q F5
+(Disclaimer: Some special processing is done after re)3.2 I
+(writing local names; see belo)-.2 E -.52(w.)-.2 G EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 192.28(SMM:9-6 SENDMAIL)72 60 R 2.5<8a41>2.5 G 2.5(nI)
+383.99 60 S(nter)395.94 60 Q(netw)-.15 E(ork Mail Router)-.1 E 2.5(3.2. Mail)87
+96 R(to Files and Pr)2.5 E(ograms)-.18 E/F1 10/Times-Roman@0 SF .609
+(Files and programs are le)127 112.2 R .609(gitimate message recipients.)-.15 F
+.609(Files pro)5.609 F .609(vide archi)-.15 F -.25(va)-.25 G 3.109(ls).25 G .61
+(torage of mes-)445.02 112.2 R .124
+(sages, useful for project administration and history)102 124.2 R 5.124(.P)-.65
+G .124(rograms are useful as recipients in a v)318.308 124.2 R .124(ariety of)
+-.25 F .69(situations, for e)102 136.2 R .691(xample, to maintain a public rep\
+ository of systems messages \(such as the Berk)-.15 F(ele)-.1 E(y)-.15 E/F2 10
+/Times-Italic@0 SF(msgs)102 148.2 Q F1(program, or the MARS system [Sattle)2.5
+E(y78]\).)-.15 E(An)127 164.4 Q 3.188(ya)-.15 G .688(ddress passing through th\
+e initial parsing algorithm as a local address \(i.e, not appear)151.698 164.4
+R(-)-.2 E .276(ing to be a v)102 176.4 R .276
+(alid address for another mailer\) is scanned for tw)-.25 F 2.776(os)-.1 G .277
+(pecial cases.)362.128 176.4 R .277(If pre\214x)5.277 F .277(ed by a v)-.15 F
+(erti-)-.15 E .18(cal bar \(\231)102 188.4 R .833<7c9a>.833 G 2.68(\)t)-.833 G
+.179(he rest of the address is processed as a shell command.)156.456 188.4 R
+.179(If the user name be)5.179 F .179(gins with a)-.15 F(slash mark \(\231/)102
+200.4 Q(\232\) the name is used as a \214le name, instead of a login name.).833
+E .241(Files that ha)127 216.6 R .541 -.15(ve s)-.2 H .241
+(etuid or setgid bits set b).15 F .241(ut no e)-.2 F -.15(xe)-.15 G .241
+(cute bits set ha).15 F .541 -.15(ve t)-.2 H .241(hose bits honored if).15 F F2
+(send-)2.742 E(mail)102 228.6 Q F1(is running as root.)2.5 E F0 2.5
+(3.3. Aliasing,)87 252.6 R -.25(Fo)2.5 G(rwarding, Inclusion).25 E F2(Sendmail)
+127 268.8 Q F1 1.075(reroutes mail three w)3.575 F 3.575(ays. Aliasing)-.1 F
+1.074(applies system wide.)3.575 F -.15(Fo)6.074 G(rw).15 E 1.074(arding allo)
+-.1 F 1.074(ws each)-.25 F .233
+(user to reroute incoming mail destined for that account.)102 280.8 R .233
+(Inclusion directs)5.233 F F2(sendmail)2.733 E F1 .233(to read a \214le for)
+2.733 F 2.5(al)102 292.8 S
+(ist of addresses, and is normally used in conjunction with aliasing.)111.72
+292.8 Q F0 2.5(3.3.1. Aliasing)102 316.8 R F1 1.554
+(Aliasing maps names to address lists using a system-wide \214le.)142 333 R
+1.553(This \214le is inde)6.553 F -.15(xe)-.15 G 4.053(dt).15 G(o)499 333 Q 1.1
+(speed access.)117 345 R 1.101(Only names that parse as local are allo)6.1 F
+1.101(wed as aliases; this guarantees a unique)-.25 F -.1(ke)117 357 S 2.5(y\()
+-.05 G(since there are no nicknames for the local host\).)137.02 357 Q F0 2.5
+(3.3.2. F)102 381 R(orwarding)-.25 E F1 .651
+(After aliasing, recipients that are local and v)142 397.2 R .651
+(alid are check)-.25 F .65(ed for the e)-.1 F .65(xistence of a \231.for)-.15 F
+(-)-.2 E -.1(wa)117 409.2 S .493(rd\232 \214le in their home directory).1 F
+5.493(.I)-.65 G 2.994(fi)264.178 409.2 S 2.994(te)273.282 409.2 S .494
+(xists, the message is)283.346 409.2 R F2(not)2.994 E F1 .494
+(sent to that user)2.994 F 2.994(,b)-.4 G .494(ut rather to)459.132 409.2 R .37
+(the list of users in that \214le.)117 421.2 R .37
+(Often this list will contain only one address, and the feature will be)5.37 F
+(used for netw)117 433.2 Q(ork mail forw)-.1 E(arding.)-.1 E -.15(Fo)142 449.4
+S(rw).15 E 1.151(arding also permits a user to specify a pri)-.1 F -.25(va)-.25
+G 1.152(te incoming mailer).25 F 6.152(.F)-.55 G 1.152(or e)437.346 449.4 R
+1.152(xample, for)-.15 F(-)-.2 E -.1(wa)117 461.4 S(rding to:).1 E -2.5 .833
+("| /)157 477.6 T(usr/local/ne)-.833 E(wmail myname")-.25 E(will use a dif)117
+493.8 Q(ferent incoming mailer)-.25 E(.)-.55 E F0 2.5(3.3.3. Inclusion)102
+517.8 R F1(Inclusion is speci\214ed in RFC 733 [Crock)142 534 Q(er77a] syntax:)
+-.1 E(:Include: pathname)157 550.2 Q .391
+(An address of this form reads the \214le speci\214ed by)117 566.4 R F2
+(pathname)2.891 E F1 .391(and sends to all users listed in that)2.891 F
+(\214le.)117 578.4 Q .644(The intent is)142 594.6 R F2(not)3.144 E F1 .644
+(to support direct use of this feature, b)3.144 F .644
+(ut rather to use this as a subset of)-.2 F 2.5(aliasing. F)117 606.6 R(or e)
+-.15 E(xample, an alias of the form:)-.15 E
+(project: :include:/usr/project/userlist)157 622.8 Q 1.93(is a method of letti\
+ng a project maintain a mailing list without interaction with the system)117
+639 R(administration, e)117 651 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(ft)203.54 651
+S(he alias \214le is protected.)212.15 651 Q 2.024(It is not necessary to reb)
+142 667.2 R 2.024(uild the inde)-.2 F 4.524(xo)-.15 G 4.524(nt)317.822 667.2 S
+2.025(he alias database when a :include: list is)330.126 667.2 R(changed.)117
+679.2 Q EP
+%%Page: 7 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(SENDMAIL \212 An Inter)72 60 Q(netw)-.15 E
+(ork Mail Router)-.1 E(SMM:9-7)462.9 60 Q 2.5(3.4. Message)87 96 R(Collection)
+2.5 E/F1 10/Times-Roman@0 SF .857
+(Once all recipient addresses are parsed and v)127 112.2 R .857
+(eri\214ed, the message is collected.)-.15 F .856(The message)5.857 F
+(comes in tw)102 124.2 Q 2.5(op)-.1 G
+(arts: a message header and a message body)162.73 124.2 Q 2.5(,s)-.65 G
+(eparated by a blank line.)343.42 124.2 Q
+(The header is formatted as a series of lines of the form)127 140.4 Q
+(\214eld-name: \214eld-v)178 156.6 Q(alue)-.25 E(Field-v)102 172.8 Q 1.366
+(alue can be split across lines by starting the follo)-.25 F 1.366
+(wing lines with a space or a tab)-.25 F 6.366(.S)-.4 G(ome)486.78 172.8 Q .211
+(header \214elds ha)102 184.8 R .511 -.15(ve s)-.2 H .211
+(pecial internal meaning, and ha).15 F .511 -.15(ve a)-.2 H .211
+(ppropriate special processing.).15 F .21(Other headers)5.21 F
+(are simply passed through.)102 196.8 Q
+(Some header \214elds may be added automatically)5 E 2.5(,s)-.65 G
+(uch as time stamps.)413.53 196.8 Q .86(The body is a series of te)127 213 R
+.861(xt lines.)-.15 F .861(It is completely uninterpreted and untouched, e)
+5.861 F .861(xcept that)-.15 F 1.43(lines be)102 225 R 1.43
+(ginning with a dot ha)-.15 F 1.729 -.15(ve t)-.2 H 1.429
+(he dot doubled when transmitted o).15 F -.15(ve)-.15 G 3.929(ra).15 G 3.929
+(nS)407.213 225 S 1.429(MTP channel.)421.702 225 R(This)6.429 E -.15(ex)102 237
+S(tra dot is stripped by the recei).15 E -.15(ve)-.25 G -.55(r.).15 G F0 2.5
+(3.5. Message)87 261 R(Deli)2.5 E -.1(ve)-.1 G(ry).1 E F1 .028
+(The send queue is ordered by recei)127 277.2 R .029
+(ving host before transmission to implement message batch-)-.25 F 3.07
+(ing. Each)102 289.2 R .57(address is mark)3.07 F .57
+(ed as it is sent so rescanning the list is safe.)-.1 F .57(An ar)5.57 F .57
+(gument list is b)-.18 F .57(uilt as)-.2 F 1.138(the scan proceeds.)102 301.2 R
+1.139(Mail to \214les is detected during the scan of the send list.)6.139 F
+1.139(The interf)6.139 F 1.139(ace to the)-.1 F
+(mailer is performed using one of the techniques described in section 2.2.)102
+313.2 Q .996(After a connection is established,)127 329.4 R/F2 10
+/Times-Italic@0 SF(sendmail)3.496 E F1(mak)3.495 E .995(es the per)-.1 F .995
+(-mailer changes to the header and)-.2 F .236(sends the result to the mailer)
+102 341.4 R 5.236(.I)-.55 G 2.736(fa)228.406 341.4 S .537 -.15(ny m)238.912
+341.4 T .237(ail is rejected by the mailer).15 F 2.737(,a\215)-.4 G .237
+(ag is set to in)386.628 341.4 R -.2(vo)-.4 G .437 -.1(ke t).2 H .237
+(he return-).1 F(to-sender function after all deli)102 353.4 Q -.15(ve)-.25 G
+(ry completes.).15 E F0 2.5(3.6. Queued)87 377.4 R(Messages)2.5 E F1 .163
+(If the mailer returns a \231temporary f)127 393.6 R .163(ailure\232 e)-.1 F
+.162(xit status, the message is queued.)-.15 F 2.662(Ac)5.162 G .162
+(ontrol \214le is)455.336 393.6 R .85
+(used to describe the recipients to be sent to and v)102 405.6 R .851
+(arious other parameters.)-.25 F .851(This control \214le is for)5.851 F(-)-.2
+E 1.011(matted as a series of lines, each describing a sender)102 417.6 R 3.511
+(,ar)-.4 G 1.011(ecipient, the time of submission, or some)333.494 417.6 R .776
+(other salient parameter of the message.)102 429.6 R .776
+(The header of the message is stored in the control \214le, so)5.776 F(that th\
+e associated data \214le in the queue is just the temporary \214le that w)102
+441.6 Q(as originally collected.)-.1 E F0 2.5(3.7. Con\214guration)87 465.6 R
+F1 .493(Con\214guration is controlled primarily by a con\214guration \214le re\
+ad at startup.)127 481.8 R F2(Sendmail)5.492 E F1(should)2.992 E
+(not need to be recomplied e)102 493.8 Q(xcept)-.15 E 12.5(\(1\) T)107 510 R
+2.5(oc)-.8 G(hange operating systems \(V6, V7/32V)150.91 510 Q 2.5(,4)-1.29 G
+(BSD\).)313.21 510 Q 12.5(\(2\) T)107 526.2 R 2.5(or)-.8 G(emo)149.8 526.2 Q .3
+-.15(ve o)-.15 H 2.5(ri).15 G(nsert the DBM \(UNIX database\) library)192.27
+526.2 Q(.)-.65 E 12.5(\(3\) T)107 542.4 R 2.5(oc)-.8 G(hange ARP)150.91 542.4 Q
+(ANET reply codes.)-.92 E 12.5(\(4\) T)107 558.6 R 2.5(oa)-.8 G
+(dd headers \214elds requiring special processing.)150.91 558.6 Q .434
+(Adding mailers or changing parsing \(i.e., re)102 574.8 R .435
+(writing\) or routing information does not require recom-)-.25 F(pilation.)102
+586.8 Q 1.317(If the mail is being sent by a local user)127 603 R 3.817(,a)-.4
+G 1.317(nd the \214le \231.mailcf\232 e)303.914 603 R 1.317
+(xists in the sender')-.15 F 3.817(sh)-.55 G(ome)486.78 603 Q(directory)102 615
+Q 2.721(,t)-.65 G .221(hat \214le is read as a con\214guration \214le after th\
+e system con\214guration \214le.)145.451 615 R .222(The primary use)5.222 F
+(of this feature is to add header lines.)102 627 Q 3.25(The con\214guration \
+\214le encodes macro de\214nitions, header de\214nitions, mailer de\214nitions\
+,)127 643.2 R(re)102 655.2 Q(writing rules, and options.)-.25 E F0 2.5
+(3.7.1. Macr)102 679.2 R(os)-.18 E F1 .332(Macros can be used in three w)142
+695.4 R 2.833(ays. Certain)-.1 F .333(macros transmit unstructured te)2.833 F
+.333(xtual informa-)-.15 F .07(tion into the mail system, such as the name)117
+707.4 R F2(sendmail)2.57 E F1 .07
+(will use to identify itself in error messages.)2.57 F 1.247
+(Other macros transmit information from)117 719.4 R F2(sendmail)3.747 E F1
+1.247(to the con\214guration \214le for use in creating)3.747 F EP
+%%Page: 8 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 192.28(SMM:9-8 SENDMAIL)72 60 R 2.5<8a41>2.5 G 2.5(nI)
+383.99 60 S(nter)395.94 60 Q(netw)-.15 E(ork Mail Router)-.1 E/F1 10
+/Times-Roman@0 SF .312(other \214elds \(such as ar)117 96 R .312(gument v)-.18
+F .312(ectors to mailers\); e.g., the name of the sender)-.15 F 2.811(,a)-.4 G
+.311(nd the host and)442.237 96 R .848(user of the recipient.)117 108 R .848
+(Other macros are unused internally)5.848 F 3.348(,a)-.65 G .848
+(nd can be used as shorthand in the)361.142 108 R(con\214guration \214le.)117
+120 Q F0 2.5(3.7.2. Header)102 144 R(declarations)2.5 E F1 .355
+(Header declarations inform)142 160.2 R/F2 10/Times-Italic@0 SF(sendmail)2.854
+E F1 .354(of the format of kno)2.854 F .354(wn header lines.)-.25 F(Kno)5.354 E
+.354(wledge of)-.25 F 2.5(af)117 172.2 S .5 -.25(ew h)127.27 172.2 T
+(eader lines is b).25 E(uilt into)-.2 E F2(sendmail)2.5 E F1 2.5(,s)C
+(uch as the \231From:\232 and \231Date:\232 lines.)284.59 172.2 Q 1.201(Most c\
+on\214gured headers will be automatically inserted in the outgoing message if \
+the)142 188.4 R(y)-.15 E(don')117 200.4 Q 2.5(te)-.18 G
+(xist in the incoming message.)144.72 200.4 Q
+(Certain headers are suppressed by some mailers.)5 E F0 2.5(3.7.3. Mailer)102
+224.4 R(declarations)2.5 E F1 1.756(Mailer declarations tell)142 240.6 R F2
+(sendmail)4.256 E F1 1.756(of the v)4.256 F 1.756(arious mailers a)-.25 F -.25
+(va)-.2 G 1.756(ilable to it.).25 F 1.755(The de\214nition)6.755 F .119
+(speci\214es the internal name of the mailer)117 252.6 R 2.619(,t)-.4 G .12
+(he pathname of the program to call, some \215ags associ-)285.183 252.6 R 2.036
+(ated with the mailer)117 264.6 R 4.536(,a)-.4 G 2.036(nd an ar)213.894 264.6 R
+2.036(gument v)-.18 F 2.036(ector to be used on the call; this v)-.15 F 2.035
+(ector is macro-)-.15 F -.15(ex)117 276.6 S(panded before use.).15 E F0 2.5
+(3.7.4. Addr)102 300.6 R(ess r)-.18 E(ewriting rules)-.18 E F1 .458
+(The heart of address parsing in)142 316.8 R F2(sendmail)2.959 E F1 .459
+(is a set of re)2.959 F .459(writing rules.)-.25 F .459(These are an ordered)
+5.459 F .561(list of pattern-replacement rules, \(some)117 328.8 R .561
+(what lik)-.25 F 3.061(eap)-.1 G .561(roduction system, e)328.867 328.8 R .56
+(xcept that order is criti-)-.15 F 1.905
+(cal\), which are applied to each address.)117 340.8 R 1.905(The address is re)
+6.905 F 1.906(written te)-.25 F 1.906(xtually until it is either)-.15 F(re)117
+352.8 Q .308(written into a special canonical form \(i.e., a \(mailer)-.25 F
+2.807(,h)-.4 G .307(ost, user\) 3-tuple, such as {arpanet, usc-)342.118 352.8 R
+.64(isif, postel} representing the address \231postel@usc-isif\232\), or it f)
+117 364.8 R .641(alls of)-.1 F 3.141(ft)-.25 G .641(he end.)406.466 364.8 R
+.641(When a pattern)5.641 F(matches, the rule is reapplied until it f)117 376.8
+Q(ails.)-.1 E 1.222
+(The con\214guration \214le also supports the editing of addresses into dif)142
+393 R 1.221(ferent formats.)-.25 F -.15(Fo)6.221 G(r).15 E -.15(ex)117 405 S
+(ample, an address of the form:).15 E(ucsfcgl!tef)157 421.2 Q
+(might be mapped into:)117 437.4 Q(tef@ucsfcgl.UUCP)157 453.6 Q
+(to conform to the domain syntax.)117 469.8 Q -.35(Tr)5 G
+(anslations can also be done in the other direction.).35 E F0 2.5
+(3.7.5. Option)102 493.8 R(setting)2.5 E F1 1.168(There are se)142 510 R -.15
+(ve)-.25 G 1.169(ral options that can be set from the con\214guration \214le.)
+.15 F 1.169(These include the)6.169 F(pathnames of v)117 522 Q
+(arious support \214les, timeouts, def)-.25 E(ault modes, etc.)-.1 E F0 2.5
+(4. COMP)72 546 R(ARISON WITH O)-.74 E(THER MAILERS)-.4 E 2.5(4.1. Deli)87 570
+R -.1(ve)-.1 G(rmail).1 E F2(Sendmail)127 586.2 Q F1(is an outgro)2.5 E(wth of)
+-.25 E F2(delivermail)2.5 E F1 5(.T)C(he primary dif)301.18 586.2 Q
+(ferences are:)-.25 E 12.5(\(1\) Con\214guration)107 602.4 R .273
+(information is not compiled in.)2.773 F .272(This change simpli\214es man)
+5.273 F 2.772(yo)-.15 G 2.772(ft)445.686 602.4 S .272(he problems)454.568 602.4
+R(of mo)133.66 614.4 Q(ving to other machines.)-.15 E(It also allo)5 E
+(ws easy deb)-.25 E(ugging of ne)-.2 E 2.5(wm)-.25 G(ailers.)413.89 614.4 Q
+12.5(\(2\) Address)107 630.6 R .681(parsing is more \215e)3.181 F 3.182
+(xible. F)-.15 F .682(or e)-.15 F(xample,)-.15 E F2(delivermail)3.182 E F1 .682
+(only supported one g)3.182 F(ate)-.05 E -.1(wa)-.25 G 3.182(yt).1 G(o)499
+630.6 Q(an)133.66 642.6 Q 2.817(yn)-.15 G(etw)155.767 642.6 Q .317
+(ork, whereas)-.1 F F2(sendmail)2.817 E F1 .317(can be sensiti)2.817 F .616
+-.15(ve t)-.25 H 2.816(oh).15 G .316(ost names and reroute to dif)345.224 642.6
+R .316(ferent g)-.25 F(ate-)-.05 E -.1(wa)133.66 654.6 S(ys.).1 E 12.5(\(3\) F)
+107 670.8 R(orw)-.15 E 1.627(arding and :include: features eliminate the requi\
+rement that the system alias \214le be)-.1 F .074(writable by an)133.66 682.8 R
+2.574(yu)-.15 G .073
+(ser \(or that an update program be written, or that the system administration)
+203.442 682.8 R(mak)133.66 694.8 Q 2.5(ea)-.1 G(ll changes\).)162.16 694.8 Q
+(\(4\))107 711 Q F2(Sendmail)133.66 711 Q F1 .4
+(supports message batching across netw)2.9 F .401
+(orks when a message is being sent to mul-)-.1 F(tiple recipients.)133.66 723 Q
+EP
+%%Page: 9 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(SENDMAIL \212 An Inter)72 60 Q(netw)-.15 E
+(ork Mail Router)-.1 E(SMM:9-9)462.9 60 Q/F1 10/Times-Roman@0 SF 12.5(\(5\) A)
+107 96 R .875(mail queue is pro)3.375 F .874(vided in)-.15 F/F2 10
+/Times-Italic@0 SF(sendmail.)3.374 E F1 .874(Mail that cannot be deli)5.874 F
+-.15(ve)-.25 G .874(red immediately b).15 F .874(ut can)-.2 F 1.063
+(potentially be deli)133.66 108 R -.15(ve)-.25 G 1.064
+(red later is stored in this queue for a later retry).15 F 6.064(.T)-.65 G
+1.064(he queue also pro-)427.218 108 R .896(vides a b)133.66 120 R(uf)-.2 E
+.896(fer ag)-.25 F .895
+(ainst system crashes; after the message has been collected it may be reli-)
+-.05 F(ably redeli)133.66 132 Q -.15(ve)-.25 G(red e).15 E -.15(ve)-.25 G 2.5
+(ni).15 G 2.5(ft)224.22 132 S(he system crashes during the initial deli)232.83
+132 Q -.15(ve)-.25 G(ry).15 E(.)-.65 E(\(6\))107 148.2 Q F2(Sendmail)133.66
+148.2 Q F1 .197(uses the netw)2.696 F .197(orking support pro)-.1 F .197
+(vided by 4.2BSD to pro)-.15 F .197(vide a direct interf)-.15 F .197(ace net-)
+-.1 F -.1(wo)133.66 160.2 S .07(rks such as the ARP).1 F .07
+(ANET and/or Ethernet using SMTP \(the Simple Mail T)-.92 F .07(ransfer Proto-)
+-.35 F(col\) o)133.66 172.2 Q -.15(ve)-.15 G 2.5(raT).15 G(CP/IP connection.)
+184.73 172.2 Q F0 2.5(4.2. MMDF)87 196.2 R F1 .957(MMDF [Crock)127 212.4 R .957
+(er79] spans a wider problem set than)-.1 F F2(sendmail)3.458 E F1 5.958(.F)C
+.958(or e)395.058 212.4 R .958(xample, the domain of)-.15 F .721
+(MMDF includes a \231phone netw)102 224.4 R .721(ork\232 mailer)-.1 F 3.221(,w)
+-.4 G(hereas)290.516 224.4 Q F2(sendmail)3.221 E F1 .721(calls on pree)3.221 F
+.72(xisting mailers in most)-.15 F(cases.)102 236.4 Q .175(MMDF and)127 252.6 R
+F2(sendmail)2.675 E F1 .175
+(both support aliasing, customized mailers, message batching, automatic)2.675 F
+(forw)102 264.6 Q .792(arding to g)-.1 F(ate)-.05 E -.1(wa)-.25 G .792
+(ys, queueing, and retransmission.).1 F .792(MMDF supports tw)5.792 F .792
+(o-stage timeout, which)-.1 F F2(sendmail)102 276.6 Q F1(does not support.)2.5
+E(The con\214guration for MMDF is compiled into the code)127 294.8 Q/F3 7
+/Times-Roman@0 SF(4)348.65 290.8 Q F1(.)352.15 294.8 Q .037
+(Since MMDF does not consider backw)127 311 R .037
+(ards compatibility as a design goal, the address parsing)-.1 F(is simpler b)
+102 323 Q(ut much less \215e)-.2 E(xible.)-.15 E 1.159(It is some)127 341.2 R
+1.159(what harder to inte)-.25 F 1.159(grate a ne)-.15 F 3.659(wc)-.25 G
+(hannel)302.802 341.2 Q F3(5)329.462 337.2 Q F1 1.159(into MMDF)336.621 341.2 R
+6.16(.I)-.8 G 3.66(np)397.59 341.2 S(articular)411.25 341.2 Q 3.66(,M)-.4 G
+1.16(MDF must)459.22 341.2 R(kno)102 353.2 Q 3.225(wt)-.25 G .725(he location \
+and format of host tables for all channels, and the channel must speak a speci\
+al)129.975 353.2 R 2.525(protocol. This)102 365.2 R(allo)2.525 E .025
+(ws MMDF to do additional v)-.25 F .025(eri\214cation \(such as v)-.15 F .025
+(erifying host names\) at submis-)-.15 F(sion time.)102 377.2 Q 1.761
+(MMDF strictly separates the submission and deli)127 393.4 R -.15(ve)-.25 G
+1.761(ry phases.).15 F(Although)6.761 E F2(sendmail)4.261 E F1 1.76(has the)
+4.261 F .784(concept of each of these stages, the)102 405.4 R 3.284(ya)-.15 G
+.784(re inte)260.068 405.4 R .785(grated into one program, whereas in MMDF the)
+-.15 F 3.285(ya)-.15 G(re)496.23 405.4 Q(split into tw)102 417.4 Q 2.5(op)-.1 G
+(rograms.)162.19 417.4 Q F0 2.5(4.3. Message)87 441.4 R(Pr)2.5 E
+(ocessing Module)-.18 E F1 .925
+(The Message Processing Module \(MPM\) discussed by Postel [Postel79b] matches)
+127 457.6 R F2(sendmail)3.425 E F1 1.364
+(closely in terms of its basic architecture.)102 469.6 R(Ho)6.364 E(we)-.25 E
+-.15(ve)-.25 G 2.164 -.4(r, l).15 H(ik).4 E 3.864(eM)-.1 G(MDF)347.526 469.6 Q
+3.864(,t)-.8 G 1.365(he MPM includes the netw)377.54 469.6 R(ork)-.1 E(interf)
+102 481.6 Q(ace softw)-.1 E(are as part of its domain.)-.1 E .408
+(MPM also postulates a duple)127 497.8 R 2.907(xc)-.15 G .407
+(hannel to the recei)256.937 497.8 R -.15(ve)-.25 G 1.207 -.4(r, a).15 H 2.907
+(sd).4 G .407(oes MMDF)365.362 497.8 R 2.907(,t)-.8 G .407(hus allo)419.546
+497.8 R .407(wing simpler)-.25 F .302
+(handling of errors by the mailer than is possible in)102 509.8 R F2(sendmail)
+2.802 E F1 5.302(.W)C .302(hen a message queued by)362.24 509.8 R F2(sendmail)
+2.802 E F1 .23(is sent, an)102 521.8 R 2.73(ye)-.15 G .23
+(rrors must be returned to the sender by the mailer itself.)154.2 521.8 R .229
+(Both MPM and MMDF mail-)5.229 F .883(ers can return an immediate error respon\
+se, and a single error processor can create an appropriate)102 533.8 R
+(response.)102 545.8 Q 2.24
+(MPM prefers passing the message as a structured object, with type-length-v)127
+564 R 2.24(alue tuples)-.25 F F3(6)498 560 Q F1(.)501.5 564 Q .874(Such a con)
+102 576 R -.15(ve)-.4 G .874(ntion requires a much higher de).15 F .875
+(gree of cooperation between mailers than is required)-.15 F(by)102 588 Q F2
+(sendmail)2.796 E F1 5.296(.M)C .296(PM also assumes a uni)167.592 588 R -.15
+(ve)-.25 G .296(rsally agreed upon internet name space \(with each address).15
+F(in the form of a net-host-user tuple\), which)102 600 Q F2(sendmail)2.5 E F1
+(does not.)2.5 E .32 LW 76 642 72 642 DL 80 642 76 642 DL 84 642 80 642 DL 88
+642 84 642 DL 92 642 88 642 DL 96 642 92 642 DL 100 642 96 642 DL 104 642 100
+642 DL 108 642 104 642 DL 112 642 108 642 DL 116 642 112 642 DL 120 642 116 642
+DL 124 642 120 642 DL 128 642 124 642 DL 132 642 128 642 DL 136 642 132 642 DL
+140 642 136 642 DL 144 642 140 642 DL 148 642 144 642 DL 152 642 148 642 DL 156
+642 152 642 DL 160 642 156 642 DL 164 642 160 642 DL 168 642 164 642 DL 172 642
+168 642 DL 176 642 172 642 DL 180 642 176 642 DL 184 642 180 642 DL 188 642 184
+642 DL 192 642 188 642 DL 196 642 192 642 DL 200 642 196 642 DL 204 642 200 642
+DL 208 642 204 642 DL 212 642 208 642 DL 216 642 212 642 DL/F4 5/Times-Roman@0
+SF(4)93.6 652.4 Q/F5 8/Times-Roman@0 SF .179
+(Dynamic con\214guration tables are currently being considered for MMDF; allo)
+3.2 J .18(wing the installer to select either compiled or dy-)-.2 F
+(namic tables.)72 665.2 Q F4(5)93.6 675.6 Q F5(The MMDF equi)3.2 I -.2(va)-.2 G
+(lent of a).2 E/F6 8/Times-Italic@0 SF(sendmail)2 E F5(\231mailer)2 E -.56
+<2e9a>-.44 G F4(6)93.6 689.2 Q F5(This is similar to the NBS standard.)3.2 I EP
+%%Page: 10 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 187.28(SMM:9-10 SENDMAIL)72 60 R 2.5<8a41>2.5 G 2.5(nI)
+383.99 60 S(nter)395.94 60 Q(netw)-.15 E(ork Mail Router)-.1 E 2.5(5. EV)72 96
+R(ALU)-1.35 E -.95(AT)-.6 G(IONS AND FUTURE PLANS).95 E/F1 10/Times-Italic@0 SF
+(Sendmail)112 112.2 Q/F2 10/Times-Roman@0 SF 1.851(is designed to w)4.351 F
+1.851(ork in a nonhomogeneous en)-.1 F 4.352(vironment. Ev)-.4 F 1.852
+(ery attempt is made to)-.15 F -.2(avo)87 124.2 S 1.037
+(id imposing unnecessary constraints on the underlying mailers.).2 F 1.036
+(This goal has dri)6.036 F -.15(ve)-.25 G 3.536(nm).15 G 1.036(uch of the)
+461.938 124.2 R 2.723(design. One)87 136.2 R .223(of the major problems has be\
+en the lack of a uniform address space, as postulated in [Pos-)2.723 F
+(tel79a] and [Postel79b].)87 148.2 Q 2.647(An)112 164.4 S .147(onuniform addre\
+ss space implies that a path will be speci\214ed in all addresses, either e)
+126.867 164.4 R(xplicitly)-.15 E .472
+(\(as part of the address\) or implicitly \(as with implied forw)87 176.4 R
+.473(arding to g)-.1 F(ate)-.05 E -.1(wa)-.25 G 2.973(ys\). This).1 F .473
+(restriction has the)2.973 F .493(unpleasant ef)87 188.4 R .493
+(fect of making replying to messages e)-.25 F .493(xceedingly dif)-.15 F .493
+(\214cult, since there is no one \231address\232)-.25 F(for an)87 200.4 Q 2.5
+(yp)-.15 G(erson, b)122.95 200.4 Q(ut only a w)-.2 E
+(ay to get there from where)-.1 E -.15(ve)-.25 G 2.5(ry).15 G(ou are.)324.7
+200.4 Q(Interf)112 216.6 Q .448(acing to mail programs that were not initially\
+ intended to be applied in an internet en)-.1 F(viron-)-.4 E(ment has been ama\
+zingly successful, and has reduced the job to a manageable task.)87 228.6 Q F1
+(Sendmail)112 244.8 Q F2 2.906(has kno)5.406 F 2.906(wledge of a fe)-.25 F
+5.406(wd)-.25 G(if)271.126 244.8 Q 2.906(\214cult en)-.25 F 2.906(vironments b)
+-.4 F 2.906(uilt in.)-.2 F 2.905(It generates ARP)7.906 F(ANET)-.92 E .648(FTP\
+/SMTP compatible error messages \(prepended with three-digit numbers [Neigus73\
+, Postel74, Pos-)87 256.8 R .771(tel82]\) as necessary)87 268.8 R 3.271(,o)-.65
+G .771(ptionally generates UNIX-style \231From\232 lines on the front of messa\
+ges for some)177.523 268.8 R 1.669(mailers, and kno)87 280.8 R 1.669(ws ho)-.25
+F 4.169(wt)-.25 G 4.169(op)195.666 280.8 S 1.669(arse the same lines on input.)
+209.835 280.8 R 1.67(Also, error handling has an option cus-)6.67 F
+(tomized for BerkNet.)87 292.8 Q 1.482(The decision to a)112 309 R -.2(vo)-.2 G
+1.482(id doing an).2 F 3.982(yt)-.15 G 1.481(ype of deli)254.222 309 R -.15(ve)
+-.25 G 1.481(ry where possible \(e).15 F -.15(ve)-.25 G 1.481
+(n, or perhaps especially).15 F(,)-.65 E .574(local deli)87 321 R -.15(ve)-.25
+G .574(ry\) has turned out to be a good idea.).15 F(Ev)5.574 E .574
+(en with local deli)-.15 F -.15(ve)-.25 G(ry).15 E 3.074(,t)-.65 G .575
+(here are issues of the loca-)394.776 321 R .469(tion of the mailbox, the form\
+at of the mailbox, the locking protocol used, etc., that are best decided by)87
+333 R .038(other programs.)87 345 R .038(One surprisingly major anno)5.038 F
+.038(yance in man)-.1 F 2.538(yi)-.15 G .038
+(nternet mailers is that the location and for)333.684 345 R(-)-.2 E .138
+(mat of local mail is b)87 357 R .138(uilt in.)-.2 F .137
+(The feeling seems to be that local mail is so common that it should be ef)
+5.137 F<8c2d>-.25 E 3.045(cient. This)87 369 R .545
+(feeling is not born out by our e)3.045 F .545(xperience; on the contrary)-.15
+F 3.045(,t)-.65 G .545(he location and format of mail-)376.575 369 R(box)87 381
+Q(es seems to v)-.15 E(ary widely from system to system.)-.25 E .681
+(The ability to automatically generate a response to incoming mail \(by forw)
+112 397.2 R .68(arding mail to a pro-)-.1 F .435
+(gram\) seems useful \(\231I am on v)87 409.2 R .435
+(acation until late August....)-.25 F 2.935(\232\) b)-.7 F .435
+(ut can create problems such as forw)-.2 F(ard-)-.1 E .143(ing loops \(tw)87
+421.2 R 2.643(op)-.1 G .143(eople on v)152.609 421.2 R .143(acation whose prog\
+rams send notes back and forth, for instance\) if these pro-)-.25 F .732
+(grams are not well written.)87 433.2 R 3.232(Ap)5.732 G .732
+(rogram could be written to do standard tasks correctly)218.592 433.2 R 3.233
+(,b)-.65 G .733(ut this w)450.404 433.2 R(ould)-.1 E(solv)87 445.2 Q 2.5(et)
+-.15 G(he general case.)113.24 445.2 Q .225
+(It might be desirable to implement some form of load limiting.)112 461.4 R
+2.725(Ia)5.225 G 2.724(mu)380.8 461.4 S(na)396.304 461.4 Q -.1(wa)-.15 G .224
+(re of an).1 F 2.724(ym)-.15 G .224(ail system)463.496 461.4 R
+(that addresses this problem, nor am I a)87 473.4 Q -.1(wa)-.15 G(re of an).1 E
+2.5(yr)-.15 G(easonable solution at this time.)294.05 473.4 Q .113(The con\214\
+guration \214le is currently practically inscrutable; considerable con)112
+489.6 R -.15(ve)-.4 G .114(nience could be real-).15 F(ized with a higher)87
+501.6 Q(-le)-.2 E -.15(ve)-.25 G 2.5(lf).15 G(ormat.)186.93 501.6 Q .778(It se\
+ems clear that common protocols will be changing soon to accommodate changing \
+require-)112 517.8 R 2.774(ments and en)87 529.8 R 5.274(vironments. These)-.4
+F 2.774(changes will include modi\214cations to the message header \(e.g.,)
+5.274 F .859([NBS80]\) or to the body of the message itself \(such as for mult\
+imedia messages [Postel80]\).)87 541.8 R(Experi-)5.859 E
+(ence indicates that these changes should be relati)87 553.8 Q -.15(ve)-.25 G
+(ly tri).15 E(vial to inte)-.25 E(grate into the e)-.15 E(xisting system.)-.15
+E .811(In tightly coupled en)112 570 R .812(vironments, it w)-.4 F .812
+(ould be nice to ha)-.1 F 1.112 -.15(ve a n)-.2 H .812(ame serv).15 F .812
+(er such as Grapvine [Bir)-.15 F(-)-.2 E .095(rell82] inte)87 582 R .095
+(grated into the mail system.)-.15 F .095(This w)5.095 F .095(ould allo)-.1 F
+2.594(was)-.25 G .094(ite such as \231Berk)330.768 582 R(ele)-.1 E .094
+(y\232 to appear as a single)-.15 F 2.606
+(host, rather than as a collection of hosts, and w)87 594 R 2.606(ould allo)-.1
+F 5.106(wp)-.25 G 2.606(eople to mo)352.786 594 R 2.906 -.15(ve t)-.15 H 2.606
+(ransparently among).15 F 1.664(machines without ha)87 606 R 1.664
+(ving to change their addresses.)-.2 F 1.664(Such a f)6.664 F 1.664(acility w)
+-.1 F 1.663(ould require an automatically)-.1 F .428
+(updated database and some method of resolving con\215icts.)87 618 R .428
+(Ideally this w)5.428 F .428(ould be ef)-.1 F(fecti)-.25 E .728 -.15(ve e)-.25
+H -.15(ve)-.1 G 2.928(nw).15 G(ithout)480.66 618 Q .184
+(all hosts being under a single management.)87 630 R(Ho)5.184 E(we)-.25 E -.15
+(ve)-.25 G .984 -.4(r, i).15 H 2.684(ti).4 G 2.683(sn)317.576 630 S .183
+(ot clear whether this feature should be inte-)329.149 630 R
+(grated into the aliasing f)87 642 Q(acility or should be considered a \231v)
+-.1 E(alue added\232 feature outside)-.25 E F1(sendmail)2.5 E F2(itself.)2.5 E
+.79(As a more interesting case, the CSNET name serv)112 658.2 R .791
+(er [Solomon81] pro)-.15 F .791(vides an f)-.15 F .791(acility that goes)-.1 F
+(be)87 670.2 Q .375(yond a single tightly-coupled en)-.15 F 2.875
+(vironment. Such)-.4 F 2.875(af)2.875 G .375(acility w)308.675 670.2 R .374
+(ould normally e)-.1 F .374(xist outside of)-.15 F F1(sendmail)2.874 E F2(ho)87
+682.2 Q(we)-.25 E -.15(ve)-.25 G -.55(r.).15 G EP
+%%Page: 11 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(SENDMAIL \212 An Inter)72 60 Q(netw)-.15 E
+(ork Mail Router)-.1 E(SMM:9-11)457.9 60 Q -.55(AC)72 96 S(KNO).55 E
+(WLEDGEMENTS)-.5 E/F1 10/Times-Roman@0 SF 1.203(Thanks are due to K)97 112.2 R
+1.204
+(urt Shoens for his continual cheerful assistance and good advice, Bill Jo)-.15
+F 3.704(yf)-.1 G(or)495.67 112.2 Q .102
+(pointing me in the correct direction \(o)72 124.2 R -.15(ve)-.15 G 2.602(ra)
+.15 G .102(nd o)244.324 124.2 R -.15(ve)-.15 G .102
+(r\), and Mark Horton for more advice, prodding, and man).15 F(y)-.15 E .453
+(of the good ideas.)72 136.2 R -.15(Ku)5.453 G .453
+(rt and Eric Schmidt are to be credited for using).15 F/F2 10/Times-Italic@0 SF
+(delivermail)2.953 E F1 .453(as a serv)2.953 F .453(er for their pro-)-.15 F
+1.663(grams \()72 148.2 R F2(Mail)A F1 1.663(and BerkNet respecti)4.163 F -.15
+(ve)-.25 G 1.663(ly\) before an).15 F 4.163(ys)-.15 G 1.663
+(ane person should ha)291.091 148.2 R -.15(ve)-.2 G 4.163(,a).15 G 1.662
+(nd making the necessary)400.423 148.2 R .078
+(modi\214cations promptly and happily)72 160.2 R 5.078(.E)-.65 G .078(ric g)
+228.332 160.2 R -2.25 -.2(av e)-.05 H .079
+(me considerable advice about the perils of netw)2.778 F .079(ork softw)-.1 F
+(are)-.1 E .179(which sa)72 172.2 R -.15(ve)-.2 G 2.679(dm).15 G 2.679(ea)
+131.998 172.2 S 2.679(nu)143.557 172.2 S(nkno)156.236 172.2 Q .178
+(wn amount of w)-.25 F .178(ork and grief.)-.1 F .178
+(Mark did the original implementation of the DBM)5.178 F -.15(ve)72 184.2 S
+.341(rsion of aliasing, installed the VFORK code, wrote the current v).15 F
+.341(ersion of)-.15 F F2(rmail)2.841 E F1 2.841(,a)C .341(nd w)411.083 184.2 R
+.342(as the person who)-.1 F .61(really con)72 196.2 R .61
+(vinced me to put the w)-.4 F .61(ork into)-.1 F F2(delivermail)3.109 E F1 .609
+(to turn it into)3.109 F F2(sendmail)3.109 E F1 5.609(.K)C .609(urt deserv)
+398.753 196.2 R .609(es accolades for)-.15 F(using)72 208.2 Q F2(sendmail)2.57
+E F1 .07(when I w)2.57 F .07(as myself afraid to tak)-.1 F 2.57(et)-.1 G .07
+(he risk; ho)271.01 208.2 R 2.57(wap)-.25 G .07
+(erson can continue to be so enthusiastic in)334.92 208.2 R(the f)72 220.2 Q
+(ace of so much bitter reality is be)-.1 E(yond me.)-.15 E -.15(Ku)97 236.4 S
+1.505(rt, Mark, Kirk McK).15 F 1.505(usick, Marvin Solomon, and man)-.15 F
+4.005(yo)-.15 G 1.504(thers ha)345.79 236.4 R 1.804 -.15(ve r)-.2 H -.25(ev).15
+G(ie).25 E 1.504(wed this paper)-.25 F 4.004(,g)-.4 G -.25(iv)483.69 236.4 S
+(ing).25 E(considerable useful advice.)72 248.4 Q .846
+(Special thanks are reserv)97 264.6 R .846(ed for Mik)-.15 F 3.346(eS)-.1 G
+(tonebrak)256.786 264.6 Q .846(er at Berk)-.1 F(ele)-.1 E 3.347(ya)-.15 G .847
+(nd Bob Epstein at Britton-Lee, who)356.995 264.6 R .542(both kno)72 276.6 R
+.542(wingly allo)-.25 F .542(wed me to put so much w)-.25 F .541
+(ork into this project when there were so man)-.1 F 3.041(yo)-.15 G .541
+(ther things I)454.588 276.6 R(really should ha)72 288.6 Q .3 -.15(ve b)-.2 H
+(een w).15 E(orking on.)-.1 E EP
+%%Page: 12 12
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF(REFERENCES)256.605 132 Q 62.73([Birrell82] Birrell,)72
+148.2 R 1.084(A. D., Le)3.584 F 1.084(vin, R., Needham, R. M., and Schroeder)
+-.25 F 3.584(,M)-.4 G 3.585(.D)433.49 148.2 S 1.085(., \231Grape)446.795 148.2
+R(vine:)-.25 E(An Ex)180 160.2 Q(ercise in Distrib)-.15 E(uted Computing.)-.2 E
+5<9a49>-.7 G(n)348.66 160.2 Q/F1 10/Times-Italic@0 SF(Comm. A.C.M. 25,)2.5 E F0
+(4, April 82.)2.5 E 59.4([Borden79] Borden,)72 176.4 R .796
+(S., Gaines, R. S., and Shapiro, N. Z.,)3.296 F F1 .795(The MH Messa)3.295 F
+.995 -.1(ge H)-.1 H .795(andling Sys-).1 F(tem: User)180 188.4 Q(s' Manual.)-.1
+E F0(R-2367-P)5 E(AF)-.92 E 5(.R)-.8 G(and Corporation.)332.06 188.4 Q
+(October 1979.)5 E([Crock)72 204.6 Q 52.29(er77a] Crock)-.1 F(er)-.1 E 2.508
+(,D)-.4 G 2.508(.H)223.938 204.6 S .008(., V)236.166 204.6 R .009
+(ittal, J. J., Pogran, K. T)-.6 F .009(., and Henderson, D. A. Jr)-.74 F(.,)
+-.55 E F1(Standar)2.509 E 2.509(df)-.37 G(or)495.11 204.6 Q .955(the F)180
+216.6 R .955(ormat of ARP)-1.05 F 3.454(AN)-.9 G .954(etwork T)272.978 216.6 R
+-.2(ex)-.92 G 3.454(tM).2 G(essa)331.536 216.6 Q -.1(ge)-.1 G(s.).1 E F0 .954
+(RFC 733, NIC 41952.)5.954 F .954(In [Fein-)5.954 F 2.5(ler78]. No)180 228.6 R
+-.15(ve)-.15 G(mber 1977.).15 E([Crock)72 244.8 Q 51.73(er77b] Crock)-.1 F(er)
+-.1 E 3.04(,D)-.4 G 3.04(.H)224.47 244.8 S(.,)237.23 244.8 Q F1 -1.55 -.55
+(Fr a)3.04 H(me).55 E .54(work and Functions of the MS P)-.15 F(er)-.8 E .54
+(sonal Messa)-.1 F .74 -.1(ge S)-.1 H(ystem.).1 E F0(R-2134-ARP)180 256.8 Q
+(A, Rand Corporation, Santa Monica, California.)-.92 E(1977.)5 E([Crock)72 273
+Q 56.73(er79] Crock)-.1 F(er)-.1 E 2.557(,D)-.4 G 2.557(.H)223.987 273 S .056
+(., Szurk)236.264 273 R -.25(ow)-.1 G .056(ski, E. S., and F).25 F(arber)-.15 E
+2.556(,D)-.4 G 2.556(.J)374.85 273 S(.,)383.796 273 Q F1 .056
+(An Internetwork Memo Dis-)2.556 F(trib)180 285 Q 1.341(ution F)-.2 F 1.341
+(acility \212 MMDF)-.75 F(.)-1.35 E F0 1.341
+(6th Data Communication Symposium, Asilomar)6.341 F(.)-.55 E(No)180 297 Q -.15
+(ve)-.15 G(mber 1979.).15 E([Crock)72 313.2 Q 56.73(er82] Crock)-.1 F(er)-.1 E
+3.383(,D)-.4 G 3.383(.H)224.813 313.2 S(.,)237.916 313.2 Q F1(Standar)3.383 E
+3.383(df)-.37 G .883(or the F)288.762 313.2 R .882(ormat of Arpa Internet T)
+-1.05 F -.2(ex)-.92 G 3.382(tM).2 G(essa)446.368 313.2 Q -.1(ge)-.1 G(s.).1 E
+F0(RFC)5.882 E 4.197(822. Netw)180 325.2 R 1.697(ork Information Center)-.1 F
+4.197(,S)-.4 G 1.698(RI International, Menlo P)333.768 325.2 R 1.698
+(ark, California.)-.15 F(August 1982.)180 337.2 Q 53.3([Metcalfe76] Metcalfe,)
+72 353.4 R .727(R., and Boggs, D., \231Ethernet: Distrib)3.227 F .727(uted P)
+-.2 F(ack)-.15 E .727(et Switching for Local)-.1 F(Computer Netw)180 365.4 Q
+(orks\232,)-.1 E F1(Communications of the A)2.5 E(CM 19,)-.3 E F0 2.5(7. July)
+2.5 F(1976.)2.5 E 60.51([Feinler78] Feinler)72 381.6 R 4.438(,E)-.4 G 1.938
+(., and Postel, J.)220.978 381.6 R(\(eds.\),)6.938 E F1(ARP)4.438 E 1.938
+(ANET Pr)-.9 F 1.938(otocol Handbook.)-.45 F F0 1.938(NIC 7104,)6.938 F(Netw)
+180 393.6 Q(ork Information Center)-.1 E 2.5(,S)-.4 G
+(RI International, Menlo P)304.48 393.6 Q(ark, California.)-.15 E(1978.)5 E
+69.39([NBS80] National)72 409.8 R 1.46(Bureau of Standards,)3.96 F F1 1.46
+(Speci\214cation of a Dr)3.96 F 1.46(aft Messa)-.15 F 1.66 -.1(ge F)-.1 H 1.46
+(ormat Stan-)-.95 F(dar)180 421.8 Q(d.)-.37 E F0(Report No. ICST/CBOS 80-2.)5 E
+(October 1980.)5 E 60.51([Neigus73] Neigus,)72 438 R(N.,)5.186 E F1 -.45(Fi)
+5.186 G 2.686(le T).45 F -.15(ra)-.55 G 2.686(nsfer Pr).15 F 2.686
+(otocol for the ARP)-.45 F 5.187(AN)-.9 G(etwork.)402.599 438 Q F0 2.687
+(RFC 542, NIC)7.687 F 2.5(17759. In)180 450 R 2.5([Feinler78]. August,)2.5 F
+(1973.)2.5 E([No)72 466.2 Q 55.21(witz78a] No)-.25 F 1.633
+(witz, D. A., and Lesk, M. E.,)-.25 F F1 4.132(AD)4.132 G 1.632
+(ial-Up Network of UNIX Systems.)338.9 466.2 R F0(Bell)6.632 E 5.403
+(Laboratories. In)180 478.2 R 2.904(UNIX Programmer')5.403 F 5.404(sM)-.55 G
+2.904(anual, Se)356.024 478.2 R -.15(ve)-.25 G 2.904(nth Edition, V).15 F 2.904
+(olume 2.)-1.29 F(August, 1978.)180 490.2 Q([No)72 506.4 Q 54.65(witz78b] No)
+-.25 F .633(witz, D. A.,)-.25 F F1 .632(Uucp Implementation Description.)3.132
+F F0 .632(Bell Laboratories.)5.632 F .632(In UNIX)5.632 F(Programmer')180 518.4
+Q 2.5(sM)-.55 G(anual, Se)248.05 518.4 Q -.15(ve)-.25 G(nth Edition, V).15 E
+(olume 2.)-1.29 E(October)5 E 2.5(,1)-.4 G(978.)431.22 518.4 Q 64.39
+([Postel74] Postel,)72 534.6 R .24(J., and Neigus, N., Re)2.74 F .241
+(vised FTP Reply Codes.)-.25 F .241(RFC 640, NIC 30843.)5.241 F(In)5.241 E 2.5
+([Feinler78]. June,)180 546.6 R(1974.)2.5 E 64.39([Postel77] Postel,)72 562.8 R
+(J.,)2.5 E F1(Mail Pr)2.5 E(otocol.)-.45 E F0(NIC 29588.)5 E(In [Feinler78].)5
+E(No)5 E -.15(ve)-.15 G(mber 1977.).15 E 59.95([Postel79a] Postel,)72 579 R
+(J.,)3.144 E F1 .644(Internet Messa)3.144 F .844 -.1(ge P)-.1 H -.45(ro).1 G
+(tocol.).45 E F0 .644(RFC 753, IEN 85.)5.644 F(Netw)5.644 E .644
+(ork Information)-.1 F(Center)180 591 Q 2.5(,S)-.4 G(RI International, Menlo P)
+216.82 591 Q(ark, California.)-.15 E(March 1979.)5 E 59.39([Postel79b] Postel,)
+72 607.2 R 1.305(J. B.,)3.805 F F1 1.305(An Internetwork Messa)3.805 F 1.505
+-.1(ge S)-.1 H(tructur).1 E -.15(e.)-.37 G F0(In)6.456 E F1(Pr)3.806 E 1.306
+(oceedings of the Sixth)-.45 F(Data Communications Symposium,)180 619.2 Q F0
+2.5(IEEE. Ne)2.5 F 2.5(wY)-.25 G 2.5(ork. No)379.74 619.2 R -.15(ve)-.15 G
+(mber 1979.).15 E 64.39([Postel80] Postel,)72 635.4 R .639(J. B.,)3.139 F F1
+3.139(AS)3.139 G(tructur)248.676 635.4 Q .639(ed F)-.37 F .639(ormat for T)
+-1.05 F -.15(ra)-.55 G .639(nsmission of Multi-Media Documents.).15 F F0 .418
+(RFC 767.)180 647.4 R(Netw)5.419 E .419(ork Information Center)-.1 F 2.919(,S)
+-.4 G .419(RI International, Menlo P)350.474 647.4 R .419(ark, Califor)-.15 F
+(-)-.2 E 2.5(nia. August)180 659.4 R(1980.)2.5 E 64.39([Postel82] Postel,)72
+675.6 R 2.05(J. B.,)4.55 F F1 2.05(Simple Mail T)4.55 F -.15(ra)-.55 G 2.05
+(nsfer Pr).15 F(otocol.)-.45 E F0 2.05(RFC821 \(obsoleting RFC788\).)7.05 F
+(Netw)180 687.6 Q .273(ork Information Center)-.1 F 2.774(,S)-.4 G .274
+(RI International, Menlo P)305.3 687.6 R .274(ark, California.)-.15 F(August)
+5.274 E(1982.)180 699.6 Q/F2 10/Times-Bold@0 SF 187.28(SMM:9-12 SENDMAIL)72 756
+R 2.5<8a41>2.5 G 2.5(nI)383.99 756 S(nter)395.94 756 Q(netw)-.15 E
+(ork Mail Router)-.1 E EP
+%%Page: 13 13
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(SENDMAIL \212 An Inter)72 60 Q(netw)-.15 E
+(ork Mail Router)-.1 E(SMM:9-13)457.9 60 Q/F1 10/Times-Roman@0 SF 55.5
+([Schmidt79] Schmidt,)72 96 R(E.,)2.972 E/F2 10/Times-Italic@0 SF .472(An Intr)
+2.972 F .472(oduction to the Berk)-.45 F(ele)-.1 E 2.972(yN)-.3 G(etwork.)
+369.664 96 Q F1(Uni)5.472 E -.15(ve)-.25 G .472(rsity of California,).15 F
+(Berk)180 108 Q(ele)-.1 E 2.5(yC)-.15 G 2.5(alifornia. 1979.)225.02 108 R 59.95
+([Shoens79] Shoens,)72 124.2 R(K.,)4.894 E F2 2.394(Mail Refer)4.894 F 2.394
+(ence Manual.)-.37 F F1(Uni)7.394 E -.15(ve)-.25 G 2.395
+(rsity of California, Berk).15 F(ele)-.1 E 6.195 -.65(y. I)-.15 H(n).65 E
+(UNIX Programmer')180 136.2 Q 2.5(sM)-.55 G(anual, Se)275.54 136.2 Q -.15(ve)
+-.25 G(nth Edition, V).15 E(olume 2C.)-1.29 E(December 1979.)5 E 60.51
+([Sluizer81] Sluizer)72 152.4 R 2.872(,S)-.4 G .372(., and Postel, J. B.,)
+218.862 152.4 R F2 .372(Mail T)2.872 F -.15(ra)-.55 G .372(nsfer Pr).15 F
+(otocol.)-.45 E F1 .371(RFC 780.)5.371 F(Netw)5.371 E .371(ork Infor)-.1 F(-)
+-.2 E(mation Center)180 164.4 Q 2.5(,S)-.4 G(RI International, Menlo P)247.1
+164.4 Q(ark, California.)-.15 E(May 1981.)5 E 52.72([Solomon81] Solomon,)72
+180.6 R .96(M., Landweber)3.46 F 3.46(,L)-.4 G .96
+(., and Neuhengen, D., \231The Design of the CSNET)296.08 180.6 R(Name Serv)180
+192.6 Q(er)-.15 E 3.9 -.7(.\232 C)-.55 H(S-DN-2, Uni).7 E -.15(ve)-.25 G
+(rsity of W).15 E(isconsin, Madison.)-.4 E(No)5 E -.15(ve)-.15 G(mber 1981.).15
+E 78.28([Su82] Su,)72 208.8 R(Za)4.344 E 1.844(w-Sing, and Postel, Jon,)-.15 F
+F2 1.844(The Domain Naming Con)4.344 F 1.844(vention for Internet)-.4 F 1.717
+(User Applications.)180 220.8 R F1 4.217(RFC819. Netw)6.717 F 1.717
+(ork Information Center)-.1 F 4.217(,S)-.4 G 1.718(RI International,)436.182
+220.8 R(Menlo P)180 232.8 Q(ark, California.)-.15 E(August 1982.)5 E([UNIX83])
+72 249 Q F2 2.12(The UNIX Pr)180 249 R -.1(og)-.45 G -.15(ra).1 G(mmer').15 E
+4.62(sM)-.4 G 2.12(anual, Se)298.3 249 R 2.12(venth Edition,)-.15 F F1 -.6(Vi)
+4.62 G 2.12(rtual V).6 F 2.12(AX-11 V)-1.35 F(ersion,)-1.11 E -1.29(Vo)180 261
+S 1.027(lume 1.)1.29 F 1.027(Bell Laboratories, modi\214ed by the Uni)6.027 F
+-.15(ve)-.25 G 1.027(rsity of California, Berk).15 F(e-)-.1 E(le)180 273 Q 1.3
+-.65(y, C)-.15 H 2.5(alifornia. March,).65 F(1983.)2.5 E EP
+%%Trailer
+end
+%%EOF
diff --git a/usr.sbin/sendmail/doc/op/op.me b/usr.sbin/sendmail/doc/op/op.me
new file mode 100644 (file)
index 0000000..debbba1
--- /dev/null
@@ -0,0 +1,6336 @@
+.\" Copyright (c) 1983 Eric P. Allman
+.\" Copyright (c) 1983, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)op.me       8.1 (Berkeley) 6/8/93
+.\"
+.\" eqn op.me | pic | troff -me
+.eh 'SMM:08-%''Sendmail Installation and Operation Guide'
+.oh 'Sendmail Installation and Operation Guide''SMM:08-%'
+.\" SD is lib if sendmail is installed in /usr/lib, sbin if in /usr/sbin
+.ds SD sbin
+.nr si 3n
+.de $0
+.(x
+.in \\$3u*3n
+.ti -3n
+\\$2.  \\$1
+.)x
+..
+.de $C
+.(x
+.in 0
+\\$1 \\$2.  \\$3
+.)x
+..
+.+c
+.(l C
+.sz 16
+.b SENDMAIL
+.sz 12
+.sp
+.b "INSTALLATION AND OPERATION GUIDE"
+.sz 10
+.sp
+.r
+Eric Allman
+University of California, Berkeley
+Mammoth Project
+eric@CS.Berkeley.EDU
+.sp
+Version 8.1
+.sp
+For Sendmail Version 8.1
+.)l
+.sp 2
+.pp
+.i Sendmail
+implements a general purpose internetwork mail routing facility
+under the UNIX*
+.(f
+*UNIX is a trademark of Bell Laboratories.
+.)f
+operating system.
+It is not tied to any one transport protocol \*-
+its function may be likened to a crossbar switch,
+relaying messages from one domain into another.
+In the process,
+it can do a limited amount of message header editing
+to put the message into a format that is appropriate
+for the receiving domain.
+All of this is done under the control of a configuration file.
+.pp
+Due to the requirements of flexibility
+for
+.i sendmail ,
+the configuration file can seem somewhat unapproachable.
+However, there are only a few basic configurations
+for most sites,
+for which standard configuration files have been supplied.
+Most other configurations
+can be built by adjusting an existing configuration files
+incrementally.
+.pp
+.i Sendmail
+is based on
+RFC822 (Internet Mail Format Protocol),
+RFC821 (Simple Mail Transport Protocol),
+RFC1123 (Internet Host Requirements),
+and
+RFC1425 (SMTP Service Extensions).
+However, since
+.i sendmail
+is designed to work in a wider world,
+in many cases it can be configured to exceed these protocols.
+These cases are described herein.
+.pp
+Although
+.i sendmail
+is intended to run
+without the need for monitoring,
+it has a number of features
+that may be used to monitor or adjust the operation
+under unusual circumstances.
+These features are described.
+.pp
+Section one describes how to do a basic
+.i sendmail
+installation.
+Section two
+explains the day-to-day information you should know
+to maintain your mail system.
+If you have a relatively normal site,
+these two sections should contain sufficient information
+for you to install
+.i sendmail
+and keep it happy.
+Section three
+describes some parameters that may be safely tweaked.
+Section four
+has information regarding the command line arguments.
+Section five
+contains the nitty-gritty information about the configuration
+file.
+This section is for masochists
+and people who must write their own configuration file.
+Section six
+gives a brief description of differences
+in this version of
+.i sendmail .
+The appendixes give a brief
+but detailed explanation of a number of features
+not described in the rest of the paper.
+.bp 5
+.sh 1 "BASIC INSTALLATION"
+.pp
+.i
+This section is a very rough rewrite;
+please don't assume that it is already completely correct.
+However,
+please send me suggestions so that later versions of this document
+can be more accurate.
+.pp
+There are two basic steps to installing sendmail.
+The hard part is to build the configuration table.
+This is a file that sendmail reads when it starts up
+that describes the mailers it knows about,
+how to parse addresses,
+how to rewrite the message header,
+and the settings of various options.
+Although the configuration table is quite complex,
+a configuration can usually be built
+by adjusting an existing off-the-shelf configuration.
+The second part is actually doing the installation,
+i.e., creating the necessary files, etc.
+.pp
+The remainder of this section will describe the installation of sendmail
+assuming you can use one of the existing configurations
+and that the standard installation parameters are acceptable.
+All pathnames and examples
+are given from the root of the
+.i sendmail
+subtree,
+normally
+.i /usr/src/usr.\*(SD/sendmail
+on 4.3BSD.
+.pp
+If you are loading this off the tape,
+continue with the next session.
+If you have a running binary already on your system,
+you should probably skip to section 1.2.
+.sh 2 "Compiling Sendmail"
+.pp
+All sendmail source is in the
+.i src
+subdirectory.
+If you are running on a 4.4BSD system,
+compile by typing
+.q make .
+On other systems, you may have to make some other adjustments.
+.sh 3 "Old versions of make"
+.pp
+If you are not running the new version of
+.b make
+you will probably have to use
+.(b
+make \-f Makefile.dist
+.)b
+This file does not assume several new syntaxes,
+including the
+.q +=
+syntax in macro definition
+and the
+.q ".include"
+syntax.
+.sh 3 "Compilation flags"
+.pp
+.i Sendmail
+supports two different formats
+for the
+.i aliases
+database.
+These formats are:
+.nr ii 1i
+.ip NDBM
+The ``new DBM'' format,
+available on nearly all systems around today.
+This was the preferred format prior to 4.4BSD.
+It allows such complex things as multiple databases
+and closing a currently open database.
+.ip NEWDB
+The new database package from Berkeley.
+If you have this, use it.
+It allows
+long records,
+multiple open databases,
+real in-memory caching,
+and so forth.
+You can define this in conjunction with one of the other two;
+if you do,
+old databases are read,
+but when a new database is created it will be in NEWDB format.
+As a nasty hack,
+if you have NEWDB, NDBM, and YPCOMPAT defined,
+and if the file
+.i /var/yp/Makefile
+exists and is readable,
+.i sendmail
+will create both new and old versions of the alias file
+during a
+.i newalias
+command.
+This is required because the Sun NIS/YP system
+reads the DBM version of the alias file.
+It's ugly as sin,
+but it works.
+.lp
+If neither of these are defined,
+.i sendmail
+reads the alias file into memory on every invocation.
+This can be slow and should be avoided.
+.pp
+System V based systems can define
+SYSTEM5
+to make several small adjustments.
+This changes the handling of timezones
+and uses the much less efficient
+.i lockf
+call in preference to
+.i flock .
+These can be specified separately using the compilation flags
+SYS5TZ
+and
+LOCKF
+respectively.
+.pp
+If you don't have the
+.i unsetenv
+routine in your system library, define the UNSETENV compilation flag.
+.pp
+You may also have to define the compilation variable LA_TYPE
+to describe how your load average is computed.
+This and other flags are detailed in section 6.1.
+.sh 3 "Compilation and installation"
+.pp
+After making the local system configuration described above,
+You should be able to compile and install the system.
+Compilation can be performed using
+.q make\**
+.(f
+\**where you may have to replace
+.q make
+with
+.q "make \-f Makefile.dist"
+as appropriate.
+.)f
+in the
+.b sendmail/src
+directory.
+You may be able to install using
+.(b
+make install
+.)b
+This should install the binary in
+/usr/\*(SD
+and create links from
+/usr/bin/newaliases
+and
+/usr/bin/mailq
+to
+/usr/\*(SD/sendmail.
+On BSD4.4 systems it will also format and install man pages.
+.sh 2 "Configuration Files"
+.pp
+.i Sendmail
+cannot operate without a configuration file.
+The configuration defines the mail systems understood at this site,
+how to access them,
+how to forward email to remote mail systems,
+and a number of tuning parameters.
+This configuration file is detailed
+in the later portion of this document.
+.pp
+The
+.i sendmail
+configuration can be daunting at first.
+The world is complex,
+and the mail configuration reflects that.
+The distribution includes an m4-based configuration package
+that hides a lot of the complexity.
+.pp
+These configuration files are simpler than old versions
+largely because the world has become simpler;
+in particular,
+text-based host files are officially eliminated,
+obviating the need to
+.q hide
+hosts behind a registered internet gateway.
+.pp
+These files also assume that most of your neighbors
+use domain-based UUCP addressing;
+that is,
+instead of naming hosts as
+.q host!user
+they will use
+.q host.domain!user .
+The configuration files can be customized to work around this,
+but it is more complex.
+.pp
+I haven't tested these yet on an isolated LAN environment
+with a single UUCP connection to the outside world.
+If you are in such an environment,
+please send comments to
+sendmail@okeeffe.CS.Berkeley.EDU.
+.pp
+Our configuration files are processed by
+.i m4
+to facilitate local customization;
+the directory
+.i cf
+of the
+sendmail
+distribution directory
+contains the source files.
+This directory contains several subdirectories:
+.nr ii 1i
+.ip cf
+Both site-dependent and site-independent descriptions of hosts.
+These can be literal host names
+(e.g.,
+.q ucbvax.mc )
+when the hosts are gateways
+or more general descriptions
+(such as
+.q "tcpproto.mc"
+as a general description of an SMTP-connected host
+or
+.q "uucpproto.mc"
+as a general description of a UUCP-connected host).
+Files ending
+.b \&.mc
+(``Master Configuration'')
+are the input descriptions;
+the output is in the corresponding
+.b \&.cf
+file.
+The general structure of these files is described below.
+.ip domain
+Site-dependent subdomain descriptions.
+These are tied to the way your organization wants to do addressing.
+For example,
+.b domain/cs.exposed.m4
+is our description for hosts in the CS.Berkeley.EDU subdomain
+that want their individual hostname to be externally visible;
+.b domain/cs.hidden.m4
+is the same except that the hostname is hidden
+(everything looks like it comes from CS.Berkeley.EDU).
+These are referenced using the
+.sm DOMAIN
+.b m4
+macro in the
+.b \&.mc
+file.
+.ip feature
+Definitions of specific features that some particular host in your site
+might want.
+These are referenced using the
+.sm FEATURE
+.b m4
+macro.
+An example feature is
+use_cw_file
+(which tells sendmail to read an /etc/sendmail.cw file on startup
+to find the set of local names).
+.ip hack
+Local hacks, referenced using the
+.sm HACK
+.b m4
+macro.
+Try to avoid these.
+The point of having them here is to make it clear that they smell.
+.ip m4
+Site-independent
+.i m4 (1)
+include files that have information common to all configuration files.
+This can be thought of as a
+.q #include
+directory.
+.ip mailer
+Definitions of mailers,
+referenced using the
+.sm MAILER
+.b m4
+macro.
+Defined mailer types in this distribution are
+fax,
+local,
+smtp,
+uucp,
+and usenet.
+.ip ostype
+Definitions describing various operating system environments
+(such as the location of support files).
+These are referenced using the
+.sm OSTYPE
+.b m4
+macro.
+.ip sh
+Shell files used by the
+.b m4
+build process.
+You shouldn't have to mess with these.
+.ip siteconfig
+Local site configuration information,
+such as UUCP connectivity.
+They normally contain lists of site information, for example:
+.(b
+SITE(contessa)
+SITE(hoptoad)
+SITE(nkainc)
+SITE(well)
+.)b
+They are referenced using the SITECONFIG macro:
+.(b
+SITECONFIG(site.config.file, name_of_site, X)
+.)b
+where
+.i X
+is the macro/class name to use.
+It can be U
+(indicating locally connected hosts)
+or one of W, X, or Y
+for up to three remote UUCP hubs.
+.pp
+If you are in a new domain
+(e.g., a company),
+you will probably want to create a
+cf/domain
+file for your domain.
+This consists primarily of relay definitions:
+for example, Berkeley's domain definition
+defines relays for
+BitNET,
+CSNET,
+and UUCP.
+Of these,
+only the UUCP relay is particularly specific
+to Berkeley.
+All of these are internet-style domain names.
+Please check to make certain they are reasonable for your domain.
+.pp
+Subdomains at Berkeley are also represented in the
+cf/domain
+directory.
+For example,
+the domain
+cs-exposed
+is the Computer Science subdomain with the local hostname shown
+to other users;
+cs-hidden
+makes users appear to be from the CS.Berkeley.EDU subdomain
+(with no local host information included).
+You will probably have to update this directory
+to be appropriate for your domain.
+.pp
+You will have to use or create
+.b \&.mc
+files in the
+.i cf/cf
+subdirectory for your hosts.
+This is detailed in the
+cf/README
+file.
+.sh 2 "Details of Installation Files"
+.pp
+This subsection describes the files that
+comprise the
+sendmail
+installation.
+.sh 3 "/usr/\*(SD/sendmail"
+.pp
+The binary for sendmail is located in /usr/\*(SD\**.
+.(f
+\**This is usually
+/usr/sbin
+on 4.4BSD and newer systems;
+many systems install it in
+/usr/lib.
+I understand it is in /usr/ucblib
+on System V Release 4.
+.)f
+It should be setuid root.
+For security reasons,
+/, /usr, and /usr/\*(SD
+should be owned by root, mode 755\**.
+.(f
+\**Some vendors ship them owned by bin;
+this creates a security hole that is not actually related to
+.i sendmail .
+Other important directories that should have restrictive ownerships
+and permissions are
+/bin, /usr/bin, /etc, /usr/etc, /lib, and /usr/lib.
+.)f
+.sh 3 "/etc/sendmail.cf"
+.pp
+This is the configuration file for sendmail.
+This and the frozen configuration file
+are the only two non-library file names compiled into sendmail\**.
+.(f
+\**The system libraries can reference other files;
+in particular, system library subroutines that
+sendmail
+calls probably reference
+.i /etc/passwd
+and
+.i /etc/resolv.conf .
+.)f
+Some older systems install it in
+.b /usr/lib/sendmail.cf .
+.pp
+If you want to move this file,
+change
+.i src/pathnames.h .
+.pp
+The configuration file is normally created
+using the distribution files described above.
+If you have a particularly unusual system configuration
+you may need to create a special version.
+The format of this file is detailed in later sections
+of this document.
+.sh 3 "/usr/ucb/newaliases"
+.pp
+If you are running delivermail,
+it is critical that the
+.i newaliases
+command be replaced.
+This can just be a link to
+.i sendmail :
+.(b
+rm \-f /usr/ucb/newaliases
+ln /usr/\*(SD/sendmail /usr/ucb/newaliases
+.)b
+This can be installed in whatever search path you prefer
+for your system.
+.sh 3 "/var/spool/mqueue"
+.pp
+The directory
+.i /var/spool/mqueue
+should be created to hold the mail queue.
+This directory should be mode 700
+and owned by root.
+.pp
+The actual path of this directory
+is defined in the
+.b Q
+option of the
+.i sendmail.cf
+file.
+.sh 3 "/etc/aliases*"
+.pp
+The system aliases are held in
+.q /etc/aliases .
+A sample is given in
+.q lib/aliases
+which includes some aliases which
+.i must
+be defined:
+.(b
+cp lib/aliases /etc/aliases
+.i "edit /etc/aliases"
+.)b
+You should extend this file with any aliases that are apropos to your system.
+.pp
+Normally
+.i sendmail
+looks at a version of these files maintained by the
+.i dbm \|(3)
+or
+.i db \|(3)
+routines.
+These are stored either in
+.q /etc/aliases.dir
+and
+.q /etc/aliases.pag
+or
+.q /etc/aliases.db
+depending on which database package you are using.
+These can initially be created as empty files,
+but they will have to be initialized promptly.
+These should be mode 644:
+.(b
+cp /dev/null /etc/aliases.dir
+cp /dev/null /etc/aliases.pag
+chmod 644 /etc/aliases.*
+newaliases
+.)b
+The
+.i db
+routines preset the mode reasonably,
+so this step can be skipped.
+The actual path of this file
+is defined in the
+.b A
+option of the
+.i sendmail.cf
+file.
+.sh 3 "/etc/sendmail.fc"
+.pp
+If you intend to install the frozen version of the configuration file
+(for quick startup)
+you should create the file /etc/sendmail.fc
+and initialize it.
+This step may be safely skipped.
+.(b
+cp /dev/null /etc/sendmail.fc
+chmod 644 /etc/sendmail.fc
+/usr/\*(SD/sendmail \-bz
+.)b
+In general, freeze files are not worth doing
+unless your disks are much faster than your CPU;
+this is seldom true any more.
+.pp
+If your
+.i sendmail
+was not compiled with
+.sm FROZENCONFIG
+defined, the
+.b \-bz
+flag will be ignored.
+.sh 3 "/etc/rc"
+.pp
+It will be necessary to start up the sendmail daemon when your system reboots.
+This daemon performs two functions:
+it listens on the SMTP socket for connections
+(to receive mail from a remote system)
+and it processes the queue periodically
+to insure that mail gets delivered when hosts come up.
+.pp
+Add the following lines to
+.q /etc/rc
+(or
+.q /etc/rc.local
+as appropriate)
+in the area where it is starting up the daemons:
+.(b
+if [ \-f /usr/\*(SD/sendmail \-a \-f /etc/sendmail.cf ]; then
+       (cd /var/spool/mqueue; rm \-f [lnx]f*)
+       /usr/\*(SD/sendmail \-bd \-q30m &
+       echo \-n ' sendmail' >/dev/console
+fi
+.)b
+The
+.q cd
+and
+.q rm
+commands insure that all lock files have been removed;
+extraneous lock files may be left around
+if the system goes down in the middle of processing a message.
+The line that actually invokes
+.i sendmail
+has two flags:
+.q \-bd
+causes it to listen on the SMTP port,
+and
+.q \-q30m
+causes it to run the queue every half hour.
+.pp
+Some people use a more complex startup script,
+removing zero length qf files and df files for which there is no qf file.
+For example:
+.(b
+# remove zero length qf files
+for qffile in qf*
+do
+       if [ \-r $qffile ]
+       then
+               if [ ! \-s $qffile ]
+               then
+                       echo \-n " <zero: $qffile>" > /dev/console
+                       rm \-f $qffile
+               fi
+       fi
+done
+# rename tf files to be qf if the qf does not exist
+for tffile in tf*
+do
+       qffile=`echo $tffile | sed 's/t/q/'`
+       if [ \-r $tffile \-a ! \-f $qffile ]
+       then
+               echo \-n " <recovering: $tffile>" > /dev/console
+               mv $tffile $qffile
+       else
+               echo \-n " <extra: $tffile>" > /dev/console
+               rm \-f $tffile
+       fi
+done
+# remove bogus qf files
+for dffile in df*
+do
+       qffile=`echo $dffile | sed 's/d/q/'`
+       if [ \-r $dffile \-a ! \-f $qffile ]
+       then
+               echo \-n " <incomplete: $dffile>" > /dev/console
+               rm \-f $dffile
+       fi
+done
+fi
+.)b
+.pp
+If you are not running a version of UNIX
+that supports Berkeley TCP/IP,
+do not include the
+.b \-bd
+flag.
+.sh 3 "/usr/lib/sendmail.hf"
+.pp
+This is the help file used by the SMTP
+.b HELP
+command.
+It should be copied from
+.q lib/sendmail.hf :
+.(b
+cp lib/sendmail.hf /usr/lib
+.)b
+The actual path of this file
+is defined in the
+.b H
+option of the
+.i sendmail.cf
+file.
+.sh 3 "/etc/sendmail.st"
+.pp
+If you wish to collect statistics
+about your mail traffic,
+you should create the file
+.q /etc/sendmail.st :
+.(b
+cp /dev/null /etc/sendmail.st
+chmod 666 /etc/sendmail.st
+.)b
+This file does not grow.
+It is printed with the program
+.q mailstats/mailstats.c.
+The actual path of this file
+is defined in the
+.b S
+option of the
+.i sendmail.cf
+file.
+.sh 3 "/usr/ucb/newaliases"
+.pp
+If
+.i sendmail
+is invoked as
+.q newaliases,
+it will simulate the
+.b \-bi
+flag
+(i.e., will rebuild the alias database;
+see below).
+This should be a link to /usr/\*(SD/sendmail.
+.sh 3 "/usr/ucb/mailq"
+.pp
+If
+.i sendmail
+is invoked as
+.q mailq,
+it will simulate the
+.b \-bp
+flag
+(i.e.,
+.i sendmail
+will print the contents of the mail queue;
+see below).
+This should be a link to /usr/\*(SD/sendmail.
+.sh 1 "NORMAL OPERATIONS"
+.sh 2 "``Quick'' Configuration Startup"
+.pp
+if the
+.sm FROZENCONFIG
+option is included during compilation,
+a precompiled (``frozen'') version of the configuration file
+can be created using the
+.b \-bz
+flag.
+This is really only worthwhile doing
+if you are on a slow processor with a relatively fast I/O system
+(a VAX 11/750 is a good example).
+Since it creates other problems,
+I recommend against using the frozen configuration
+on most current architectures.
+.pp
+To create the freeze file, use
+.(b
+/usr/\*(SD/sendmail \-bz
+.)b
+This creates the frozen configuration file
+.i /etc/sendmail.fc .
+This file is an image of
+.i sendmail 's
+data space after reading in the configuration file.
+If this file exists,
+it is used instead of
+.i /etc/sendmail.cf
+.i sendmail.fc
+must be rebuilt manually every time
+.i sendmail.cf
+is changed.
+.pp
+The frozen configuration file will be ignored
+if a
+.b \-C
+flag is specified
+or if sendmail detects that it is out of date.
+However, the heuristics are not strong
+so this should not be trusted.
+.sh 2 "The System Log"
+.pp
+The system log is supported by the
+.i syslogd \|(8)
+program.
+.sh 3 "Format"
+.pp
+Each line in the system log
+consists of a timestamp,
+the name of the machine that generated it
+(for logging from several machines
+over the local area network),
+the word
+.q sendmail: ,
+and a message.
+.sh 3 "Levels"
+.pp
+If you have
+.i syslogd \|(8)
+or an equivalent installed,
+you will be able to do logging.
+There is a large amount of information that can be logged.
+The log is arranged as a succession of levels.
+At the lowest level
+only extremely strange situations are logged.
+At the highest level,
+even the most mundane and uninteresting events
+are recorded for posterity.
+As a convention,
+log levels under ten
+are considered generally
+.q useful;
+log levels above 64
+are reserved for debugging purposes.
+Levels from 11\-64 are reserved for verbose information
+that some sites might want.
+.pp
+A complete description of the log levels
+is given in section 4.6.
+.sh 2 "The Mail Queue"
+.pp
+The mail queue should be processed transparently.
+However, you may find that manual intervention is sometimes necessary.
+For example,
+if a major host is down for a period of time
+the queue may become clogged.
+Although sendmail ought to recover gracefully when the host comes up,
+you may find performance unacceptably bad in the meantime.
+.sh 3 "Printing the queue"
+.pp
+The contents of the queue can be printed
+using the
+.i mailq
+command
+(or by specifying the
+.b \-bp
+flag to sendmail):
+.(b
+mailq
+.)b
+This will produce a listing of the queue id's,
+the size of the message,
+the date the message entered the queue,
+and the sender and recipients.
+.sh 3 "Forcing the queue"
+.pp
+.i Sendmail
+should run the queue automatically
+at intervals.
+The algorithm is to read and sort the queue,
+and then to attempt to process all jobs in order.
+When it attempts to run the job,
+.i sendmail
+first checks to see if the job is locked.
+If so, it ignores the job.
+.pp
+There is no attempt to insure that only one queue processor
+exists at any time,
+since there is no guarantee that a job cannot take forever
+to process
+(however,
+.i sendmail
+does include heuristics to try to abort jobs
+that are taking absurd amounts of time;
+technically, this violates RFC 821, but is blessed by RFC 1123).
+Due to the locking algorithm,
+it is impossible for one job to freeze the entire queue.
+However,
+an uncooperative recipient host
+or a program recipient
+that never returns
+can accumulate many processes in your system.
+Unfortunately,
+there is no completely general way to solve this.
+.pp
+In some cases,
+you may find that a major host going down
+for a couple of days
+may create a prohibitively large queue.
+This will result in
+.i sendmail
+spending an inordinate amount of time
+sorting the queue.
+This situation can be fixed by moving the queue to a temporary place
+and creating a new queue.
+The old queue can be run later when the offending host returns to service.
+.pp
+To do this,
+it is acceptable to move the entire queue directory:
+.(b
+cd /var/spool
+mv mqueue omqueue; mkdir mqueue; chmod 700 mqueue
+.)b
+You should then kill the existing daemon
+(since it will still be processing in the old queue directory)
+and create a new daemon.
+.pp
+To run the old mail queue,
+run the following command:
+.(b
+/usr/\*(SD/sendmail \-oQ/var/spool/omqueue \-q
+.)b
+The
+.b \-oQ
+flag specifies an alternate queue directory
+and the
+.b \-q
+flag says to just run every job in the queue.
+If you have a tendency toward voyeurism,
+you can use the
+.b \-v
+flag to watch what is going on.
+.pp
+When the queue is finally emptied,
+you can remove the directory:
+.(b
+rmdir /var/spool/omqueue
+.)b
+.sh 2 "The Alias Database"
+.pp
+The alias database exists in two forms.
+One is a text form,
+maintained in the file
+.i /etc/aliases.
+The aliases are of the form
+.(b
+name: name1, name2, ...
+.)b
+Only local names may be aliased;
+e.g.,
+.(b
+eric@prep.ai.MIT.EDU: eric@CS.Berkeley.EDU
+.)b
+will not have the desired effect.
+Aliases may be continued by starting any continuation lines
+with a space or a tab.
+Blank lines and lines beginning with a sharp sign
+(\c
+.q # )
+are comments.
+.pp
+The second form is processed by the
+.i dbm \|(3)
+(or
+.i db \|(3))
+library.
+This form is in the files
+.i /etc/aliases.dir
+and
+.i /etc/aliases.pag.
+This is the form that
+.i sendmail
+actually uses to resolve aliases.
+This technique is used to improve performance.
+.pp
+You can also use
+.sm NIS -based
+alias files.
+For example, the specification:
+.(b
+OA/etc/aliases
+OAnis:mail.aliases@my.nis.domain
+.)b
+will first search the /etc/aliases file
+and then the map named
+.q mail.aliases
+in
+.q my.nis.domain .
+.sh 3 "Rebuilding the alias database"
+.pp
+The DB or DBM version of the database
+may be rebuilt explicitly by executing the command
+.(b
+newaliases
+.)b
+This is equivalent to giving
+.i sendmail
+the
+.b \-bi
+flag:
+.(b
+/usr/\*(SD/sendmail \-bi
+.)b
+.pp
+If the
+.q D
+option is specified in the configuration,
+.i sendmail
+will rebuild the alias database automatically
+if possible
+when it is out of date.
+Auto-rebuild can be dangerous
+on heavily loaded machines
+with large alias files;
+if it might take more than five minutes
+to rebuild the database,
+there is a chance that several processes will start the rebuild process
+simultaneously.
+.pp
+If you have multiple aliases databases specified,
+the
+.b \-bi
+flag rebuilds all the database types it understands
+(for example, it can rebuild dbm databases but not nis databases).
+.sh 3 "Potential problems"
+.pp
+There are a number of problems that can occur
+with the alias database.
+They all result from a
+.i sendmail
+process accessing the DBM version
+while it is only partially built.
+This can happen under two circumstances:
+One process accesses the database
+while another process is rebuilding it,
+or the process rebuilding the database dies
+(due to being killed or a system crash)
+before completing the rebuild.
+.pp
+Sendmail has two techniques to try to relieve these problems.
+First, it ignores interrupts while rebuilding the database;
+this avoids the problem of someone aborting the process
+leaving a partially rebuilt database.
+Second,
+at the end of the rebuild
+it adds an alias of the form
+.(b
+@: @
+.)b
+(which is not normally legal).
+Before sendmail will access the database,
+it checks to insure that this entry exists\**.
+.(f
+\**The
+.q a
+option is required in the configuration
+for this action to occur.
+This should normally be specified
+unless you are running
+.i delivermail
+in parallel with
+.i sendmail.
+.)f
+.sh 3 "List owners"
+.pp
+If an error occurs on sending to a certain address,
+say
+.q \fIx\fP ,
+.i sendmail
+will look for an alias
+of the form
+.q owner-\fIx\fP
+to receive the errors.
+This is typically useful
+for a mailing list
+where the submitter of the list
+has no control over the maintenance of the list itself;
+in this case the list maintainer would be the owner of the list.
+For example:
+.(b
+unix-wizards: eric@ucbarpa, wnj@monet, nosuchuser,
+       sam@matisse
+owner-unix-wizards: eric@ucbarpa
+.)b
+would cause
+.q eric@ucbarpa
+to get the error that will occur
+when someone sends to
+unix-wizards
+due to the inclusion of
+.q nosuchuser
+on the list.
+.pp
+List owners also cause the envelope sender address to be modified.
+The contents of the owner alias are used if they point to a single user,
+otherwise the name of the alias itself is used.
+For this reason, and to obey Internet conventions,
+a typical scheme would be:
+.(b
+list:  some, set, of, addresses
+list-request:  list, administrators
+owner-list:    list-request
+.)b
+.sh 2 "User Information Database"
+.pp
+If you have a version of
+.i sendmail
+with the user information database
+compiled in,
+and you have specified one or more databases using the
+.b U
+option,
+the databases will be searched for a
+.i user :maildrop
+entry.
+If found, the mail will be sent to the specified address.
+.pp
+If the first token passed to user part of the
+.q local
+mailer is an at sign,
+the at sign will be stripped off
+and this step will be skipped.
+.sh 2 "Per-User Forwarding (.forward Files)"
+.pp
+As an alternative to the alias database,
+any user may put a file with the name
+.q .forward
+in his or her home directory.
+If this file exists,
+.i sendmail
+redirects mail for that user
+to the list of addresses listed in the .forward file.
+For example, if the home directory for user
+.q mckusick
+has a .forward file with contents:
+.(b
+mckusick@ernie
+kirk@calder
+.)b
+then any mail arriving for
+.q mckusick
+will be redirected to the specified accounts.
+.pp
+Actually, the configuration file defines a sequence of filenames to check.
+By default, this is the user's .forward file,
+but can be defined to be more generally using the
+.b J
+option.
+If you change this,
+you will have to inform your user base of the change;
+\&.forward is pretty well incorporated into the collective subconscious.
+.sh 2 "Special Header Lines"
+.pp
+Several header lines have special interpretations
+defined by the configuration file.
+Others have interpretations built into
+.i sendmail
+that cannot be changed without changing the code.
+These builtins are described here.
+.sh 3 "Return-Receipt-To:"
+.pp
+If this header is sent,
+a message will be sent to any specified addresses
+when the final delivery is complete,
+that is,
+when successfully delivered to a mailer with the
+.b l
+flag (local delivery) set in the mailer descriptor.
+.sh 3 "Errors-To:"
+.pp
+If errors occur anywhere during processing,
+this header will cause error messages to go to
+the listed addresses.
+This is intended for mailing lists.
+.pp
+The Errors-To: header was created in the bad old days
+when UUCP didn't understand the distinction between an envelope and a header;
+this was a hack to provide what should now be passed
+as the envelope sender address.
+It should go away.
+It is only used if the
+.b l
+option is set.
+.sh 3 "Apparently-To:"
+.pp
+If a message comes in with no recipients listed in the message
+(in a To:, Cc:, or Bcc: line)
+then
+.i sendmail
+will add an
+.q "Apparently-To:"
+header line for any recipients it is aware of.
+This is not put in as a standard recipient line
+to warn any recipients that the list is not complete.
+.pp
+At least one recipient line is required under RFC 822.
+.sh 2 "IDENT Protocol Support"
+.pp
+.i Sendmail
+supports the IDENT protocol as defined in RFC 1413.
+Although this enhances identification
+of the author of an email message
+by doing a ``call back'' to the originating system to include
+the owner of a particular TCP connection
+in the audit trail
+it is in no sense perfect;
+a determined forger can easily spoof the IDENT protocol.
+The following description is excerpted from RFC 1413:
+.ba +5
+6.  Security Considerations
+.lp
+The information returned by this protocol is at most as trustworthy
+as the host providing it OR the organization operating the host.  For
+example, a PC in an open lab has few if any controls on it to prevent
+a user from having this protocol return any identifier the user
+wants.  Likewise, if the host has been compromised the information
+returned may be completely erroneous and misleading.
+.lp
+The Identification Protocol is not intended as an authorization or
+access control protocol.  At best, it provides some additional
+auditing information with respect to TCP connections.  At worst, it
+can provide misleading, incorrect, or maliciously incorrect
+information.
+.lp
+The use of the information returned by this protocol for other than
+auditing is strongly discouraged.  Specifically, using Identification
+Protocol information to make access control decisions - either as the
+primary method (i.e., no other checks) or as an adjunct to other
+methods may result in a weakening of normal host security.
+.lp
+An Identification server may reveal information about users,
+entities, objects or processes which might normally be considered
+private.  An Identification server provides service which is a rough
+analog of the CallerID services provided by some phone companies and
+many of the same privacy considerations and arguments that apply to
+the CallerID service apply to Identification.  If you wouldn't run a
+"finger" server due to privacy considerations you may not want to run
+this protocol.
+.ba
+.sh 1 "ARGUMENTS"
+.pp
+The complete list of arguments to
+.i sendmail
+is described in detail in Appendix A.
+Some important arguments are described here.
+.sh 2 "Queue Interval"
+.pp
+The amount of time between forking a process
+to run through the queue
+is defined by the
+.b \-q
+flag.
+If you run in mode
+.b f
+or
+.b a
+this can be relatively large,
+since it will only be relevant
+when a host that was down comes back up.
+If you run in
+.b q
+mode
+it should be relatively short,
+since it defines the maximum amount of time that a message
+may sit in the queue.
+.pp
+RFC 1123 section 5.3.1.1 says that this value should be at least 30 minutes
+(although that probably doesn't make sense if you use ``queue-only'' mode).
+.sh 2 "Daemon Mode"
+.pp
+If you allow incoming mail over an IPC connection,
+you should have a daemon running.
+This should be set by your
+.i /etc/rc
+file using the
+.b \-bd
+flag.
+The
+.b \-bd
+flag and the
+.b \-q
+flag may be combined in one call:
+.(b
+/usr/\*(SD/sendmail \-bd \-q30m
+.)b
+.sh 2 "Forcing the Queue"
+.pp
+In some cases you may find that the queue has gotten clogged for some reason.
+You can force a queue run
+using the
+.b \-q
+flag (with no value).
+It is entertaining to use the
+.b \-v
+flag (verbose)
+when this is done to watch what happens:
+.(b
+/usr/\*(SD/sendmail \-q \-v
+.)b
+.pp
+You can also limit the jobs to those with a particular queue identifier,
+sender, or recipient
+using one of the queue modifiers.
+For example,
+.q \-qRberkeley
+restricts the queue run to jobs that have the string
+.q berkeley
+somewhere in one of the recipient addresses.
+Similarly,
+.q \-qSstring
+limits the run to particular senders and
+.q \-qIstring
+limits it to particular identifiers.
+.sh 2 "Debugging"
+.pp
+There are a fairly large number of debug flags
+built into
+.i sendmail .
+Each debug flag has a number and a level,
+where higher levels means to print out more information.
+The convention is that levels greater than nine are
+.q absurd,
+i.e.,
+they print out so much information that you wouldn't normally
+want to see them except for debugging that particular piece of code.
+Debug flags are set using the
+.b \-d
+option;
+the syntax is:
+.(b
+.ta \w'debug-option  'u
+debug-flag:    \fB\-d\fP debug-list
+debug-list:    debug-option [ , debug-option ]
+debug-option:  debug-range [ . debug-level ]
+debug-range:   integer | integer \- integer
+debug-level:   integer
+.)b
+where spaces are for reading ease only.
+For example,
+.(b
+\-d12  Set flag 12 to level 1
+\-d12.3        Set flag 12 to level 3
+\-d3-17        Set flags 3 through 17 to level 1
+\-d3-17.4      Set flags 3 through 17 to level 4
+.)b
+For a complete list of the available debug flags
+you will have to look at the code
+(they are too dynamic to keep this documentation up to date).
+.sh 2 "Trying a Different Configuration File"
+.pp
+An alternative configuration file
+can be specified using the
+.b \-C
+flag; for example,
+.(b
+/usr/\*(SD/sendmail \-Ctest.cf
+.)b
+uses the configuration file
+.i test.cf
+instead of the default
+.i /etc/sendmail.cf.
+If the
+.b \-C
+flag has no value
+it defaults to
+.i sendmail.cf
+in the current directory.
+.sh 2 "Changing the Values of Options"
+.pp
+Options can be overridden using the
+.b \-o
+flag.
+For example,
+.(b
+/usr/\*(SD/sendmail \-oT2m
+.)b
+sets the
+.b T
+(timeout) option to two minutes
+for this run only.
+.pp
+Some options have security implications.
+Sendmail allows you to set these,
+but refuses to run as root thereafter.
+.sh 1 "TUNING"
+.pp
+There are a number of configuration parameters
+you may want to change,
+depending on the requirements of your site.
+Most of these are set
+using an option in the configuration file.
+For example,
+the line
+.q OT5d
+sets option
+.q T
+to the value
+.q 5d
+(five days).
+.pp
+Most of these options have appropriate defaults for most sites.
+However,
+sites having very high mail loads may find they need to tune them
+as appropriate for their mail load.
+In particular,
+sites experiencing a large number of small messages,
+many of which are delivered to many recipients,
+may find that they need to adjust the parameters
+dealing with queue priorities.
+.sh 2 "Timeouts"
+.pp
+All time intervals are set
+using a scaled syntax.
+For example,
+.q 10m
+represents ten minutes, whereas
+.q 2h30m
+represents two and a half hours.
+The full set of scales is:
+.(b
+.ta 4n
+s      seconds
+m      minutes
+h      hours
+d      days
+w      weeks
+.)b
+.sh 3 "Queue interval"
+.pp
+The argument to the
+.b \-q
+flag
+specifies how often a sub-daemon will run the queue.
+This is typically set to between fifteen minutes
+and one hour.
+RFC 1123 section 5.3.1.1 recommends that this be at least 30 minutes.
+.sh 3 "Read timeouts"
+.pp
+It is possible to time out when reading the standard input
+or when reading from a remote SMTP server.
+These timeouts are set using the
+.b r
+option in the configuration file.
+The argument is a list of
+.i keyword=value
+pairs.
+The recognized keywords, their default values, and the minimum values
+allowed by RFC 1123 section 5.3.2 are:
+.nr ii 1i
+.ip initial
+The wait for the initial 220 greeting message
+[5m, 5m].
+.ip helo
+The wait for a reply from a HELO or EHLO command
+[5m, unspecified].
+This may require a host name lookup, so
+five minutes is probably a reasonable minimum.
+.ip mail\(dg
+The wait for a reply from a MAIL command
+[10m, 5m].
+.ip rcpt\(dg
+The wait for a reply from a RCPT command
+[1h, 5m].
+This should be long
+because it could be pointing at a list
+that takes a long time to expand.
+.ip datainit\(dg
+The wait for a reply from a DATA command
+[5m, 2m].
+.ip datablock\(dg
+The wait for reading a data block
+(that is, the body of the message).
+[1h, 3m].
+This should be long because it also applies to programs
+piping input to
+.i sendmail
+which have no guarantee of promptness.
+.ip datafinal\(dg
+The wait for a reply from the dot terminating a message.
+[1h, 10m].
+If this is shorter than the time actually needed
+for the receiver to deliver the message,
+duplicates will be generated.
+This is discussed in RFC 1047.
+.ip rset
+The wait for a reply from a RSET command
+[5m, unspecified].
+.ip quit
+The wait for a reply from a QUIT command
+[2m, unspecified].
+.ip misc
+The wait for a reply from miscellaneous (but short) commands
+such as NOOP (no-operation) and VERB (go into verbose mode).
+[2m, unspecified].
+.ip command\(dg
+In server SMTP,
+the time to wait for another command.
+[1h, 5m].
+.lp
+For compatibility with old configuration files,
+if no ``keyword='' is specified,
+all the timeouts marked with \(dg are set to the indicated value.
+.pp
+Many of the RFC 1123 minimum values
+may well be too short.
+.i Sendmail
+was designed to the RFC 822 protocols,
+which did not specify read timeouts;
+hence,
+.i sendmail
+does not guarantee to reply to messages promptly.
+In particular, a
+.q RCPT
+command specifying a mailing list
+will expand and verify the entire list;
+a large list on a slow system
+may take more than five minutes\**.
+.(f
+\**This verification includes looking up every address
+with the name server;
+this involves network delays,
+and can in some cases can be considerable.
+.)f
+I recommend a one hour timeout \*-
+since this failure is rare,
+a long timeout is not onerous
+and may ultimately help reduce network load.
+.pp
+For example, the line:
+.(b
+Orcommand=25m,datablock=3h
+.)b
+sets the server SMTP command timeout to 25 minutes
+and the input data block timeout to three hours.
+.sh 3 "Message timeouts"
+.pp
+After sitting in the queue for a few days,
+a message will time out.
+This is to insure that at least the sender is aware
+of the inability to send a message.
+The timeout is typically set to three days.
+This timeout is set using the
+.b T
+option in the configuration file.
+.pp
+The time of submission is set in the queue,
+rather than the amount of time left until timeout.
+As a result, you can flush messages that have been hanging
+for a short period
+by running the queue
+with a short message timeout.
+For example,
+.(b
+/usr/\*(SD/sendmail \-oT1d \-q
+.)b
+will run the queue
+and flush anything that is one day old.
+.pp
+Since this option is global,
+and since you can not
+.i "a priori"
+know how long another host outside your domain will be down,
+a five day timeout is recommended.
+This allows a recipient to fix the problem even if it occurs
+at the beginning of a long weekend.
+RFC 1123 section 5.3.1.1 says that this parameter
+should be ``at least 4\-5 days''.
+.pp
+The
+.b T
+option can also take a second timeout indicating a time after which
+a warning message should be sent;
+the two timeouts are separated by a slash.
+For example, the value
+.(b
+5d/4h
+.)b
+causes email to fail after five days,
+but a warning message will be sent after four hours.
+This should be large enough that the message will have been tried
+several times.
+.sh 2 "Forking During Queue Runs"
+.pp
+By setting the
+.b Y
+option,
+.i sendmail
+will fork before each individual message
+while running the queue.
+This will prevent
+.i sendmail
+from consuming large amounts of memory,
+so it may be useful in memory-poor environments.
+However, if the
+.b Y
+option is not set,
+.i sendmail
+will keep track of hosts that are down during a queue run,
+which can improve performance dramatically.
+.pp
+If the
+.b Y
+option is set,
+.i sendmail
+can not use connection caching.
+.sh 2 "Queue Priorities"
+.pp
+Every message is assigned a priority when it is first instantiated,
+consisting of the message size (in bytes)
+offset by the message class times the
+.q "work class factor"
+and the number of recipients times the
+.q "work recipient factor."
+The priority is used to order the queue.
+Higher numbers for the priority mean that the message will be processed later
+when running the queue.
+.pp
+The message size is included so that large messages are penalized
+relative to small messages.
+The message class allows users to send
+.q "high priority"
+messages by including a
+.q Precedence:
+field in their message;
+the value of this field is looked up in the
+.b P
+lines of the configuration file.
+Since the number of recipients affects the amount of load a message presents
+to the system,
+this is also included into the priority.
+.pp
+The recipient and class factors
+can be set in the configuration file using the
+.b y
+and
+.b z
+options respectively.
+They default to 30000 (for the recipient factor)
+and 1800
+(for the class factor).
+The initial priority is:
+.EQ
+pri = size - (class times bold z) + (nrcpt times bold y)
+.EN
+(Remember, higher values for this parameter actually mean
+that the job will be treated with lower priority.)
+.pp
+The priority of a job can also be adjusted each time it is processed
+(that is, each time an attempt is made to deliver it)
+using the
+.q "work time factor,"
+set by the
+.b Z
+option.
+This is added to the priority,
+so it normally decreases the precedence of the job,
+on the grounds that jobs that have failed many times
+will tend to fail again in the future.
+The
+.b Z
+option defaults to 90000.
+.sh 2 "Load Limiting"
+.pp
+.i Sendmail
+can be asked to queue (but not deliver)
+mail if the system load average gets too high
+using the
+.b x
+option.
+When the load average exceeds the value of the
+.b x
+option,
+the delivery mode is set to
+.b q
+(queue only)
+if the
+.i "Queue Factor"
+(\c
+.b q
+option)
+divided by the difference in the current load average and the
+.b x
+option
+plus one
+exceeds the priority of the message \(em
+that is, the message is queued iff:
+.EQ
+pri > { bold q } over { LA - { bold x } + 1 }
+.EN
+The
+.b q
+option defaults to 200000,
+so each point of load average is worth 200000
+priority points
+(as described above).
+.pp
+For drastic cases,
+the
+.b X
+option defines a load average at which sendmail will refuse
+to accept network connections.
+Locally generated mail
+(including incoming UUCP mail)
+is still accepted.
+.sh 2 "Delivery Mode"
+.pp
+There are a number of delivery modes that
+.i sendmail
+can operate in,
+set by the
+.q d
+configuration option.
+These modes
+specify how quickly mail will be delivered.
+Legal modes are:
+.(b
+.ta 4n
+i      deliver interactively (synchronously)
+b      deliver in background (asynchronously)
+q      queue only (don't deliver)
+.)b
+There are tradeoffs.
+Mode
+.q i
+passes the maximum amount of information to the sender,
+but is hardly ever necessary.
+Mode
+.q q
+puts the minimum load on your machine,
+but means that delivery may be delayed for up to the queue interval.
+Mode
+.q b
+is probably a good compromise.
+However, this mode can cause large numbers of processes
+if you have a mailer that takes a long time to deliver a message.
+.pp
+If you run in mode
+.q q
+(queue only)
+.i sendmail
+will not expand aliases and follow .forward files
+upon initial receipt of the mail.
+This speeds up the response to RCPT commands.
+.sh 2 "Log Level"
+.pp
+The level of logging can be set for sendmail.
+The default using a standard configuration table is level 9.
+The levels are as follows:
+.nr ii 0.5i
+.ip 0
+No logging.
+.ip 1
+Serious system failures and potential security problems.
+.ip 2
+Lost communications (network problems) and protocol failures.
+.ip 3
+Other serious failures.
+.ip 4
+Minor failures.
+.ip 5
+Message collection statistics.
+.ip 6
+Creation of error messages,
+VRFY and EXPN commands.
+.ip 7
+Delivery failures (host or user unknown, etc.).
+.ip 8
+Successful deliveries.
+.ip 9
+Messages being deferred
+(due to a host being down, etc.).
+.ip 10
+Database expansion (alias, forward, and userdb lookups).
+.ip 15
+Automatic alias database rebuilds.
+.ip 20
+Logs attempts to run locked queue files.
+These are not errors,
+but can be useful to note if your queue appears to be clogged.
+.ip 30
+Lost locks (only if using lockf instead of flock).
+.lp
+Additionally,
+values above 64 are reserved for extremely verbose debuggging output.
+No normal site would ever set these.
+.sh 2 "File Modes"
+.pp
+There are a number of files
+that may have a number of modes.
+The modes depend on what functionality you want
+and the level of security you require.
+.sh 3 "To suid or not to suid?"
+.pp
+.i Sendmail
+can safely be made
+setuid to root.
+At the point where it is about to
+.i exec \|(2)
+a mailer,
+it checks to see if the userid is zero;
+if so,
+it resets the userid and groupid to a default
+(set by the
+.b u
+and
+.b g
+options).
+(This can be overridden
+by setting the
+.b S
+flag to the mailer
+for mailers that are trusted
+and must be called as root.)
+However,
+this will cause mail processing
+to be accounted
+(using
+.i sa \|(8))
+to root
+rather than to the user sending the mail.
+.sh 3 "Should my alias database be writable?"
+.pp
+At Berkeley
+we have the alias database
+(/etc/aliases*)
+mode 644.
+While this is not as flexible as if the database
+were more 666, it avoids potential security problems
+with a globally writable database.
+.pp
+The database that
+.i sendmail
+actually used
+is represented by the two files
+.i aliases.dir
+and
+.i aliases.pag
+(both in /etc)
+(or
+.i aliases.db
+if you are running with the new Berkeley database primitives).
+The mode on these files should match the mode
+on /etc/aliases.
+If
+.i aliases
+is writable
+and the
+DBM
+files
+(\c
+.i aliases.dir
+and
+.i aliases.pag )
+are not,
+users will be unable to reflect their desired changes
+through to the actual database.
+However,
+if
+.i aliases
+is read-only
+and the DBM files are writable,
+a slightly sophisticated user
+can arrange to steal mail anyway.
+.pp
+If your DBM files are not writable by the world
+or you do not have auto-rebuild enabled
+(with the
+.q D
+option),
+then you must be careful to reconstruct the alias database
+each time you change the text version:
+.(b
+newaliases
+.)b
+If this step is ignored or forgotten
+any intended changes will also be ignored or forgotten.
+.sh 2 "Connection Caching"
+.pp
+When processing the queue,
+.b sendmail
+will try to keep the last few open connections open
+to avoid startup and shutdown costs.
+This only applies to IPC connections.
+.pp
+When trying to open a connection
+the cache is first searched.
+If an open connection is found, it is probed to see if it is still active
+by sending a
+.sm NOOP
+command.
+It is not an error if this fails;
+instead, the connection is closed and reopened.
+.pp
+Two parameters control the connection cache.
+The
+.b k
+option defines the number of simultaneous open connections
+that will be permitted.
+If it is set to zero,
+connections will be closed as quickly as possible.
+The default is one.
+This should be set as appropriate for your system size;
+it will limit the amount of system resources that
+.b sendmail
+will use during queue runs.
+.pp
+The
+.b K
+option specifies the maximum time that any cached connection
+will be permitted to idle.
+When the idle time exceeds this value
+the connection is closed.
+This number should be small
+(under ten minutes)
+to prevent you from grabbing too many resources
+from other hosts.
+The default is five minutes.
+.sh 2 "Name Server Access"
+.pp
+If your system supports the name server,
+then the probability is that
+.i sendmail
+will be using it regardless of how you configure sendmail.
+However, if you have nameserver support
+which you are not using,
+sendmail will get a
+.q "connection refused"
+message when it tries to connect to the name server
+(either by calling
+.i gethostbyname
+or by trying to look up the MX records).
+If the
+.b I
+option is set,
+.i sendmail
+will interpret this to mean a temporary failure;
+otherwise, it ignores the name server data.
+If your name server is running properly,
+the setting of this option is not relevant;
+however, it is important that it be set properly
+to make error handling work properly.
+.pp
+This option also allows you to tweak name server options.
+The command line takes a series of flags as documented in
+.i resolver (3)
+(with the leading
+.q RES_
+deleted).
+Each can be preceded by an optional `+' or `\(mi'.
+For example, the line
+.(b
+OITrue +AAONLY \(miDNSRCH
+.)b
+turns on the AAONLY (accept authoritative answers only)
+and turns off the DNSRCH (search the domain path) options.
+Most resolver libraries default DNSRCH, DEFNAMES, and RECURSE
+flags on and all others off.
+Note the use of the initial ``True'' \*-
+this is for compatibility with previous versions of sendmail,
+but is not otherwise necessary.
+.pp
+Version level 1 configurations
+turn DNSRCH and DEFNAMES off when doing delivery lookups,
+but leave them on everywhere else.
+Version 6 of
+.i sendmail
+ignores them when doing canonification lookups
+(that is, when using $[ ... $]),
+and always does the search.
+If you don't want to do automatic name extension,
+don't call $[ ... $].
+.pp
+The search rules for $[ ... $] are somewhat different than usual.
+If the name (that is, the ``...'')
+has at least one dot, it always tries the unmodified name first.
+If that fails, it tries the reduced search path,
+and lastly tries the unmodified name
+(but only for names without a dot,
+since names with a dot have already been tried).
+This allows names such as
+``utc.CS''
+to match the site in Czechoslovakia
+rather than the site in your local Computer Science department.
+It also prefers A and CNAME records over MX records \*-
+that is, if it finds an MX record it makes note of it,
+but keeps looking.
+This way, if you have a wildcard MX record matching your domain,
+it will not assume that all names match.
+.sh 2 "Moving the Per-User Forward Files"
+.pp
+Some sites mount each user's home directory
+from a local disk on their workstation,
+so that local access is fast.
+However, the result is that .forward file lookups are slow.
+In some cases,
+mail can even be delivered on machines inappropriately
+because of a file server being down.
+The performance can be especially bad if you run the automounter.
+.pp
+The
+.b J
+option allows you to set a path of forward files.
+For example, the config file line
+.(b
+OJ/var/forward/$u:$z/.forward
+.)b
+would first look for a file with the same name as the user's login
+in /var/forward;
+if that is not found (or is inaccessible)
+the file
+.q \&.forward
+in the user's home directory is searched.
+A truly perverse site could also search by sender
+by using $r, $s, or $f.
+.pp
+If you create a directory such as /var/forward,
+it should be mode 1777
+(that is, the sticky bit should be set).
+Users should create the files mode 644.
+.sh 2 "Free Space"
+.pp
+On systems that have the
+.i statfs (2)
+system call,
+you can specify a minimum number of free blocks on the queue filesystem
+using the
+.b b
+option.
+If there are fewer than the indicated number of blocks free
+on the filesystem on which the queue is mounted
+the SMTP server will reject mail
+with the
+452 error code.
+This invites the SMTP client to try again later.
+.pp
+Beware of setting this option too high;
+it can cause rejection of email
+when that mail would be processed without difficulty.
+.pp
+This option can also specify an advertised
+.q "maximum message size"
+for hosts that speak ESMTP.
+.sh 2 "Privacy Flags"
+.pp
+The
+.b p
+option allows you to set certain
+``privacy''
+flags.
+Actually, many of them don't give you any extra privacy,
+rather just insisting that client SMTP servers
+use the HELO command
+before using certain commands.
+.pp
+The option takes a series of flag names;
+the final privacy is the inclusive or of those flags.
+For example:
+.(b
+Op needmailhelo, noexpn
+.)b
+insists that the HELO or EHLO command be used before a MAIL command is accepted
+and disables the EXPN command.
+.pp
+The
+.q restrictmailq
+option restricts printing the queue to the group that owns the queue directory.
+It is absurd to set this if you don't also protect the logs.
+.sh 2 "Send to Me Too"
+.pp
+Normally,
+.i sendmail
+deletes the (envelope) sender from any list expansions.
+For example, if
+.q matt
+sends to a list that contains
+.q matt
+as one of the members he won't get a copy of the message.
+If the
+.b \-m
+(me too)
+command line flag, or if the
+.b m
+option is set in the configuration file,
+this behaviour is supressed.
+Some sites like to run the
+.sm SMTP
+daemon with
+.b \-m .
+.sh 1 "THE WHOLE SCOOP ON THE CONFIGURATION FILE"
+.pp
+This section describes the configuration file
+in detail,
+including hints on how to write one of your own
+if you have to.
+.pp
+There is one point that should be made clear immediately:
+the syntax of the configuration file
+is designed to be reasonably easy to parse,
+since this is done every time
+.i sendmail
+starts up,
+rather than easy for a human to read or write.
+On the
+.q "future project"
+list is a
+configuration-file compiler.
+.pp
+An overview of the configuration file
+is given first,
+followed by details of the semantics.
+.sh 2 "Configuration File Lines"
+.pp
+The configuration file is organized as a series of lines,
+each of which begins with a single character
+defining the semantics for the rest of the line.
+Lines beginning with a space or a tab
+are continuation lines
+(although the semantics are not well defined in many places).
+Blank lines and lines beginning with a sharp symbol
+(`#')
+are comments.
+.sh 3 "R and S \*- rewriting rules"
+.pp
+The core of address parsing
+are the rewriting rules.
+These are an ordered production system.
+.i Sendmail
+scans through the set of rewriting rules
+looking for a match on the left hand side
+(LHS)
+of the rule.
+When a rule matches,
+the address is replaced by the right hand side
+(RHS)
+of the rule.
+.pp
+There are several sets of rewriting rules.
+Some of the rewriting sets are used internally
+and must have specific semantics.
+Other rewriting sets
+do not have specifically assigned semantics,
+and may be referenced by the mailer definitions
+or by other rewriting sets.
+.pp
+The syntax of these two commands are:
+.(b F
+.b S \c
+.i n
+.)b
+Sets the current ruleset being collected to
+.i n .
+If you begin a ruleset more than once
+it deletes the old definition.
+.(b F
+.b R \c
+.i lhs
+.i rhs
+.i comments
+.)b
+The
+fields must be separated
+by at least one tab character;
+there may be embedded spaces
+in the fields.
+The
+.i lhs
+is a pattern that is applied to the input.
+If it matches,
+the input is rewritten to the
+.i rhs .
+The
+.i comments
+are ignored.
+.pp
+Macro expansions of the form
+.b $ \c
+.i x
+are performed when the configuration file is read.
+Expansions of the form
+.b $& \c
+.i x
+are performed at run time using a somewhat less general algorithm.
+This for is intended only for referencing internally defined macros
+such as
+.b $h
+that are changed at runtime.
+.sh 4 "The left hand side"
+.pp
+The left hand side of rewriting rules contains a pattern.
+Normal words are simply matched directly.
+Metasyntax is introduced using a dollar sign.
+The metasymbols are:
+.(b
+.ta \w'\fB$=\fP\fIx\fP  'u
+\fB$*\fP       Match zero or more tokens
+\fB$+\fP       Match one or more tokens
+\fB$\-\fP      Match exactly one token
+\fB$=\fP\fIx\fP        Match any phrase in class \fIx\fP
+\fB$~\fP\fIx\fP        Match any word not in class \fIx\fP
+.)b
+If any of these match,
+they are assigned to the symbol
+.b $ \c
+.i n
+for replacement on the right hand side,
+where
+.i n
+is the index in the LHS.
+For example,
+if the LHS:
+.(b
+$\-:$+
+.)b
+is applied to the input:
+.(b
+UCBARPA:eric
+.)b
+the rule will match, and the values passed to the RHS will be:
+.(b
+.ta 4n
+$1     UCBARPA
+$2     eric
+.)b
+.pp
+Additionally, the LHS can include
+.b $@
+to match zero tokens.
+This is
+.i not
+bound to a
+.b $ \c
+.i N
+on the RHS, and is normally only used when it stands alone
+in order to match the null input.
+.sh 4 "The right hand side"
+.pp
+When the left hand side of a rewriting rule matches,
+the input is deleted and replaced by the right hand side.
+Tokens are copied directly from the RHS
+unless they begin with a dollar sign.
+Metasymbols are:
+.(b
+.ta \w'$#mailer\0\0\0'u
+\fB$\fP\fIn\fP Substitute indefinite token \fIn\fP from LHS
+\fB$[\fP\fIname\fP\fB$]\fP     Canonicalize \fIname\fP
+\fB$(\fP\fImap key\fP \fB$@\fP\fIarguments\fP \fB$:\fP\fIdefault\fP \fB$)\fP
+       Generalized keyed mapping function
+\fB$>\fP\fIn\fP        \*(lqCall\*(rq ruleset \fIn\fP
+\fB$#\fP\fImailer\fP   Resolve to \fImailer\fP
+\fB$@\fP\fIhost\fP     Specify \fIhost\fP
+\fB$:\fP\fIuser\fP     Specify \fIuser\fP
+.)b
+.pp
+The
+.b $ \c
+.i n
+syntax substitutes the corresponding value from a
+.b $+ ,
+.b $\- ,
+.b $* ,
+.b $= ,
+or
+.b $~
+match on the LHS.
+It may be used anywhere.
+.pp
+A host name enclosed between
+.b $[
+and
+.b $]
+is looked up using the
+.i gethostent \|(3)
+routines and replaced by the canonical name\**.
+.(f
+\**This is actually
+completely equivalent
+to $(host \fIhostname\fP$).
+In particular, a
+.b $:
+default can be used.
+.)f
+For example,
+.q $[csam$]
+might become
+.q lbl-csam.arpa
+and
+.q $[[128.32.130.2]$]
+would become
+.q vangogh.CS.Berkeley.EDU.
+.i Sendmail
+recognizes it's numeric IP address
+without calling the name server
+and replaces it with it's canonical name.
+.pp
+The
+.b $(
+\&...
+.b $)
+syntax is a more general form of lookup;
+it uses a named map instead of an implicit map.
+If no lookup is found, the indicted
+.i default
+is inserted;
+if no default is specified and no lookup matches,
+the value is left unchanged.
+.pp
+The
+.b $> \c
+.i n
+syntax
+causes the remainder of the line to be substituted as usual
+and then passed as the argument to ruleset
+.i n .
+The final value of ruleset
+.i n
+then becomes
+the substitution for this rule.
+.pp
+The
+.b $#
+syntax should
+.i only
+be used in ruleset zero.
+It causes evaluation of the ruleset to terminate immediately,
+and signals to sendmail that the address has completely resolved.
+The complete syntax is:
+.(b
+\fB$#\fP\fImailer\fP \fB$@\fP\fIhost\fP \fB$:\fP\fIuser\fP
+.)b
+This specifies the
+{mailer, host, user}
+3-tuple necessary to direct the mailer.
+If the mailer is local
+the host part may be omitted\**.
+.(f
+\**You may want to use it for special
+.q "per user"
+extensions.
+For example, at CMU you can send email to
+.q jgm+foo ;
+the part after the plus sign
+is not part of the user name,
+and is passed to the local mailer for local use.
+.)f
+The
+.i mailer
+must be a single word,
+but the
+.i host
+and
+.i user
+may be multi-part.
+If the
+.i mailer
+is the builtin IPC mailer,
+the
+.i host
+may be a colon-separated list of hosts
+that are searched in order for the first working address
+(exactly like MX records).
+.pp
+A RHS may also be preceded by a
+.b $@
+or a
+.b $:
+to control evaluation.
+A
+.b $@
+prefix causes the ruleset to return with the remainder of the RHS
+as the value.
+A
+.b $:
+prefix causes the rule to terminate immediately,
+but the ruleset to continue;
+this can be used to avoid continued application of a rule.
+The prefix is stripped before continuing.
+.pp
+The
+.b $@
+and
+.b $:
+prefixes may precede a
+.b $>
+spec;
+for example:
+.(b
+.ta 8n
+R$+    $: $>7 $1
+.)b
+matches anything,
+passes that to ruleset seven,
+and continues;
+the
+.b $:
+is necessary to avoid an infinite loop.
+.pp
+Substitution occurs in the order described,
+that is,
+parameters from the LHS are substituted,
+hostnames are canonicalized,
+.q subroutines
+are called,
+and finally
+.b $# ,
+.b $@ ,
+and
+.b $:
+are processed.
+.sh 4 "Semantics of rewriting rule sets"
+.pp
+There are five rewriting sets
+that have specific semantics.
+These are related as depicted by figure 2.
+.(z
+.hl
+.ie n \{\
+.(c
+                    +---+
+                 -->| 0 |-->resolved address
+                /   +---+
+               /            +---+   +---+
+              /        ---->| 1 |-->| S |--
+       +---+ / +---+  /     +---+   +---+  \e    +---+
+addr-->| 3 |-->| D |--                      --->| 4 |-->msg
+       +---+   +---+  \e     +---+   +---+  /    +---+
+                        --->| 2 |-->| R |--
+                            +---+   +---+
+.)c
+
+.\}
+.el .ie !"\*(.T"" \
+\{\
+.PS
+boxwid = 0.3i
+boxht = 0.3i
+movewid = 0.3i
+moveht = 0.3i
+linewid = 0.3i
+lineht = 0.3i
+
+       box invis "addr"; arrow
+Box3:  box "3"
+A1:    arrow
+BoxD:  box "D"; line; L1: Here
+C:     [
+       C1:     arrow; box "1"; arrow; box "S"; line; E1: Here
+               move to C1 down 0.5; right
+       C2:     arrow; box "2"; arrow; box "R"; line; E2: Here
+       ] with .w at L1 + (0.5, 0)
+       move to C.e right 0.5
+L4:    arrow; box "4"; arrow; box invis "msg"
+       line from L1 to C.C1
+       line from L1 to C.C2
+       line from C.E1 to L4
+       line from C.E2 to L4
+       move to BoxD.n up 0.6; right
+Box0:  arrow; box "0"
+       arrow; box invis "resolved address" width 1.3
+       line from 1/3 of the way between A1 and BoxD.w to Box0
+.PE
+.\}
+.el .sp 2i
+.ce
+Figure 2 \*- Rewriting set semantics
+.(c
+D \*- sender domain addition
+S \*- mailer-specific sender rewriting
+R \*- mailer-specific recipient rewriting
+.)c
+.hl
+.)z
+.pp
+Ruleset three
+should turn the address into
+.q "canonical form."
+This form should have the basic syntax:
+.(b
+local-part@host-domain-spec
+.)b
+If no
+.q @
+sign is specified,
+then the
+host-domain-spec
+.i may
+be appended from the
+sender address
+(if the
+.b C
+flag is set in the mailer definition
+corresponding to the
+.i sending
+mailer).
+Ruleset three
+is applied by sendmail
+before doing anything with any address.
+.pp
+Ruleset zero
+is applied after ruleset three
+to addresses that are going to actually specify recipients.
+It must resolve to a
+.i "{mailer, host, user}"
+triple.
+The
+.i mailer
+must be defined in the mailer definitions
+from the configuration file.
+The
+.i host
+is defined into the
+.b $h
+macro
+for use in the argv expansion of the specified mailer.
+.pp
+Rulesets one and two
+are applied to all sender and recipient addresses respectively.
+They are applied before any specification
+in the mailer definition.
+They must never resolve.
+.pp
+Ruleset four is applied to all addresses
+in the message.
+It is typically used
+to translate internal to external form.
+.sh 4 "IPC mailers"
+.pp
+Some special processing occurs
+if the ruleset zero resolves to an IPC mailer
+(that is, a mailer that has
+.q [IPC]
+listed as the Path in the
+.b M
+configuration line.
+The host name passed after
+.q $@
+has MX expansion performed;
+this looks the name up in DNS to find alternate delivery sites.
+.pp
+The host name can also be provided as a dotted quad in square brackets;
+for example:
+.(b
+[128.32.149.78]
+.)b
+This causes direct conversion of the numeric value
+to a TCP/IP host address.
+.pp
+The host name passed in after the
+.q $@
+may also be a colon-separated list of hosts.
+Each is separately MX expanded and the results are concatenated
+to make (essentially) one long MX list.
+The intent here is to create
+.q fake
+MX records that are not published in DNS
+for private internal networks.
+.pp
+As a final special case, the host name can be passed in
+as a text string
+in square brackets:
+.(b
+[ucbvax.berkeley.edu]
+.)b
+This form avoids the MX mapping.
+.b N.B.:
+This is intended only for situations where you have a network firewall,
+so that your MX record points to a gateway machine;
+this machine could then do direct delivery to machines
+within your local domain.
+Use of this feature directly violates RFC 1123 section 5.3.5:
+it should not be used lightly.
+.sh 3 "D \*- define macro"
+.pp
+Macros are named with a single character.
+These may be selected from the entire ASCII set,
+but user-defined macros
+should be selected from the set of upper case letters only.
+Lower case letters
+and special symbols
+are used internally.
+.pp
+The syntax for macro definitions is:
+.(b F
+.b D \c
+.i x\|val
+.)b
+where
+.i x
+is the name of the macro
+and
+.i val
+is the value it should have.
+.pp
+Macros are interpolated
+using the construct
+.b $ \c
+.i x ,
+where
+.i x
+is the name of the macro to be interpolated.
+This interpolation is done when the configuration file is read,
+except in
+.b M
+lines.
+The special construct
+.b $& \c
+.i x
+can be used in
+.b R
+lines to get deferred interpolation.
+.pp
+Conditionals can be specified using the syntax:
+.(b
+$?x text1 $| text2 $.
+.)b
+This interpolates
+.i text1
+if the macro
+.b $x
+is set,
+and
+.i text2
+otherwise.
+The
+.q else
+(\c
+.b $| )
+clause may be omitted.
+.pp
+Lower case macro names are reserved to have
+special semantics,
+used to pass information in or out of sendmail,
+and special characters are reserved to
+provide conditionals, etc.
+Upper case names
+(that is,
+.b $A
+through
+.b $Z )
+are specifically reserved for configuration file authors.
+.pp
+The following macros
+.i must
+be defined to transmit information into
+.i sendmail:
+.(b
+.ta 4n
+e      The SMTP entry message
+j      The \*(lqofficial\*(rq domain name for this site
+l      The format of the UNIX from line
+n      The name of the daemon (for error messages)
+o      The set of "operators" in addresses
+q      default format of sender address
+.)b
+The
+.b $e
+macro is printed out when SMTP starts up.
+The first word must be the
+.b $j
+macro.
+The
+.b $j
+macro
+should be in RFC821 format.
+The
+.b $l
+and
+.b $n
+macros can be considered constants
+except under terribly unusual circumstances.
+The
+.b $o
+macro consists of a list of characters
+which will be considered tokens
+and which will separate tokens
+when doing parsing.
+For example, if
+.q @
+were in the
+.b $o
+macro, then the input
+.q a@b
+would be scanned as three tokens:
+.q a,
+.q @,
+and
+.q b.
+Finally, the
+.b $q
+macro specifies how an address should appear in a message
+when it is defaulted.
+For example, on our system these definitions are:
+.(b
+De$j Sendmail $v/$Z ready at $b
+DnMAILER-DAEMON
+DlFrom $g  $d
+Do.:%@!^/[]
+Dq$?x$x <$g>$|$g$.
+Dj$w
+.)b
+An acceptable alternative for the
+.b $q
+macro is
+.q "$g$?x ($x)$." .
+These correspond to the following two formats:
+.(b
+Eric Allman <eric@CS.Berkeley.EDU>
+eric@CS.Berkeley.EDU (Eric Allman)
+.)b
+.i Sendmail
+properly quotes names that have special characters
+if the first form is used.
+.pp
+Some macros are defined by
+.i sendmail
+for interpolation into argv's for mailers
+or for other contexts.
+These macros are:
+.(b
+a      The origination date in RFC 822 format
+b      The current date in RFC 822 format
+c      The hop count
+d      The date in UNIX (ctime) format
+f      The sender (from) address
+g      The sender address relative to the recipient
+h      The recipient host
+i      The queue id
+k      The UUCP node name (from the uname system call)
+m      The domain part of the \fIgethostname\fP return value
+p      Sendmail's pid
+r      Protocol used to receive the message
+s      Sender's host name
+t      A numeric representation of the current time
+u      The recipient user
+v      The version number of sendmail
+w      The hostname of this site
+x      The full name of the sender
+z      The home directory of the recipient
+_      The validated sender address
+.)b
+.pp
+There are three types of dates that can be used.
+The
+.b $a
+and
+.b $b
+macros are in RFC 822 format;
+.b $a
+is the time as extracted from the
+.q Date:
+line of the message
+(if there was one),
+and
+.b $b
+is the current date and time
+(used for postmarks).
+If no
+.q Date:
+line is found in the incoming message,
+.b $a
+is set to the current time also.
+The
+.b $d
+macro is equivalent to the
+.b $b
+macro in UNIX
+(ctime)
+format.
+.pp
+The
+.b $f
+macro is the id of the sender
+as originally determined;
+when mailing to a specific host
+the
+.b $g
+macro is set to the address of the sender
+.ul
+relative to the recipient.
+For example,
+if I send to
+.q bollard@matisse.CS.Berkeley.EDU
+from the machine
+.q vangogh.CS.Berkeley.EDU
+the
+.b $f
+macro will be
+.q eric
+and the
+.b $g
+macro will be
+.q eric@vangogh.CS.Berkeley.EDU.
+.pp
+The
+.b $x
+macro is set to the full name of the sender.
+This can be determined in several ways.
+It can be passed as flag to
+.i sendmail.
+The second choice is the value of the
+.q Full-name:
+line in the header if it exists,
+and the third choice is the comment field
+of a
+.q From:
+line.
+If all of these fail,
+and if the message is being originated locally,
+the full name is looked up in the
+.i /etc/passwd
+file.
+.pp
+When sending,
+the
+.b $h ,
+.b $u ,
+and
+.b $z
+macros get set to the host, user, and home directory
+(if local)
+of the recipient.
+The first two are set from the
+.b $@
+and
+.b $:
+part of the rewriting rules, respectively.
+.pp
+The
+.b $p
+and
+.b $t
+macros are used to create unique strings
+(e.g., for the
+.q Message-Id:
+field).
+The
+.b $i
+macro is set to the queue id on this host;
+if put into the timestamp line
+it can be extremely useful for tracking messages.
+The
+.b $v
+macro is set to be the version number of
+.i sendmail ;
+this is normally put in timestamps
+and has been proven extremely useful for debugging.
+The
+.b $w
+macro is set to the name of this host
+if it can be determined.
+The
+.b $c
+field is set to the
+.q "hop count,"
+i.e., the number of times this message has been processed.
+This can be determined
+by the
+.b \-h
+flag on the command line
+or by counting the timestamps in the message.
+.pp
+The
+.b $r
+and
+.b $s
+fields are set to the protocol used to communicate with sendmail
+and the sending hostname.
+The
+.b $_
+is set to a validated sender host name.
+If the sender is running an RFC 1413 compliant IDENT server,
+it will include the user name on that host.
+.sh 3 "C and F \*- define classes"
+.pp
+Classes of phrases may be defined
+to match on the left hand side of rewriting rules,
+where a
+.q phrase
+is a sequence of characters that do not contain space characters.
+For example
+a class of all local names for this site
+might be created
+so that attempts to send to oneself
+can be eliminated.
+These can either be defined directly in the configuration file
+or read in from another file.
+Classes may be given names
+from the set of upper case letters.
+Lower case letters and special characters
+are reserved for system use.
+.pp
+The syntax is:
+.(b F
+.b C \c
+.i c\|phrase1
+.i phrase2...
+.br
+.b F \c
+.i c\|file
+.)b
+The first form defines the class
+.i c
+to match any of the named words.
+It is permissible to split them among multiple lines;
+for example, the two forms:
+.(b
+CHmonet ucbmonet
+.)b
+and
+.(b
+CHmonet
+CHucbmonet
+.)b
+are equivalent.
+The second form
+reads the elements of the class
+.i c
+from the named
+.i file .
+.pp
+The
+.b $~
+(match entries not in class)
+only matches a single word;
+multi-word entries in the class are ignored in this context.
+.pp
+The class
+.b $=w
+is set to be the set of all names
+this host is known by.
+This can be used to match local hostnames.
+.pp
+The class
+.b $=k
+is set to be the same as
+.b $k ,
+that is, the UUCP node name.
+.sh 3 "M \*- define mailer"
+.pp
+Programs and interfaces to mailers
+are defined in this line.
+The format is:
+.(b F
+.b M \c
+.i name ,
+{\c
+.i field =\c
+.i value \|}*
+.)b
+where
+.i name
+is the name of the mailer
+(used internally only)
+and the
+.q field=name
+pairs define attributes of the mailer.
+Fields are:
+.(b
+.ta 1i
+Path   The pathname of the mailer
+Flags  Special flags for this mailer
+Sender A rewriting set for sender addresses
+Recipient      A rewriting set for recipient addresses
+Argv   An argument vector to pass to this mailer
+Eol    The end-of-line string for this mailer
+Maxsize        The maximum message length to this mailer
+Linelimit      The maximum line length in the message body
+Directory      The working directory for the mailer
+.)b
+Only the first character of the field name is checked.
+.pp
+The following flags may be set in the mailer description.
+Any other flags may be used freely
+to conditionally assign headers to messages
+destined for particular mailers.
+.nr ii 4n
+.ip a
+Run Extended SMTP (ESMTP) protocol (defined in RFCs 1425, 1426, and 1427).
+.ip b
+Force a blank line on the end of a message.
+This is intended to work around some stupid versions of
+/bin/mail
+that require a blank line, but do not provide it themselves.
+It would not normally be used on network mail.
+.ip c
+Do not include comments in addresses.
+This should only be used if you have to work around
+a remote mailer that gets confused by comments.
+.ip C
+If mail is
+.i received
+from a mailer with this flag set,
+any addresses in the header that do not have an at sign
+(\c
+.q @ )
+after being rewritten by ruleset three
+will have the
+.q @domain
+clause from the sender
+tacked on.
+This allows mail with headers of the form:
+.(b
+From: usera@hosta
+To: userb@hostb, userc
+.)b
+to be rewritten as:
+.(b
+From: usera@hosta
+To: userb@hostb, userc@hosta
+.)b
+automatically.
+.ip D
+This mailer wants a
+.q Date:
+header line.
+.ip e
+This mailer is expensive to connect to,
+so try to avoid connecting normally;
+any necessary connection will occur during a queue run.
+.ip E
+Escape lines beginning with
+.q From
+in the message with a `>' sign.
+.ip f
+The mailer wants a
+.b \-f
+.i from
+flag,
+but only if this is a network forward operation
+(i.e.,
+the mailer will give an error
+if the executing user
+does not have special permissions).
+.ip F
+This mailer wants a
+.q From:
+header line.
+.ip g
+Normally,
+.i sendmail
+sends internally generated email (e.g., error messages)
+using the null return address\**
+.(f
+\**Actually, this only applies to SMTP,
+which uses the ``MAIL FROM:<>'' command.
+.)f
+as required by RFC 1123.
+However, some mailers don't accept a null return address.
+If necessary,
+you can set the
+.b g
+flag to prevent
+.i sendmail
+from obeying the standards;
+error messages will be sent as from the MAILER-DAEMON
+(actually, the value of the
+.b $n
+macro).
+.ip h
+Upper case should be preserved in host names
+for this mailer.
+.ip I
+This mailer will be speaking SMTP
+to another
+.i sendmail
+\*-
+as such it can use special protocol features.
+This option is not required
+(i.e.,
+if this option is omitted the transmission will still operate successfully,
+although perhaps not as efficiently as possible).
+.ip l
+This mailer is local
+(i.e.,
+final delivery will be performed).
+.ip L
+Limit the line lengths as specified in RFC821.
+This deprecated option should be replaced by the
+.b L=
+mail declaration.
+For historic reasons, the
+.b L
+flag also sets the
+.b 7
+flag.
+.ip m
+This mailer can send to multiple users
+on the same host
+in one transaction.
+When a
+.b $u
+macro occurs in the
+.i argv
+part of the mailer definition,
+that field will be repeated as necessary
+for all qualifying users.
+.ip M
+This mailer wants a
+.q Message-Id:
+header line.
+.ip n
+Do not insert a UNIX-style
+.q From
+line on the front of the message.
+.ip p
+Use the route-addr style reverse-path in the SMTP
+.q "MAIL FROM:"
+command
+rather than just the return address;
+although this is required in RFC821 section 3.1,
+many hosts do not process reverse-paths properly.
+Reverse-paths are officially discouraged by RFC 1123.
+.ip P
+This mailer wants a
+.q Return-Path:
+line.
+.ip r
+Same as
+.b f ,
+but sends a
+.b \-r
+flag.
+.ip s
+Strip quote characters off of the address
+before calling the mailer.
+.ip S
+Don't reset the userid
+before calling the mailer.
+This would be used in a secure environment
+where
+.i sendmail
+ran as root.
+This could be used to avoid forged addresses.
+This flag is suppressed if given from an
+.q unsafe
+environment
+(e.g, a user's mail.cf file).
+.ip u
+Upper case should be preserved in user names
+for this mailer.
+.ip U
+This mailer wants Unix-style
+.q From
+lines with the ugly UUCP-style
+.q "remote from <host>"
+on the end.
+.ip x
+This mailer wants a
+.q Full-Name:
+header line.
+.ip X
+This mailer want to use the hidden dot algorithm
+as specified in RFC821;
+basically,
+any line beginning with a dot
+will have an extra dot prepended
+(to be stripped at the other end).
+This insures that lines in the message containing a dot
+will not terminate the message prematurely.
+.ip 7
+Strip all output to seven bits.
+This is the default if the
+.b L
+flag is set.
+Note that setting this is not
+sufficient to get full eight bit data passed through
+.i sendmail .
+If the
+.b 7
+option is set, this is essentially always set,
+since the eighth bit was stripped on input.
+.pp
+The mailer with the special name
+.q error
+can be used to generate a user error.
+The (optional) host field is an exit status to be returned,
+and the user field is a message to be printed.
+The exit status may be numeric or one of the values
+USAGE, NOUSER, NOHOST, UNAVAILABLE, SOFTWARE, TEMPFAIL, PROTOCOL, or CONFIG
+to return the corresponding EX_ exit code.
+For example, the entry:
+.(b
+$#error $@ NOHOST $: Host unknown in this domain
+.)b
+on the RHS of a rule
+will cause the specified error to be generated
+and the
+.q "Host unknown"
+exit status to be returned
+if the LHS matches.
+This mailer is only functional in ruleset zero.
+.pp
+The mailer named
+.q local
+.i must
+be defined in every configuration file.
+This is used to deliver local mail,
+and is treated specially in several ways.
+Additionally, three other mailers named
+.q prog ,
+.q *file* ,
+and
+.q *include*
+may be defined to tune the delivery of messages to programs,
+files,
+and :include: lists respectively.
+They default to:
+.(b
+Mprog, P=/bin/sh, F=lsD, A=sh \-c $u
+M*file*, P=/dev/null, F=lsDFMPEu, A=FILE
+M*include*, P=/dev/null, F=su, A=INCLUDE
+.)b
+.pp
+The Sender and Recipient rewriting sets
+may either be a simple integer
+or may be two integers separated by a slash;
+if so, the first rewriting set is applied to envelope
+addresses
+and the second is applied to headers.
+.pp
+The Directory
+is actually a colon-separated path of directories to try.
+For example, the definition
+.q D=$z:/
+first tries to execute in the recipient's home directory;
+if that is not available,
+it tries to execute in the root of the filesystem.
+This is intended to be used only on the
+.q prog
+mailer,
+since some shells (such as
+.i csh )
+refuse to execute if they cannot read the home directory.
+Since the queue directory is not normally readable by normal users
+.i csh
+scripts as recipients can fail.
+.sh 3 "H \*- define header"
+.pp
+The format of the header lines that sendmail inserts into the message
+are defined by the
+.b H
+line.
+The syntax of this line is:
+.(b F
+.b H [\c
+.b ? \c
+.i mflags \c
+.b ? ]\c
+.i hname \c
+.b :
+.i htemplate
+.)b
+Continuation lines in this spec
+are reflected directly into the outgoing message.
+The
+.i htemplate
+is macro expanded before insertion into the message.
+If the
+.i mflags
+(surrounded by question marks)
+are specified,
+at least one of the specified flags
+must be stated in the mailer definition
+for this header to be automatically output.
+If one of these headers is in the input
+it is reflected to the output
+regardless of these flags.
+.pp
+Some headers have special semantics
+that will be described below.
+.sh 3 "O \*- set option"
+.pp
+There are a number of
+.q random
+options that
+can be set from a configuration file.
+Options are represented by single characters.
+The syntax of this line is:
+.(b F
+.b O \c
+.i o\|value
+.)b
+This sets option
+.i o
+to be
+.i value .
+Depending on the option,
+.i value
+may be a string, an integer,
+a boolean
+(with legal values
+.q t ,
+.q T ,
+.q f ,
+or
+.q F ;
+the default is TRUE),
+or
+a time interval.
+.pp
+The options supported are:
+.nr ii 1i
+.ip a\fIN\fP
+If set,
+wait up to
+.i N
+minutes for an
+.q @:@
+entry to exist in the alias database
+before starting up.
+If it does not appear in
+.i N
+minutes,
+rebuild the database
+(if the
+.b D
+option is also set)
+or issue a warning.
+.ip "A\fIspec, spec, ...\fP"
+Specify possible alias file(s).
+Each
+.i spec
+should be in the format
+``\c
+.i class \c
+.b :
+.i file ''
+where
+.i class \c
+.b :
+is optional and defaults to ``implicit''.
+Depending on how
+.b sendmail
+is compiled, valid classes are
+.q implicit
+(search through a compiled-in list of alias file types,
+for back compatibility),
+.q hash
+(if
+.sm NEWDB
+is specified),
+.q dbm
+(if
+.sm NDBM
+is specified),
+.q stab
+(internal symbol table \*- not normally used
+unless you have no other database lookup),
+or
+.q nis
+(if
+.sm NIS
+is specified).
+If a list of
+.i spec s
+are provided,
+.i sendmail
+searches them in order.
+.ip b\fIN\fP/\fIM\fP
+Insist on at least
+.i N
+blocks free on the filesystem that holds the queue files
+before accepting email via SMTP.
+If there is insufficient space
+.i sendmail
+gives a 452 response
+to the MAIL command.
+This invites the sender to try again later.
+The optional
+.i M
+is a maximum message size advertised in the ESMTP EHLO response.
+It is currently otherwise unused.
+.ip B\fIc\fP
+Set the blank substitution character to
+.i c .
+Unquoted spaces in addresses are replaced by this character.
+Defaults to space (i.e., no change is made).
+.ip c
+If an outgoing mailer is marked as being expensive,
+don't connect immediately.
+This requires that queueing be compiled in,
+since it will depend on a queue run process to
+actually send the mail.
+.ip C\fIN\fP
+Checkpoints the queue every
+.i N
+(default 10)
+addresses sent.
+If your system crashes during delivery to a large list,
+this prevents retransmission to any but the last
+.I N
+recipients.
+.ip d\fIx\fP
+Deliver in mode
+.i x .
+Legal modes are:
+.(b
+.ta 4n
+i      Deliver interactively (synchronously)
+b      Deliver in background (asynchronously)
+q      Just queue the message (deliver during queue run)
+.)b
+Defaults to ``b'' if no option is specified,
+``i'' if it is specified but given no argument
+(i.e., ``Od'' is equivalent to ``Odi'').
+.ip D
+If set,
+rebuild the alias database if necessary and possible.
+If this option is not set,
+.i sendmail
+will never rebuild the alias database
+unless explicitly requested
+using
+.b \-bi .
+.ip e\fIx\fP
+Dispose of errors using mode
+.i x .
+The values for
+.i x
+are:
+.(b
+p      Print error messages (default)
+q      No messages, just give exit status
+m      Mail back errors
+w      Write back errors (mail if user not logged in)
+e      Mail back errors and give zero exit stat always
+.)b
+.ip E\fIfile/message\fP
+Prepend error messages with the indicated message.
+If it begins with a slash,
+it is assumed to be the pathname of a file
+containing a message (this is the recommended setting).
+Otherwise, it is a literal message.
+The error file might contain the name, email address, and/or phone number
+of a local postmaster who could provide assistance
+in to end users.
+If the option is missing or null,
+or if it names a file which does not exist or which is not readable,
+no message is printed.
+.ip f
+Save
+Unix-style
+.q From
+lines at the front of headers.
+Normally they are assumed redundant
+and discarded.
+.ip F\fImode\fP
+The file mode for queue files.
+.ip g\fIn\fP
+Set the default group id
+for mailers to run in
+to
+.i n .
+Defaults to 1.
+.ip G
+Allow fuzzy matching on the GECOS field.
+If this flag is set,
+and the usual user name lookups fail
+(that is, there is no alias with this name and a
+.i getpwnam
+fails),
+sequentially search the password file
+for a matching entry in the GECOS field.
+This also requires that MATCHGECOS
+be turned on during compilation.
+This option is not recommended.
+.ip h\fIN\fP
+The maximum hop count.
+Messages that have been processed more than
+.i N
+times are assumed to be in a loop and are rejected.
+Defaults to 25.
+.ip H\fIfile\fP
+Specify the help file
+for SMTP.
+.ip i
+Ignore dots in incoming messages.
+This is always disabled (that is, dots are always accepted)
+when reading SMTP mail.
+.ip I
+Insist that the BIND name server be running
+to resolve host names.
+If this is not set and the name server is not running,
+the
+.i /etc/hosts
+file will be considered complete.
+In general, you do want to set this option
+if your
+.i /etc/hosts
+file does not include all hosts known to you
+or if you are using the MX (mail forwarding) feature of the BIND name server.
+The name server will still be consulted
+even if this option is not set, but
+.i sendmail
+will feel free to resort to reading
+.i /etc/hosts
+if the name server is not available.
+Thus, you should
+.i never
+set this option if you do not run the name server.
+.ip j
+If set, send error messages in MIME format
+(see RFC1341 and RFC1344 for details).
+.ip J\fIpath\fP
+Set the path for searching for users' .forward files.
+The default is
+.q $z/.forward .
+Some sites that use the automounter may prefer to change this to
+.q /var/forward/$u
+to search a file with the same name as the user in a system directory.
+It can also be set to a sequence of paths separated by colons;
+.i sendmail
+stops at the first file it can successfully and safely open.
+For example,
+.q /var/forward/$u:$z/.forward
+will search first in /var/forward/\c
+.i username
+and then in
+.i ~username /.forward
+(but only if the first file does not exist).
+.ip k\fIN\fP
+The maximum number of open connections that will be cached at a time.
+The default is one.
+This delays closing the the current connection until
+either this invocation of sendmail needs to connect to another host
+or it terminates.
+Setting it to zero defaults to the old behavior,
+that is, connections are closed immediately.
+.ip K\fItimeout\fP
+The maximum amount of time a cached connection will be permitted to idle
+without activity.
+If this time is exceeded,
+the connection is immediately closed.
+This value should be small (on the order of ten minutes).
+Before
+.b sendmail
+uses a cached connection,
+it always sends a NOOP (no operation) command
+to check the connection;
+if this fails, it reopens the connection.
+This keeps your end from failing if the other end times out.
+The point of this option is to be a good network neighbor
+and avoid using up excessive resources
+on the other end.
+The default is five minutes.
+.ip l
+If there is an
+.q Errors-To:
+header, send error messages to the addresses listed there.
+They normally go to the envelope sender.
+Use of this option causes sendmail to violate RFC 1123.
+.ip L\fIn\fP
+Set the default log level to
+.i n .
+Defaults to 9.
+.ip m
+Send to me too,
+even if I am in an alias expansion.
+.ip M\fIx\|value\fP
+Set the macro
+.i x
+to
+.i value .
+This is intended only for use from the command line.
+.ip n
+Validate the RHS of aliases when rebuilding the alias database.
+.ip o
+Assume that the headers may be in old format,
+i.e.,
+spaces delimit names.
+This actually turns on
+an adaptive algorithm:
+if any recipient address contains a comma, parenthesis,
+or angle bracket,
+it will be assumed that commas already exist.
+If this flag is not on,
+only commas delimit names.
+Headers are always output with commas between the names.
+.ip O\fIoptions\fP
+Set server SMTP options.
+The options are
+.i key=value
+pairs.
+Known keys are:
+.(b
+.ta 1i
+Port   Name/number of listening port (defaults to "smtp")
+Addr   Address mask (defaults INADDR_ANY)
+Family Address family (defaults to INET)
+Listen Size of listen queue (defaults to 10)
+.)b
+The
+.i Addr ess
+mask may be a numeric address in dot notation
+or a network name.
+.ip p\fI\|opt,opt,...\fP
+Set the privacy
+.i opt ions.
+``Privacy'' is really a misnomer;
+many of these are just a way of insisting on stricter adherence
+to the SMTP protocol.
+The
+.i opt ions
+can be selected from:
+.(b
+.ta \w'needvrfyhelo'u+3n
+public Allow open access
+needmailhelo   Insist on HELO or EHLO command before MAIL
+needexpnhelo   Insist on HELO or EHLO command before EXPN
+noexpn Disallow EXPN entirely
+needvrfyhelo   Insist on HELO or EHLO command before VRFY
+novrfy Disallow VRFY entirely
+restrictmailq  Restrict mailq command
+goaway Disallow essentially all SMTP status queries
+.)b
+The
+.q goaway
+pseudo-flag sets all flags except
+.q restrictmailq .
+If mailq is restricted,
+only people in the same group as the queue directory
+can print the queue.
+.ip P\fIpostmaster\fP
+If set,
+copies of error messages will be sent to the named
+.i postmaster .
+Only the header of the failed message is sent.
+Since most errors are user problems,
+this is probably not a good idea on large sites,
+and arguably contains all sorts of privacy violations,
+but it seems to be popular with certain operating systems vendors.
+.ip q\fIfactor\fP
+Use
+.i factor
+as the multiplier in the map function
+to decide when to just queue up jobs rather than run them.
+This value is divided by the difference between the current load average
+and the load average limit
+(\c
+.b x
+flag)
+to determine the maximum message priority
+that will be sent.
+Defaults to 600000.
+.ip Q\fIdir\fP
+Use the named
+.i dir
+as the queue directory.
+.ip r\|\fItimeouts\fP
+Timeout reads after
+.i time
+interval.
+The
+.i timeouts
+argument is a list of
+.i keyword=value
+pairs.
+The recognized timeouts and their default values, and their
+minimum values specified in RFC 1123 section 5.3.2 are:
+.(b
+.ta \w'datafinal'u+3n
+initial        wait for initial greeting message [5m, 5m]
+helo   reply to HELO or EHLO command [5m, none]
+mail   reply to MAIL command [10m, 5m]
+rcpt   reply to RCPT command [1h, 5m]
+datainit       reply to DATA command [5m, 2m]
+datablock      data block read [1h, 3m]
+datafinal      reply to final ``.'' in data [1h, 10m]
+rset   reply to RSET command [5m, none]
+quit   reply to QUIT command [2m, none]
+misc   reply to NOOP and VERB commands [2m, none]
+command        command read [1h, 5m]
+.)b
+All but
+.q command
+apply to client SMTP.
+For back compatibility,
+a timeout with no ``keyword='' part
+will set all of the longer values.
+.ip s
+Be super-safe when running things,
+i.e.,
+always instantiate the queue file,
+even if you are going to attempt immediate delivery.
+.i Sendmail
+always instantiates the queue file
+before returning control the the client
+under any circumstances.
+.ip S\fIfile\fP
+Log statistics in the named
+.i file .
+.ip t\fIS,D\fP
+Set the local time zone name to
+.i S
+for standard time and
+.i D
+for daylight time;
+this is only used under version six.
+.ip T\fIrtime/wtime\fP
+Set the queue timeout to
+.i rtime .
+After this interval,
+messages that have not been successfully sent
+will be returned to the sender.
+Defaults to five days.
+The optional
+.i wtime
+is the time after which a warning message is sent.
+If it is missing or zero
+then no warning messages are sent.
+.ip u\fIn\fP
+Set the default userid for mailers to
+.i n .
+Mailers without the
+.i S
+flag in the mailer definition
+will run as this user.
+Defaults to 1.
+.ip U\fIudbspec\fP
+The user database specification.
+.ip v
+Run in verbose mode.
+If this is set,
+.i sendmail
+adjusts options
+.b c
+(don't connect to expensive mailers)
+and
+.b d
+(delivery mode)
+so that all mail is delivered completely
+in a single job
+so that you can see the entire delivery process.
+Option
+.b v
+should
+.i never
+be set in the configuration file;
+it is intended for command line use only.
+.ip V\fIfallbackhost\fP
+If specified, the
+.i fallbackhost
+acts like a very low priority MX
+on every host.
+This is intended to be used by sites with poor network connectivity.
+.ip x\fILA\fP
+When the system load average exceeds
+.i LA ,
+just queue messages
+(i.e., don't try to send them).
+Defaults to 8.
+.ip X\fILA\fP
+When the system load average exceeds
+.i LA ,
+refuse incoming SMTP connections.
+Defaults to 12.
+.ip y\fIfact\fP
+The indicated
+.i fact or
+is added to the priority (thus
+.i lowering
+the priority of the job)
+for each recipient,
+i.e., this value penalizes jobs with large numbers of recipients.
+Defaults to 30000.
+.ip Y
+If set,
+deliver each job that is run from the queue in a separate process.
+Use this option if you are short of memory,
+since the default tends to consume considerable amounts of memory
+while the queue is being processed.
+.ip z\fIfact\fP
+The indicated
+.i fact or
+is multiplied by the message class
+(determined by the Precedence: field in the user header
+and the
+.b P
+lines in the configuration file)
+and subtracted from the priority.
+Thus, messages with a higher Priority: will be favored.
+Defaults to 1800.
+.ip Z\fIfact\fP
+The
+.i fact or
+is added to the priority
+every time a job is processed.
+Thus,
+each time a job is processed,
+its priority will be decreased by the indicated value.
+In most environments this should be positive,
+since hosts that are down are all too often down for a long time.
+Defaults to 90000.
+.ip 7
+Strip input to seven bits for compatibility with old systems.
+This shouldn't be necessary.
+.lp
+All options can be specified on the command line using the
+\-o flag,
+but most will cause
+.i sendmail
+to relinquish its setuid permissions.
+The options that will not cause this are
+b, d, e, E, i, L, m, o, p, r, s, v, C, and 7.
+Also, M (define macro) when defining the r or s macros
+is also considered
+.q safe .
+.sh 3 "P \*- precedence definitions"
+.pp
+Values for the
+.q "Precedence:"
+field may be defined using the
+.b P
+control line.
+The syntax of this field is:
+.(b
+\fBP\fP\fIname\fP\fB=\fP\fInum\fP
+.)b
+When the
+.i name
+is found in a
+.q Precedence:
+field,
+the message class is set to
+.i num .
+Higher numbers mean higher precedence.
+Numbers less than zero
+have the special property
+that if an error occurs during processing
+the body of the message will not be returned;
+this is expected to be used for
+.q "bulk"
+mail such as through mailing lists.
+The default precedence is zero.
+For example,
+our list of precedences is:
+.(b
+Pfirst-class=0
+Pspecial-delivery=100
+Plist=\-30
+Pbulk=\-60
+Pjunk=\-100
+.)b
+People writing mailing list exploders
+are encouraged to use
+.q "Precedence: list" .
+Older versions of
+.i sendmail
+(which discarded all error returns for negative precedences)
+didn't recognize this name, giving it a default precedence of zero.
+This allows list maintainers to see error returns
+on both old and new versions of
+.i sendmail .
+.sh 3 "V \*- configuration version level"
+.pp
+To provide compatibility with old configuration files,
+the
+.b V
+line has been added to define some very basic semantics
+of the configuration file.
+These are not intended to be long term supports;
+rather, they describe compatibility features
+which will probably be removed in future releases.
+.pp
+.q Old
+configuration files are defined as version level one.
+Version level two files make the following changes:
+.np
+Host name canonification ($[ ... $])
+appends a dot if the name is recognized;
+this gives the config file a way of finding out if anything matched.
+(Actually, this just initializes the
+.q host
+map with the
+.q \-a.
+flag \*- you can reset it to anything you prefer
+by declaring the map explicitly.)
+.np
+Default host name extension is consistent throughout processing;
+version level one configurations turned off domain extension
+(that is, adding the local domain name)
+during certain points in processing.
+Version level two configurations are expected to include a trailing dot
+to indicate that the name is already canonical.
+.np
+Local names that are not aliases
+are passed through a new distinguished ruleset five;
+this can be used to append a local relay.
+This behaviour can be prevented by resolving the local name
+with an initial `@'.
+That is, something that resolves to a local mailer and a user name of
+.q vikki
+will be passed through ruleset five,
+but a user name of
+.q @vikki
+will have the `@' stripped,
+will not be passed through ruleset five,
+but will otherwise be treated the same as the prior example.
+The expectation is that this might be used to implement a policy
+where mail sent to
+.q vikki
+was handled by a central hub,
+but mail sent to
+.q vikki@localhost
+was delivered directly.
+.pp
+Version level three files
+allow # initiated comments on all lines.
+Exceptions are backslash escaped # marks
+and the $# syntax.
+.sh 3 "K \*- key file declaration"
+.pp
+Special maps can be defined using the line:
+.(b
+Kmapname mapclass arguments
+.)b
+The
+.i mapname
+is the handle by which this map is referenced in the rewriting rules.
+The
+.i mapclass
+is the name of a type of map;
+these are compiled in to sendmail.
+The
+.i arguments
+are interpreted depending on the class;
+typically,
+there would be a single argument naming the file containing the map.
+.pp
+Maps are referenced using the syntax:
+.(b
+$( \fImap\fP \fIkey\fP $@ \fIarguments\fP $: \fIdefault\fP $)
+.)b
+where either or both of the
+.i arguments
+or
+.i default
+portion may be omitted.
+The
+.i arguments
+may appear more than once.
+The indicated
+.i key
+and
+.i arguments
+are passed to the appropriate mapping function.
+If it returns a value, it replaces the input.
+If it does not return a value and the
+.i default
+is specified, the
+.i default
+replaces the input.
+Otherwise, the input is unchanged.
+.pp
+During replacement of either a map value or default
+the string
+.q %\fIn\fP
+(where
+.i n
+is a digit)
+is replaced by the corresponding
+.i argument .
+Argument zero
+is always the database key.
+For example, the rule
+.(b
+.ta 1.5i
+R$- ! $+       $: $(uucp $1 $@ $2 $: %1 @ %0 . UUCP $)
+.)b
+Looks up the UUCP name in a (user defined) UUCP map;
+if not found it turns it into
+.q \&.UUCP
+form.
+The database might contain records like:
+.(b
+decvax %1@%0.DEC.COM
+research       %1@%0.ATT.COM
+.)b
+.pp
+The built in map with both name and class
+.q host
+is the host name canonicalization lookup.
+Thus,
+the syntax:
+.(b
+$(host \fIhostname\fP$)
+.)b
+is equivalent to:
+.(b
+$[\fIhostname\fP$]
+.)b
+.pp
+There are four predefined database lookup classes:
+.q dbm ,
+.q btree ,
+.q hash ,
+and
+.q nis .
+The first requires that sendmail be compiled with the
+.b ndbm
+library;
+the second two require the
+.b db
+library,
+and the third requires that sendmail be compiled with NIS support.
+All four accept as arguments the some optional flags
+and a filename (or a mapname for NIS).
+Known flags are:
+.ip "\-o"
+Indicates that this map is optional \*- that is,
+if it cannot be opened,
+no error is produced,
+and sendmail will behave as if the map existed but was empty.
+.ip "\-N"
+Normally sendmail does not include the trailing null byte
+on a string as part of the key.
+If this flag is indicated,
+it will be included.
+This is for compatibility with some methods of building the maps.
+.ip "\-a\fIx\fP"
+Append the character
+.i x
+on successful matches.
+For example, the default
+.i host
+map appends a dot on successful matches.
+.ip "\-f"
+Fold upper to lower case before looking up the key.
+.ip "\-m"
+Match only (without replacing the value).
+If you only care about the existence of a key and not the value
+(as you might when searching the NIS map
+.q hosts.byname
+for example),
+this flag prevents the map from substituting the value.
+However,
+The \-a argument is still appended on a match,
+and the default is still taken if the match fails.
+.pp
+The
+.i dbm
+map appends the strings
+.q \&.pag
+and
+.q \&.dir
+to the given filename;
+the two
+.i db -based
+maps append
+.q \&.db .
+.pp
+The program
+.i makemap (8)
+can be used to build any of the three database-oriented maps.
+It takes the following flags:
+.ip \-f
+Do not fold upper to lower case in the map.
+.ip \-N
+Include null bytes in keys.
+.ip \-o
+Append to an existing (old) file.
+.ip \-r
+Allow replacement of existing keys;
+normally, re-inserting an existing key is an error.
+.ip \-v
+Print what is happening.
+.pp
+There are also two builtin maps that are,
+strictly speaking,
+not database lookups.
+.pp
+The
+.q host
+map does host domain canonification;
+given a host name it calls the name server
+to find the canonical name for that host.
+.pp
+The
+.q dequote
+map strips double quotes (") from a name.
+It does not strip backslashes.
+It will not strip quotes if the resulting string
+would contain unscannable syntax
+(that is, basic errors like unbalanced angle brackets;
+more sophisticated errors such as unknown hosts are not checked).
+The intent is for use when trying to accept mail from systems such as
+DECnet
+that routinely quote odd syntax such as
+.(b
+"49ers::ubell"
+.)b
+A typical usage is probably something like:
+.(b
+Kdequote dequote
+
+\&...
+
+R$\-   $: $(dequote $1 $)
+R$\- $+        $: $>3 $1 $2
+.)b
+Care must be taken to prevent unexpected results;
+for example,
+.(b
+"|someprogram < input > output"
+.)b
+will have quotes stripped,
+but the result is probably not what you had in mind.
+Fortunately these cases are rare.
+.pp
+New classes can be added in the routine
+.b setupmaps
+in file
+.b conf.c .
+.sh 2 "Building a Configuration File From Scratch"
+.pp
+Building a configuration table from scratch is an extremely difficult job.
+Fortunately,
+it is almost never necessary to do so;
+nearly every situation that may come up
+may be resolved by changing an existing table.
+In any case,
+it is critical that you understand what it is that you are trying to do
+and come up with a philosophy for the configuration table.
+This section is intended to explain what the real purpose
+of a configuration table is
+and to give you some ideas
+for what your philosophy might be.
+.pp
+.b "Do not even consider"
+writing your own configuration file
+without carefully studying
+RFC 821, 822, and 1123.
+You should also read RFC 976
+if you are doing UUCP exchange.
+.sh 3 "What you are trying to do"
+.pp
+The configuration table has three major purposes.
+The first and simplest
+is to set up the environment for
+.i sendmail .
+This involves setting the options,
+defining a few critical macros,
+etc.
+Since these are described in other places,
+we will not go into more detail here.
+.pp
+The second purpose is to rewrite addresses in the message.
+This should typically be done in two phases.
+The first phase maps addresses in any format
+into a canonical form.
+This should be done in ruleset three.
+The second phase maps this canonical form
+into the syntax appropriate for the receiving mailer.
+.i Sendmail
+does this in three subphases.
+Rulesets one and two
+are applied to all sender and recipient addresses respectively.
+After this,
+you may specify per-mailer rulesets
+for both sender and recipient addresses;
+this allows mailer-specific customization.
+Finally,
+ruleset four is applied to do any default conversion
+to external form.
+.pp
+The third purpose
+is to map addresses into the actual set of instructions
+necessary to get the message delivered.
+Ruleset zero must resolve to the internal form,
+which is in turn used as a pointer to a mailer descriptor.
+The mailer descriptor describes the interface requirements
+of the mailer.
+.sh 3 "Philosophy"
+.pp
+The particular philosophy you choose will depend heavily
+on the size and structure of your organization.
+I will present a few possible philosophies here.
+There are as many philosophies as there are config designers;
+feel free to develop your own.
+.pp
+One general point applies to all of these philosophies:
+it is almost always a mistake
+to try to do full host route resolution.
+For example,
+if you are on a UUCP-only site
+and you are trying to get names of the form
+.q user@host
+to the Internet,
+it does not pay to route them to
+.q xyzvax!decvax!ucbvax!c70!user@host
+since you then depend on several links not under your control,
+some of which are likely to misparse it anyway.
+The best approach to this problem
+is to simply forward the message for
+.q user@host
+to
+.q xyzvax
+and let xyzvax
+worry about it from there.
+In summary,
+just get the message closer to the destination,
+rather than determining the full path.
+.sh 4 "Large site, many hosts \*- minimum information"
+.pp
+Berkeley is an example of a large site,
+i.e., more than two or three hosts
+and multiple mail connections.
+We have decided that the only reasonable philosophy
+in our environment
+is to designate one host as the guru for our site.
+It must be able to resolve any piece of mail it receives.
+The other sites should have the minimum amount of information
+they can get away with.
+In addition,
+any information they do have
+should be hints rather than solid information.
+.pp
+For example,
+a typical site on our local ether network is
+.q monet
+(actually
+.q monet.CS.Berkeley.EDU ).
+When monet receives mail for delivery,
+it checks whether it knows
+that the destination host is directly reachable;
+if so, mail is sent to that host.
+If it receives mail for any unknown host,
+it just passes it directly to
+.q ucbvax.CS.Berkeley.EDU ,
+our master host.
+Ucbvax may determine that the host name is illegal
+and reject the message,
+or may be able to do delivery.
+However, it is important to note that when a new mail connection is added,
+the only host that
+.i must
+have its tables updated
+is ucbvax;
+the others
+.i may
+be updated if convenient,
+but this is not critical.
+.pp
+This picture is slightly muddied
+due to network connections that are not actually located
+on ucbvax.
+For example,
+some UUCP connections are currently on
+.q ucbarpa.
+However,
+monet
+.i "does not"
+know about this;
+the information is hidden totally between ucbvax and ucbarpa.
+Mail going from monet to a UUCP host
+is transferred via the ethernet
+from monet to ucbvax,
+then via the ethernet from ucbvax to ucbarpa,
+and then is submitted to UUCP.
+Although this involves some extra hops,
+we feel this is an acceptable tradeoff.
+.pp
+An interesting point is that it would be possible
+to update monet
+to send appropriate UUCP mail directly to ucbarpa
+if the load got too high;
+if monet failed to note a host as connected to ucbarpa
+it would go via ucbvax as before,
+and if monet incorrectly sent a message to ucbarpa
+it would still be sent by ucbarpa
+to ucbvax as before.
+The only problem that can occur is loops,
+for example,
+if ucbarpa thought that ucbvax had the UUCP connection
+and vice versa.
+For this reason,
+updates should
+.i always
+happen to the master host first.
+.pp
+This philosophy results as much from the need
+to have a single source for the configuration files
+(typically built using
+.i m4 \|(1)
+or some similar tool)
+as any logical need.
+Maintaining more than three separate tables by hand
+is essentially an impossible job.
+.sh 4 "Small site \*- complete information"
+.pp
+A small site
+(two or three hosts and few external connections)
+may find it more reasonable to have complete information
+at each host.
+This would require that each host
+know exactly where each network connection is,
+possibly including the names of each host on that network.
+As long as the site remains small
+and the the configuration remains relatively static,
+the update problem will probably not be too great.
+.sh 4 "Single host"
+.pp
+This is in some sense the trivial case.
+The only major issue is trying to insure that you don't
+have to know too much about your environment.
+For example,
+if you have a UUCP connection
+you might find it useful to know about the names of hosts
+connected directly to you,
+but this is really not necessary
+since this may be determined from the syntax.
+.sh 4 "A completely different philosophy"
+.pp
+This is adapted from Bruce Lilly.
+Any errors in interpretation are mine.
+.pp
+Do minimal changes in ruleset 3:
+fix some common but unambiguous errors (e.g. trailing dot on domains) and
+hide bang paths foo!bar into bar@foo.UUCP.
+The resulting "canonical" form is any valid RFC822/RFC1123/RFC976 address.
+.pp
+Ruleset 0 does the bulk of the work.
+It removes the trailing "@.UUCP" that hides bang paths,
+strips anything not needed to resolve,
+e.g. the phrase from phrase <route-addr> and from named groups,
+rejects unparseable addresses using $#error,
+and finally
+resolves to a mailer/host/user triple.
+Ruleset 0 is rather lengthy
+as it has to handle 3 basic address forms:
+RFC976 bang paths,
+RFC1123 %-hacks
+(including vanilla RFC822 local-part@domain),
+and RFC822 source routes.
+It's also complicated by having to handle named lists.
+.pp
+The header rewriting rulesets 1 and 2
+remove the trailing "@.UUCP" that hides bang paths.
+Ruleset 2 also strips the $# mailer $@ host (for test mode).
+.pp
+Ruleset 4 does absolutely nothing.
+.pp
+The per-mailer rewriting rulesets conform the envelope and
+header addresses to the requirements of the specific
+mailer.
+.pp
+Lots of rulesets-as-subroutines are used.
+.pp
+As a result, header addresses are subject to minimal munging
+(per RFC1123), and the general plan is per RFC822 sect. 3.4.10.
+.sh 3 "Relevant issues"
+.pp
+The canonical form you use
+should almost certainly be as specified in
+the Internet protocols
+RFC819 and RFC822.
+Copies of these RFC's are included on the
+.i sendmail
+tape
+as
+.i doc/rfc819.lpr
+and
+.i doc/rfc822.lpr .
+.pp
+RFC822
+describes the format of the mail message itself.
+.i Sendmail
+follows this RFC closely,
+to the extent that many of the standards described in this document
+can not be changed without changing the code.
+In particular,
+the following characters have special interpretations:
+.(b
+< > ( ) " \e
+.)b
+Any attempt to use these characters for other than their RFC822
+purpose in addresses is probably doomed to disaster.
+.pp
+RFC819
+describes the specifics of the domain-based addressing.
+This is touched on in RFC822 as well.
+Essentially each host is given a name
+which is a right-to-left dot qualified pseudo-path
+from a distinguished root.
+The elements of the path need not be physical hosts;
+the domain is logical rather than physical.
+For example,
+at Berkeley
+one legal host might be
+.q a.CC.Berkeley.EDU ;
+reading from right to left,
+.q EDU
+is a top level domain
+comprising educational institutions,
+.q Berkeley
+is a logical domain name,
+.q CC
+represents the Computer Center,
+(in this case a strictly logical entity),
+and
+.q a
+is a host in the Computer Center.
+.pp
+Beware when reading RFC819
+that there are a number of errors in it.
+.sh 3 "How to proceed"
+.pp
+Once you have decided on a philosophy,
+it is worth examining the available configuration tables
+to decide if any of them are close enough
+to steal major parts of.
+Even under the worst of conditions,
+there is a fair amount of boiler plate that can be collected safely.
+.pp
+The next step is to build ruleset three.
+This will be the hardest part of the job.
+Beware of doing too much to the address in this ruleset,
+since anything you do will reflect through
+to the message.
+In particular,
+stripping of local domains is best deferred,
+since this can leave you with addresses with no domain spec at all.
+Since
+.i sendmail
+likes to append the sending domain to addresses with no domain,
+this can change the semantics of addresses.
+Also try to avoid
+fully qualifying domains in this ruleset.
+Although technically legal,
+this can lead to unpleasantly and unnecessarily long addresses
+reflected into messages.
+The Berkeley configuration files
+define ruleset nine
+to qualify domain names and strip local domains.
+This is called from ruleset zero
+to get all addresses into a cleaner form.
+.pp
+Once you have ruleset three finished,
+the other rulesets should be relatively trivial.
+If you need hints,
+examine the supplied configuration tables.
+.sh 3 "Testing the rewriting rules \*- the \-bt flag"
+.pp
+When you build a configuration table,
+you can do a certain amount of testing
+using the
+.q "test mode"
+of
+.i sendmail .
+For example,
+you could invoke
+.i sendmail
+as:
+.(b
+sendmail \-bt \-Ctest.cf
+.)b
+which would read the configuration file
+.q test.cf
+and enter test mode.
+In this mode,
+you enter lines of the form:
+.(b
+rwset address
+.)b
+where
+.i rwset
+is the rewriting set you want to use
+and
+.i address
+is an address to apply the set to.
+Test mode shows you the steps it takes
+as it proceeds,
+finally showing you the address it ends up with.
+You may use a comma separated list of rwsets
+for sequential application of rules to an input.
+For example:
+.(b
+3,1,21,4 monet:bollard
+.)b
+first applies ruleset three to the input
+.q monet:bollard.
+Ruleset one is then applied to the output of ruleset three,
+followed similarly by rulesets twenty-one and four.
+.pp
+If you need more detail,
+you can also use the
+.q \-d21
+flag to turn on more debugging.
+For example,
+.(b
+sendmail \-bt \-d21.99
+.)b
+turns on an incredible amount of information;
+a single word address
+is probably going to print out several pages worth of information.
+.pp
+You should be warned that internally,
+.b sendmail
+applies ruleset 3 to all addresses.
+In this version of sendmail, you will have to do that manually.
+For example, older versions allowed you to use
+.(b
+0 bruce@broadcast.sony.com
+.)b
+This version requires that you use:
+.(b
+3,0 bruce@broadcast.sony.com
+.)b
+.sh 3 "Building mailer descriptions"
+.pp
+To add an outgoing mailer to your mail system,
+you will have to define the characteristics of the mailer.
+.pp
+Each mailer must have an internal name.
+This can be arbitrary,
+except that the names
+.q local
+and
+.q prog
+must be defined.
+.pp
+The pathname of the mailer must be given in the P field.
+If this mailer should be accessed via an IPC connection,
+use the string
+.q [IPC]
+instead.
+.pp
+The F field defines the mailer flags.
+You should specify an
+.q f
+or
+.q r
+flag to pass the name of the sender as a
+.b \-f
+or
+.b \-r
+flag respectively.
+These flags are only passed if they were passed to
+.i sendmail,
+so that mailers that give errors under some circumstances
+can be placated.
+If the mailer is not picky
+you can just specify
+.q "\-f $g"
+in the argv template.
+If the mailer must be called as
+.b root
+the
+.q S
+flag should be given;
+this will not reset the userid
+before calling the mailer\**.
+.(f
+\**\c
+.i Sendmail
+must be running setuid to root
+for this to work.
+.)f
+If this mailer is local
+(i.e., will perform final delivery
+rather than another network hop)
+the
+.q l
+flag should be given.
+Quote characters
+(backslashes and " marks)
+can be stripped from addresses if the
+.q s
+flag is specified;
+if this is not given
+they are passed through.
+If the mailer is capable of sending to more than one user
+on the same host
+in a single transaction
+the
+.q m
+flag should be stated.
+If this flag is on,
+then the argv template containing
+.b $u
+will be repeated for each unique user
+on a given host.
+The
+.q e
+flag will mark the mailer as being
+.q expensive,
+which will cause
+.i sendmail
+to defer connection
+until a queue run\**.
+.(f
+\**The
+.q c
+configuration option must be given
+for this to be effective.
+.)f
+.pp
+An unusual case is the
+.q C
+flag.
+This flag applies to the mailer that the message is received from,
+rather than the mailer being sent to;
+if set,
+the domain spec of the sender
+(i.e., the
+.q @host.domain
+part)
+is saved
+and is appended to any addresses in the message
+that do not already contain a domain spec.
+For example,
+a message of the form:
+.(b
+From: eric@vangogh.CS.Berkeley.EDU
+To: wnj@monet.CS.Berkeley.EDU, mckusick
+.)b
+will be modified to:
+.(b
+From: eric@vangogh.CS.Berkeley.EDU
+To: wnj@monet.CS.Berkeley.EDU, mckusick@vangogh.CS.Berkeley.EDU
+.)b
+.i "if and only if"
+the
+.q C
+flag is defined in the mailer corresponding to
+.q eric@vangogh.CS.Berkeley.EDU.
+.pp
+Other flags are described
+in Appendix C.
+.pp
+The S and R fields in the mailer description
+are per-mailer rewriting sets
+to be applied to sender and recipient addresses
+respectively.
+These are applied after the sending domain is appended
+and the general rewriting sets
+(numbers one and two)
+are applied,
+but before the output rewrite
+(ruleset four)
+is applied.
+A typical use is to append the current domain
+to addresses that do not already have a domain.
+For example,
+a header of the form:
+.(b
+From: eric
+.)b
+might be changed to be:
+.(b
+From: eric@vangogh.CS.Berkeley.EDU
+.)b
+or
+.(b
+From: ucbvax!eric
+.)b
+depending on the domain it is being shipped into.
+These sets can also be used
+to do special purpose output rewriting
+in cooperation with ruleset four.
+.pp
+The E field defines the string to use
+as an end-of-line indication.
+A string containing only newline is the default.
+The usual backslash escapes
+(\er, \en, \ef, \eb)
+may be used.
+.pp
+Finally,
+an argv template is given as the E field.
+It may have embedded spaces.
+If there is no argv with a
+.b $u
+macro in it,
+.i sendmail
+will speak SMTP
+to the mailer.
+If the pathname for this mailer is
+.q [IPC],
+the argv should be
+.(b
+IPC $h [ \fIport\fP ]
+.)b
+where
+.i port
+is the optional port number
+to connect to.
+.pp
+For example,
+the specifications:
+.(b
+.ta \w'Mlocal, 'u +\w'P=/bin/mail, 'u +\w'F=rlsm, 'u +\w'S=10, 'u +\w'R=20, 'u
+Mlocal,        P=/bin/mail,    F=rlsm  S=10,   R=20,   A=mail \-d $u
+Mether,        P=[IPC],        F=meC,  S=11,   R=21,   A=IPC $h, M=100000
+.)b
+specifies a mailer to do local delivery
+and a mailer for ethernet delivery.
+The first is called
+.q local,
+is located in the file
+.q /bin/mail,
+takes a picky
+.b \-r
+flag,
+does local delivery,
+quotes should be stripped from addresses,
+and multiple users can be delivered at once;
+ruleset ten
+should be applied to sender addresses in the message
+and ruleset twenty
+should be applied to recipient addresses;
+the argv to send to a message will be the word
+.q mail,
+the word
+.q \-d,
+and words containing the name of the receiving user.
+If a
+.b \-r
+flag is inserted
+it will be between the words
+.q mail
+and
+.q \-d.
+The second mailer is called
+.q ether,
+it should be connected to via an IPC connection,
+it can handle multiple users at once,
+connections should be deferred,
+and any domain from the sender address
+should be appended to any receiver name
+without a domain;
+sender addresses should be processed by ruleset eleven
+and recipient addresses by ruleset twenty-one.
+There is a 100,000 byte limit on messages passed through this mailer.
+.sh 2 "The User Database"
+.pp
+If you have a version of sendmail with the user database package
+compiled in,
+the handling of sender and recipient addresses
+is modified.
+.pp
+The location of this database is controlled with the
+.b U
+option.
+.sh 3 "Structure of the user database"
+.pp
+The database is a sorted (BTree-based) structure.
+User records are stored with the key:
+.(b
+\fIuser-name\fP\fB:\fP\fIfield-name\fP
+.)b
+The sorted database format ensures that user records are clustered together.
+Meta-information is always stored with a leading colon.
+.pp
+Field names define both the syntax and semantics of the value.
+Defined fields include:
+.nr ii 1i
+.ip maildrop
+The delivery address for this user.
+There may be multiple values of this record.
+In particular,
+mailing lists will have one
+.i maildrop
+record for each user on the list.
+.ip "mailname"
+The outgoing mailname for this user.
+For each outgoing name,
+there should be an appropriate
+.i maildrop
+record for that name to allow return mail.
+See also
+.i :default:mailname .
+.ip mailsender
+Changes any mail sent to this address to have the indicated envelope sender.
+This is intended for mailing lists,
+and will normally be the name of an appropriate -request address.
+It is very similar to the owner-\c
+.i list
+syntax in the alias file.
+.ip fullname
+The full name of the user.
+.ip office-address
+The office address for this user.
+.ip office-phone
+The office phone number for this user.
+.ip office-fax
+The office FAX number for this user.
+.ip home-address
+The home address for this user.
+.ip home-phone
+The home phone number for this user.
+.ip home-fax
+The home FAX number for this user.
+.ip project
+A (short) description of the project this person is affiliated with.
+In the University this is often just the name of their graduate advisor.
+.ip plan
+A pointer to a file from which plan information can be gathered.
+.pp
+As of this writing,
+only a few of these fields are actually being used by sendmail:
+.i maildrop
+and
+.i mailname .
+A
+.i finger
+program that uses the other fields is planned.
+.sh 3 "User database semantics"
+.pp
+When the rewriting rules submit an address to the local mailer,
+the user name is passed through the alias file.
+If no alias is found (or if the alias points back to the same address),
+the name (with
+.q :maildrop
+appended)
+is then used as a key in the user database.
+If no match occurs (or if the maildrop points at the same address),
+forwarding is tried.
+.pp
+If the first token of the user name returned by ruleset 0
+is an
+.q @
+sign, the user database lookup is skipped.
+The intent is that the user database will act as a set of defaults
+for a cluster (in our case, the Computer Science Division);
+mail sent to a specific machine should ignore these defaults.
+.pp
+When mail is sent,
+the name of the sending user is looked up in the database.
+If that user has a
+.q mailname
+record,
+the value of that record is used as their outgoing name.
+For example, I might have a record:
+.(b
+eric:mailname  Eric.Allman@CS.Berkeley.EDU
+.)b
+This would cause my outgoing mail to be sent as Eric.Allman.
+.pp
+If a
+.q maildrop
+is found for the user,
+but no corresponding
+.q maildrop
+record exists,
+the record
+.q :default:mailname
+is consulted.
+If present, this is the name of a host to override the local host.
+For example, in our case we would set it to
+.q CS.Berkeley.EDU .
+The effect is that anyone known in the database
+gets their outgoing mail stamped as
+.q user@CS.Berkeley.EDU ,
+but people not listed in the database use the local hostname.
+.sh 1 "OTHER CONFIGURATION"
+.pp
+There are some configuration changes that can be made by
+recompiling
+.i sendmail .
+This section describes what changes can be made
+and what has to be modified to make them.
+.sh 2 "Parameters in src/Makefile"
+.pp
+These parameters are intended to describe the compilation environment,
+not site policy,
+and should normally be defined in src/Makefile.
+.ip NDBM
+If set,
+the new version of the DBM library
+that allows multiple databases will be used.
+If neither NDBM nor NEWDB are set,
+a much less efficient method of alias lookup is used.
+.ip NEWDB
+If set, use the new database package from Berkeley (from 4.4BSD).
+This package is substantially faster than DBM or NDBM.
+If NEWDB and NDBM are both set,
+sendmail will read DBM files,
+but will create and use NEWDB files.
+.ip YPCOMPAT
+If set together with
+.i both
+NEWDB and NDBM,
+.i sendmail
+will create both DBM and NEWDB files if and only if
+the file /var/yp/Makefile
+exists and is readable.
+This is intended for compatibility with Sun Microsystems'
+.i mkalias
+program used on YP masters.
+.ip _AIX3
+Compile for IBM AIX 3.x.
+This has only been tested on 3.2.3.
+.ip SYSTEM5
+Set all of the compilation parameters appropriate for System V.
+.ip LOCKF
+Use System V
+.b lockf
+instead of Berkeley
+.b flock .
+Due to the highly unusual semantics of locks
+across forks in
+.b lockf ,
+this should never be used unless absolutely necessary.
+Set by default if
+SYSTEM5 is set.
+.ip SYS5TZ
+Use System V
+time zone semantics.
+.ip HASINITGROUPS
+Set this if your system has the
+.i initgroups()
+call
+(if you have multiple group support).
+This is the default if SYSTEM5 is
+.i not
+defined or if you are on HPUX.
+.ip HASUNAME
+Set this if you have the
+.i uname (2)
+system call (or corresponding library routine).
+Set by default if
+SYSTEM5
+is set.
+.ip HASSTATFS
+Set this if you have the
+.i statfs (2)
+system call.
+This will allow you to give a temporary failure
+message to incoming SMTP email
+when you are low on disk space.
+It is set by default on 4.4 BSD and OSF/1 systems.
+.ip HASUSTAT
+Set if you have the
+.i ustat (2)
+system call.
+This is an alternative implementation of disk space control.
+You should only set one of HASSTATFS or HASUSTAT;
+the first is preferred.
+.ip _PATH_SENDMAILCF
+The pathname of the sendmail.cf file.
+.ip _PATH_SENDMAILFC
+The pathname of the sendmail.fc file.
+.ip _PATH_SENDMAILPID
+The pathname of the sendmail.pid file.
+.ip LA_TYPE
+The load average type.
+Details are described below.
+.lp
+The are four built-in ways of computing the load average.
+.i Sendmail
+tries to auto-configure them based on imperfect guesses;
+you can select one using the
+.i cc
+option
+.b \-DLA_TYPE= \c
+.i type ,
+where
+.i type
+is:
+.ip LA_INT
+The kernel stores the load average in the kernel as an array of long integers.
+The actual values are scaled by a factor FSCALE
+(default 256).
+.ip LA_FLOAT
+The kernel stores the load average in the kernel as an array of
+double precision floats.
+.ip LA_SUBR
+Call the
+.i getloadavg
+routine to get the load average as an array of doubles.
+.ip LA_ZERO
+Always return zero as the load average.
+This is the fallback case.
+.lp
+If type
+.sm LA_INT
+or
+.sm LA_FLOAT
+is specified,
+you may also need to specify
+.sm _PATH_UNIX
+(the path to your system binary)
+and
+.sm LA_AVENRUN
+(the name of the variable containing the load average in the kernel;
+usually
+.q _avenrun
+or
+.q avenrun ).
+.sh 2 "Parameters in src/conf.h"
+.pp
+Parameters and compilation options
+are defined in conf.h.
+Most of these need not normally be tweaked;
+common parameters are all in sendmail.cf.
+However, the sizes of certain primitive vectors, etc.,
+are included in this file.
+The numbers following the parameters
+are their default value.
+.nr ii 1.2i
+.ip "MAXLINE [1024]"
+The maximum line length of any input line.
+If message lines exceed this length
+they will still be processed correctly;
+however, header lines,
+configuration file lines,
+alias lines,
+etc.,
+must fit within this limit.
+.ip "MAXNAME [256]"
+The maximum length of any name,
+such as a host or a user name.
+.ip "MAXPV [40]"
+The maximum number of parameters to any mailer.
+This limits the number of recipients that may be passed in one transaction.
+It can be set to any arbitrary number above about 10,
+since
+.i sendmail
+will break up a delivery into smaller batches as needed.
+A higher number may reduce load on your system, however.
+.ip "MAXATOM [100]"
+The maximum number of atoms
+(tokens)
+in a single address.
+For example,
+the address
+.q "eric@CS.Berkeley.EDU"
+is seven atoms.
+.ip "MAXMAILERS [25]"
+The maximum number of mailers that may be defined
+in the configuration file.
+.ip "MAXRWSETS [100]"
+The maximum number of rewriting sets
+that may be defined.
+.ip "MAXPRIORITIES [25]"
+The maximum number of values for the
+.q Precedence:
+field that may be defined
+(using the
+.b P
+line in sendmail.cf).
+.ip "MAXUSERENVIRON [40]"
+The maximum number of items in the user environment
+that will be passed to subordinate mailers.
+.ip "QUEUESIZE [1000]"
+The maximum number of entries that will be processed
+in a single queue run.
+.ip "MAXMXHOSTS [20]"
+The maximum number of MX records we will accept for any single host.
+.ip "MAXIPADDR [16]"
+The maximum number of numeric IP addresses we will accept
+for this host.
+This does not limit the number the number of addresses for other hosts.
+.lp
+A number of other compilation options exist.
+These specify whether or not specific code should be compiled in.
+.nr ii 1.2i
+.ip DEBUG
+If set, debugging information is compiled in.
+To actually get the debugging output,
+the
+.b \-d
+flag must be used.
+.b "WE STRONGLY RECOMMEND THAT THIS BE LEFT ON."
+Some people, believing that it was a security hole
+(it was, once)
+have turned it off and thus crippled debuggers.
+.ip NETINET
+If set,
+support for Internet protocol networking is compiled in.
+Previous versions of
+.b sendmail
+referred to this as
+.sm DAEMON ;
+this old usage is now incorrect.
+.ip NETISO
+If set,
+support for ISO protocol networking is compiled in
+(it may be appropriate to #define this in the Makefile instead of conf.h).
+.ip LOG
+If set,
+the
+.i syslog
+routine in use at some sites is used.
+This makes an informational log record
+for each message processed,
+and makes a higher priority log record
+for internal system errors.
+.ip MATCHGECOS
+Compile in the code to do ``fuzzy matching'' on the GECOS field
+in /etc/passwd.
+This also requires that option G be turned on.
+.ip NAMED_BIND
+Compile in code to use the
+Berkeley Internet Name Domain (BIND) server
+to resolve TCP/IP host names.
+.ip NOTUNIX
+If you are using a non-UNIX mail format,
+you can set this flag to turn off special processing
+of UNIX-style
+.q "From "
+lines.
+.ip QUEUE
+This flag should be set to compile in the queueing code.
+If this is not set,
+mailers must accept the mail immediately
+or it will be returned to the sender.
+.ip SETPROCTITLE
+If defined,
+.i sendmail
+will change its
+.i argv
+array to indicate its current status.
+This can be used in conjunction with the
+.i ps
+command to find out just what it's up to.
+.ip SMTP
+If set,
+the code to handle user and server SMTP will be compiled in.
+This is only necessary if your machine has some mailer
+that speaks SMTP
+(this means most machines everywhere).
+.ip UGLYUUCP
+If you have a UUCP host adjacent to you which is not running
+a reasonable version of
+.i rmail ,
+you will have to set this flag to include the
+.q "remote from sysname"
+info on the from line.
+Otherwise, UUCP gets confused about where the mail came from.
+.ip USERDB
+Include the
+.b experimental
+Berkeley user information database package.
+This adds a new level of local name expansion
+between aliasing and forwarding.
+It also uses the NEWDB package.
+This may change in future releases.
+.ip IDENTPROTO
+Compile in the IDENT protocol as defined in RFC 1413.
+This defaults on for all systems except Ultrix,
+which apparently has the interesting
+.q feature
+that when it receives a
+.q "host unreachable"
+message it closes all open connections to that host.
+Since some firewall gateways send this error code
+when you access an unauthorized port (such as 113, used by IDENT),
+Ultrix cannot receive email from such hosts.
+.sh 2 "Configuration in src/conf.c"
+.pp
+The following changes can be made in conf.c.
+.sh 3 "Built-in Header Semantics"
+.pp
+Not all header semantics are defined in the configuration file.
+Header lines that should only be included by certain mailers
+(as well as other more obscure semantics)
+must be specified in the
+.i HdrInfo
+table in
+.i conf.c .
+This table contains the header name
+(which should be in all lower case)
+and a set of header control flags (described below),
+The flags are:
+.ip H_ACHECK
+Normally when the check is made to see if a header line is compatible
+with a mailer,
+.i sendmail
+will not delete an existing line.
+If this flag is set,
+.i sendmail
+will delete
+even existing header lines.
+That is,
+if this bit is set and the mailer does not have flag bits set
+that intersect with the required mailer flags
+in the header definition in
+sendmail.cf,
+the header line is
+.i always
+deleted.
+.ip H_EOH
+If this header field is set,
+treat it like a blank line,
+i.e.,
+it will signal the end of the header
+and the beginning of the message text.
+.ip H_FORCE
+Add this header entry
+even if one existed in the message before.
+If a header entry does not have this bit set,
+.i sendmail
+will not add another header line if a header line
+of this name already existed.
+This would normally be used to stamp the message
+by everyone who handled it.
+.ip H_TRACE
+If set,
+this is a timestamp
+(trace)
+field.
+If the number of trace fields in a message
+exceeds a preset amount
+the message is returned
+on the assumption that it has an aliasing loop.
+.ip H_RCPT
+If set,
+this field contains recipient addresses.
+This is used by the
+.b \-t
+flag to determine who to send to
+when it is collecting recipients from the message.
+.ip H_FROM
+This flag indicates that this field
+specifies a sender.
+The order of these fields in the
+.i HdrInfo
+table specifies
+.i sendmail's
+preference
+for which field to return error messages to.
+.nr ii 5n
+.lp
+Let's look at a sample
+.i HdrInfo
+specification:
+.(b
+.ta 4n +\w'"return-receipt-to",  'u
+struct hdrinfo HdrInfo[] =
+\&{
+            /* originator fields, most to least significant  */
+       "resent-sender",        H_FROM,
+       "resent-from",  H_FROM,
+       "sender",       H_FROM,
+       "from", H_FROM,
+       "full-name",    H_ACHECK,
+            /* destination fields */
+       "to",   H_RCPT,
+       "resent-to",    H_RCPT,
+       "cc",   H_RCPT,
+            /* message identification and control */
+       "message",      H_EOH,
+       "text", H_EOH,
+            /* trace fields */
+       "received",     H_TRACE|H_FORCE,
+
+       NULL,   0,
+};
+.)b
+This structure indicates that the
+.q To: ,
+.q Resent-To: ,
+and
+.q Cc:
+fields
+all specify recipient addresses.
+Any
+.q Full-Name:
+field will be deleted unless the required mailer flag
+(indicated in the configuration file)
+is specified.
+The
+.q Message:
+and
+.q Text:
+fields will terminate the header;
+these are used by random dissenters around the network world.
+The
+.q Received:
+field will always be added,
+and can be used to trace messages.
+.pp
+There are a number of important points here.
+First,
+header fields are not added automatically just because they are in the
+.i HdrInfo
+structure;
+they must be specified in the configuration file
+in order to be added to the message.
+Any header fields mentioned in the configuration file but not
+mentioned in the
+.i HdrInfo
+structure have default processing performed;
+that is,
+they are added unless they were in the message already.
+Second,
+the
+.i HdrInfo
+structure only specifies cliched processing;
+certain headers are processed specially by ad hoc code
+regardless of the status specified in
+.i HdrInfo .
+For example,
+the
+.q Sender:
+and
+.q From:
+fields are always scanned on ARPANET mail
+to determine the sender\**;
+.(f
+\**Actually, this is no longer true in SMTP;
+this information is contained in the envelope.
+The older ARPANET protocols did not completely distinguish
+envelope from header.
+.)f
+this is used to perform the
+.q "return to sender"
+function.
+The
+.q "From:"
+and
+.q "Full-Name:"
+fields are used to determine the full name of the sender
+if possible;
+this is stored in the macro
+.b $x
+and used in a number of ways.
+.sh 3 "Restricting Use of Email"
+.pp
+If it is necessary to restrict mail through a relay,
+the
+.i checkcompat
+routine can be modified.
+This routine is called for every recipient address.
+It returns an exit status
+indicating the status of the message.
+The status
+.sm EX_OK
+accepts the address,
+.sm EX_TEMPFAIL
+queues the message for a later try,
+and other values
+(commonly
+.sm EX_UNAVAILABLE )
+reject the message.
+It is up to
+.i checkcompat
+to print an error message
+(using
+.i usrerr )
+if the message is rejected.
+For example,
+.i checkcompat
+could read:
+.(b
+.re
+.sz -1
+.ta 4n +4n +4n +4n +4n +4n +4n
+int
+checkcompat(to, e)
+       register ADDRESS *to;
+       register ENVELOPE *e;
+\&{
+       register STAB *s;
+
+       s = stab("private", ST_MAILER, ST_FIND);
+       if (s != NULL && e\->e_from.q_mailer != LocalMailer &&
+           to->q_mailer == s->s_mailer)
+       {
+               usrerr("No private net mail allowed through this machine");
+               return (EX_UNAVAILABLE);
+       }
+       if (MsgSize > 50000 && to\->q_mailer != LocalMailer)
+       {
+               usrerr("Message too large for non-local delivery");
+               NoReturn = TRUE;
+               return (EX_UNAVAILABLE);
+       }
+       return (EX_OK);
+}
+.sz
+.)b
+This would reject messages greater than 50000 bytes
+unless they were local.
+The
+.i NoReturn
+flag can be sent to suppress the return of the actual body
+of the message in the error return.
+The actual use of this routine is highly dependent on the
+implementation,
+and use should be limited.
+.sh 3 "Load Average Computation"
+.pp
+The routine
+.i getla
+should return an approximation of the current system load average
+as an integer.
+There are four versions included on compilation flags
+as described above.
+.sh 3 "New Database Map Classes"
+.pp
+New key maps can be added by creating a class initialization function
+and a lookup function.
+These are then added to the routine
+.i setupmaps.
+.pp
+The initialization function is called as
+.(b
+\fIxxx\fP_map_init(MAP *map, char *mapname, char *args)
+.)b
+The
+.i map
+is an internal data structure.
+The
+.i mapname
+is the name of the map (used for error messages).
+The
+.i args
+is a pointer to the rest of the configuration file line;
+flags and filenames can be extracted from this line.
+The initialization function must return
+.sm TRUE
+if it successfully opened the map,
+.sm FALSE
+otherwise.
+.pp
+The lookup function is called as
+.(b
+\fIxxx\fP_map_lookup(MAP *map, char buf[], int bufsize, char **av, int *statp)
+.)b
+The
+.i map
+defines the map internally.
+The parameters
+.i buf
+and
+.i bufsize
+have the input key.
+This may be (and often is) used destructively.
+The
+.i av
+is a list of arguments passed in from the rewrite line.
+The lookup function should return a pointer to the new value.
+IF the map lookup fails,
+.i *statp
+should be set to an exit status code;
+in particular, it should be set to
+.sm EX_TEMPFAIL
+if recovery is to be attempted by the higher level code.
+.sh 3 "Queueing Function"
+.pp
+The routine
+.i shouldqueue
+is called to decide if a message should be queued
+or processed immediately.
+Typically this compares the message priority to the current load average.
+The default definition is:
+.(b
+bool
+shouldqueue(pri, ctime)
+       long pri;
+       time_t ctime;
+{
+       if (CurrentLA < QueueLA)
+               return (FALSE);
+       if (CurrentLA >= RefuseLA)
+               return (TRUE);
+       return (pri > (QueueFactor / (CurrentLA \- QueueLA + 1)));
+}
+.)b
+If the current load average
+(global variable
+.i CurrentLA ,
+which is set before this function is called)
+is less than the low threshold load average
+(option
+.b x ,
+variable
+.i QueueLA ),
+.i shouldqueue
+returns
+.sm FALSE
+immediately
+(that is, it should
+.i not
+queue).
+If the current load average exceeds the high threshold load average
+(option
+.b X ,
+variable
+.i RefuseLA ),
+.i shouldqueue
+returns
+.sm TRUE
+immediately.
+Otherwise, it computes the function based on the message priority,
+the queue factor
+(option
+.b q ,
+global variable
+.i QueueFactor ),
+and the current and threshold load averages.
+.pp
+An implementation wishing to take the actual age of the message into account
+can also use the
+.i ctime
+parameter,
+which is the time that the message was first submitted to
+.i sendmail .
+Note that the
+.i pri
+parameter is already weighted
+by the number of times the message has been tried
+(although this tends to lower the priority of the message with time);
+the expectation is that the
+.i ctime
+would be used as an
+.q "escape clause"
+to ensure that messages are eventually processed.
+.sh 3 "Refusing Incoming SMTP Connections"
+.pp
+The function
+.i refuseconnections
+returns
+.sm TRUE
+if incoming SMTP connections should be refused.
+The current implementation is based exclusively on the current load average
+and the refuse load average option
+(option
+.b X ,
+global variable
+.i RefuseLA ):
+.(b
+bool
+refuseconnections()
+{
+       return (CurrentLA >= RefuseLA);
+}
+.)b
+A more clever implementation
+could look at more system resources.
+.sh 3 "Load Average Computation"
+.pp
+The routine
+.i getla
+returns the current load average (as a rounded integer).
+The distribution includes several possible implementations.
+.sh 2 "Configuration in src/daemon.c"
+.pp
+The file
+.i src/daemon.c
+contains a number of routines that are dependent
+on the local networking environment.
+The version supplied is specific to 4.3 BSD.
+.pp
+In previous releases,
+we recommended that you modify the routine
+.i maphostname
+if you wanted to generalize
+.b $[
+\&...\&
+.b $]
+lookups.
+We now recommend that you create a new keyed map instead.
+.sh 1 "CHANGES IN VERSION 6"
+.pp
+The following summarizes changes
+since the last commonly available version of
+.b sendmail
+(5.67):
+.sh 2 "Connection Caching"
+.pp
+Instead of closing SMTP connections immediately,
+those connections are cached for possible future use.
+The advent of MX records made this effective for mailing lists;
+in addition,
+substantial performance improvements can be expected for queue processing.
+.sh 2 "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 6 notices this and tries to batch the messages.
+.sh 2 "Eight-Bit Clean"
+.pp
+Previous versions of
+.b sendmail
+used the 0200 bit for quoting.
+This version avoids that use.
+However, for compatibility with RFC 822,
+you can set option `7' to get seven bit stripping.
+.pp
+Individual mailers can still produce seven bit out put using the
+`7' mailer flag.
+.sh 2 "User Database"
+.pp
+The user database 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.
+.sh 2 "Improved BIND Support"
+.pp
+The BIND support,
+particularly for MX records,
+had a number of annoying
+.q 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
+.b sendmail .
+.sh 2 "Keyed Files"
+.pp
+Generalized keyed files is an idea taken directly from
+.sm IDA
+.b sendmail
+(albeit with a completely different implementation).
+They can be useful on large sites.
+.pp
+R6 also understands YP.
+.sh 2 "Multi-Word Classes"
+.pp
+Classes can now be multiple words.
+For example,
+.(b
+CShofmann.CS.Berkeley.EDU
+.)b
+allows you to match the entire string
+.q hofmann.CS.Berkeley.EDU
+using the single construct
+.q $=S .
+.sh 2 "Deferred Macro Expansion"
+.pp
+The
+.b $& \c
+.i x
+construct has been adopted from
+.sm IDA .
+.sh 2 "IDENT Protocol Support"
+.pp
+The IDENT protocol as defined in RFC 1413 is supported.
+.sh 2 "Parsing Bug Fixes"
+.pp
+A number of small bugs having to do with things like
+backslash-escaped quotes inside of comments
+have been fixed.
+.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
+.b $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
+.b S enderRWSet
+and
+.b R ecipientRWset
+arguments for mailers
+can be specified as
+.i 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.
+.sh 2 "Dynamic Header Allocation"
+.pp
+The fixed size limit on header lines has been eliminated.
+.sh 2 "New Command Line Flag"
+.pp
+The \-p flag has been added
+to pass in protocol information.
+.sh 2 "New and Old Configuration Line Types"
+.pp
+The
+.b T
+(Trusted users) configuration line has been deleted.
+It will still be accepted but will be ignored.
+.pp
+The
+.b K
+line has been added to declare database maps.
+.pp
+The
+.b V
+line has been added to declare the configuration version level.
+.sh 2 "New Options"
+.pp
+Several new options have been added,
+many to support new features,
+others to allow tuning that was previously available
+only by recompiling.
+They are described in detail in Section 5.1.5.
+Briefly,
+.ip b
+Insist on a minimum number of disk blocks.
+.ip C
+Set checkpoint interval.
+.ip E
+Default error message.
+.ip G
+Enable GECOS matching.
+.ip h
+Maximum hop count.
+.ip j
+Send errors in MIME-encapsulated format.
+.ip J
+Forward file path.
+.ip k
+Connection cache size
+.ip K
+Connection cache lifetime.
+.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 p
+Privacy options.
+.ip U
+User database spec.
+.ip 7
+Do not run eight bit clean.
+.sh 2 "Extended Options"
+.pp
+The
+.b r
+(read timeout),
+.b I
+(use BIND),
+and
+.b T
+(queue timeout)
+options have been extended to pass in more information.
+.sh 2 "New Mailer Flag"
+.pp
+The
+.b c
+mailer flag will strip all comments
+from addresses;
+this should only be used as a last resort
+when dealing with cranky mailers.
+.sh 2 "New LHS Token"
+.pp
+Version 6 allows
+.b $@
+on the Left Hand Side of an
+.q R
+line to match zero tokens.
+This is intended to be used to match the null input.
+.sh 2 "Bigger Defaults"
+.pp
+Version 6 allows up to 100 rulesets instead of 30.
+It is recommended that rulesets 0\-9 be reserved for
+.i 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 6 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
+.q "Full Name <email address>"
+syntax would generate incorrect protocol output
+if
+.q "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.
+.sh 2 "SMTP VRFY Doesn't Expand"
+.pp
+Previous versions of
+.i 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.
+.sh 2 "[IPC] Mailers Allow Multiple Hosts"
+.pp
+When an address resolves to a mailer that has
+.q [IPC]
+as its
+.q 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 NIS-based aliases.
+.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.
+.sh 1 "ACKNOWLEDGEMENTS"
+.pp
+I've worked on
+.i sendmail
+for many years,
+and many employers have been remarkably patient
+about letting me work on a large project
+that was not part of my official job.
+This includes time on the INGRES Project at Berkeley,
+at Britton Lee,
+and again on the Mammoth Project at Berkeley.
+.pp
+Much of the second wave of improvements
+should be credited to Bryan Costales of ICSI.
+As he passed me drafts of his book on
+.i sendmail
+I was inspired to start working on things again.
+Bryan was also available to bounce ideas off of.
+.pp
+Many, many people contributed chunks of code and ideas to
+.i sendmail .
+It has proven to be a group network effort.
+Version 6 in particular was a group project.
+The following people made notable contributions:
+.(l
+Keith Bostic, CSRG, University of California, Berkeley
+Michael J. Corrigan, University of California, San Diego
+Bryan Costales, International Computer Science Institute
+P{r (Pell) Emanuelsson
+Craig Everhart, Transarc Corporation
+Tom Ivar Helbekkmo, Norwegian School of Economics
+Allan E. Johannesen, WPI
+Takahiro Kanbe, FujiXerox
+Brian Kantor, University of California, San Diego
+Bruce Lilly, Sony U.S.
+Nakamura Motonori, Kyoto University
+John Gardiner Myers, Carnegie Mellon University
+Neil Rickert, Northern Illinois University
+Eric Wassenaar, National Institute for Nuclear and High Energy Physics, Amsterdam
+Christophe Wolfhugel, Herve Schauer Consultants (Paris)
+.)l
+I apologize for anyone I have omitted, misspelled, misattributed, or
+otherwise missed.
+Many other people have contributed ideas, comments, and encouragement.
+I appreciate their contribution as well.
+.++ A
+.+c "COMMAND LINE FLAGS"
+.ba 0
+.nr ii 1i
+.pp
+Arguments must be presented with flags before addresses.
+The flags are:
+.ip \-b\fIx\fP
+Set operation mode to
+.i x .
+Operation modes are:
+.(b
+.ta 4n
+m      Deliver mail (default)
+s      Speak SMTP on input side
+d      Run as a daemon
+t      Run in test mode
+v      Just verify addresses, don't collect or deliver
+i      Initialize the alias database
+p      Print the mail queue
+z      Freeze the configuration file
+.)b
+.ip \-C\fIfile\fP
+Use a different configuration file.
+.i Sendmail
+runs as the invoking user (rather than root)
+when this flag is specified.
+.ip \-d\fIlevel\fP
+Set debugging level.
+.ip "\-f\ \fIaddr\fP"
+The sender's machine address is
+.i addr .
+.ip \-F\fIname\fP
+Sets the full name of this user to
+.i name .
+.ip "\-h\ \fIcnt\fP"
+Sets the
+.q "hop count"
+to
+.i cnt .
+This represents the number of times this message has been processed
+by
+.i sendmail
+(to the extent that it is supported by the underlying networks).
+.i Cnt
+is incremented during processing,
+and if it reaches
+MAXHOP
+(currently 30)
+.i sendmail
+throws away the message with an error.
+.ip \-n
+Don't do aliasing or forwarding.
+.ip "\-r\ \fIaddr\fP"
+An obsolete form of
+.b \-f .
+.ip \-o\fIx\|value\fP
+Set option
+.i x
+to the specified
+.i value .
+These options are described in Appendix B.
+.ip \-p\fIprotocol\fP
+Set the sending protocol.
+Programs are encouraged to set this.
+The protocol field can be in the form
+.i protocol \c
+.b : \c
+.i host
+to set both the sending protocol and sending host.
+For example,
+.q \-pUUCP:uunet
+sets the sending protocol to UUCP
+and the sending host to uunet.
+(Some existing programs use \-oM to set the r and s macros;
+this is equivalent to using \-p.)
+.ip \-q\fItime\fP
+Try to process the queued up mail.
+If the time is given,
+a sendmail will run through the queue at the specified interval
+to deliver queued mail;
+otherwise, it only runs once.
+.ip \-q\fIXstring\fP
+Run the queue once,
+limiting the jobs to those matching
+.i Xstring .
+The key letter
+.i X
+can be
+.b I
+to limit based on queue identifier,
+.b R
+to limit based on recipient,
+or
+.b S
+to limit based on sender.
+A particular queued job is accepted if one of the corresponding addresses
+contains the indicated
+.i string .
+.ip \-t
+Read the header for
+.q To: ,
+.q Cc: ,
+and
+.q Bcc:
+lines, and send to everyone listed in those lists.
+The
+.q Bcc:
+line will be deleted before sending.
+Any addresses in the argument vector will be deleted
+from the send list.
+.pp
+There are a number of options that may be specified as
+primitive flags
+(provided for compatibility with
+.i delivermail ).
+These are the e, i, m, and v options.
+Also,
+the f option
+may be specified as the
+.b \-s
+flag.
+.+c "QUEUE FILE FORMATS"
+.pp
+This appendix describes the format of the queue files.
+These files live in the directory defined by the
+.b Q
+option in the
+.i sendmail.cf
+file, usually
+.i /var/spool/mqueue
+or
+.i /usr/spool/mqueue .
+.pp
+All queue files have the name
+\fIx\fP\|\fBf\fP\fIAAA99999\fP
+where
+.i AAA99999
+is the
+.i id
+for this message
+and the
+.i x
+is a type.
+The first letter of the id encodes the hour of the day
+that the message was received by the system
+(with A being the hour between midnight and 1:00AM).
+All files with the same id collectively define one message.
+.pp
+The types are:
+.nr ii 0.5i
+.ip d
+The data file.
+The message body (excluding the header) is kept in this file.
+.ip l
+The lock file.
+If this file exists,
+the job is currently being processed,
+and a queue run will not process the file.
+For that reason,
+an extraneous
+.b lf
+file can cause a job to apparently disappear
+(it will not even time out!).
+[Actually, this file is obsolete on most systems that support the
+.b flock
+or
+.b lockf
+system calls.]
+.ip n
+This file is created when an id is being created.
+It is a separate file to insure that no mail can ever be destroyed
+due to a race condition.
+It should exist for no more than a few milliseconds
+at any given time.
+[This is only used on old versions of
+sendmail;
+it is not used 
+on newer versions.]
+.ip q
+The queue control file.
+This file contains the information necessary to process the job.
+.ip t
+A temporary file.
+These are an image of the
+.b qf
+file when it is being rebuilt.
+It should be renamed to a
+.b qf
+file very quickly.
+.ip x
+A transcript file,
+existing during the life of a session
+showing everything that happens
+during that session.
+.pp
+The
+.b qf
+file is structured as a series of lines
+each beginning with a code letter.
+The lines are as follows:
+.ip D
+The name of the data file.
+There may only be one of these lines.
+.ip H
+A header definition.
+There may be any number of these lines.
+The order is important:
+they represent the order in the final message.
+These use the same syntax
+as header definitions in the configuration file.
+.ip C
+The controlling address.
+The syntax is
+.q localuser:aliasname .
+Recipient addresses following this line
+will be flagged so that deliveries will be run as the
+.i localuser
+(a user name from the /etc/passwd file);
+.i aliasname
+is the name of the alias that expanded to this address
+(used for printing messages).
+.ip R
+A recipient address.
+This will normally be completely aliased,
+but is actually realiased when the job is processed.
+There will be one line
+for each recipient.
+.ip S
+The sender address.
+There may only be one of these lines.
+.ip E
+An error address.
+If any such lines exist,
+they represent the addresses that should receive error messages.
+.ip T
+The job creation time.
+This is used to compute when to time out the job.
+.ip P
+The current message priority.
+This is used to order the queue.
+Higher numbers mean lower priorities.
+The priority changes
+as the message sits in the queue.
+The initial priority depends on the message class
+and the size of the message.
+.ip M
+A message.
+This line is printed by the
+.i mailq
+command,
+and is generally used to store status information.
+It can contain any text.
+.ip F
+Flag bits, represented as one letter per flag.
+Defined flag bits are
+.b r
+indicating that this is a response message
+and
+.b w
+indicating that a warning message has been sent
+announcing that the mail has been delayed.
+.ip $
+A macro definition.
+The values of certain macros
+(as of this writing, only
+.b $r
+and
+.b $s )
+are passed through to the queue run phase.
+.ip B
+The body type.
+The remainder of the line is a text string defining the body type.
+If this field is missing,
+the body type is assumed to be
+.q "undefined"
+and no special processing is attempted.
+Legal values are
+.q 7BIT
+and
+.q 8BITMIME .
+.pp
+As an example,
+the following is a queue file sent to
+.q eric@mammoth.Berkeley.EDU
+and
+.q bostic@okeeffe.CS.Berkeley.EDU \**:
+.(f
+\**This example is contrived and probably inaccurate for your environment.
+Glance over it to get an idea;
+nothing can replace looking at what your own system generates.
+.)f
+.(b
+P835771
+T404261372
+DdfAAA13557
+Seric
+Eowner-sendmail@vangogh.CS.Berkeley.EDU
+Ceric:sendmail@vangogh.CS.Berkeley.EDU
+Reric@mammoth.Berkeley.EDU
+Rbostic@okeeffe.CS.Berkeley.EDU
+H?P?return-path: <owner-sendmail@vangogh.CS.Berkeley.EDU>
+Hreceived: by vangogh.CS.Berkeley.EDU (5.108/2.7) id AAA06703;
+       Fri, 17 Jul 92 00:28:55 -0700
+Hreceived: from mail.CS.Berkeley.EDU by vangogh.CS.Berkeley.EDU (5.108/2.7)
+       id AAA06698; Fri, 17 Jul 92 00:28:54 -0700
+Hreceived: from [128.32.31.21] by mail.CS.Berkeley.EDU (5.96/2.5)
+       id AA22777; Fri, 17 Jul 92 03:29:14 -0400
+Hreceived: by foo.bar.baz.de (5.57/Ultrix3.0-C)
+       id AA22757; Fri, 17 Jul 92 09:31:25 GMT
+H?F?from: eric@foo.bar.baz.de (Eric Allman)
+H?x?full-name: Eric Allman
+Hmessage-id: <9207170931.AA22757@foo.bar.baz.de>
+HTo: sendmail@vangogh.CS.Berkeley.EDU
+Hsubject: this is an example message
+.)b
+This shows the name of the data file,
+the person who sent the message,
+the submission time
+(in seconds since January 1, 1970),
+the message priority,
+the message class,
+the recipients,
+and the headers for the message.
+.+c "SUMMARY OF SUPPORT FILES"
+.pp
+This is a summary of the support files
+that
+.i sendmail
+creates or generates.
+Many of these can be changed by editing the sendmail.cf file;
+check there to find the actual pathnames.
+.nr ii 1i
+.ip "/usr/\*(SD/sendmail"
+The binary of
+.i sendmail .
+.ip /usr/bin/newaliases
+A link to /usr/\*(SD/sendmail;
+causes the alias database to be rebuilt.
+Running this program is completely equivalent to giving
+.i sendmail
+the
+.b \-bi
+flag.
+.ip /usr/bin/mailq
+Prints a listing of the mail queue.
+This program is equivalent to using the
+.b \-bp
+flag to
+.i sendmail .
+.ip /etc/sendmail.cf
+The configuration file,
+in textual form.
+.ip /etc/sendmail.fc
+The configuration file
+represented as a memory image.
+.ip /usr/lib/sendmail.hf
+The SMTP help file.
+.ip /etc/sendmail.st
+A statistics file; need not be present.
+.ip /etc/sendmail.pid
+Created in daemon mode;
+it contains the process id of the current SMTP daemon.
+If you use this in scripts;
+use ``head \-1'' to get just the first line;
+later versions of
+.i sendmail
+may add information to subsequent lines.
+.ip /etc/aliases
+The textual version of the alias file.
+.ip /etc/aliases.{pag,dir}
+The alias file in
+.i dbm \|(3)
+format.
+.ip /var/spool/mqueue
+The directory in which the mail queue
+and temporary files reside.
+.ip /var/spool/mqueue/qf*
+Control (queue) files for messages.
+.ip /var/spool/mqueue/df*
+Data files.
+.ip /var/spool/mqueue/tf*
+Temporary versions of the qf files,
+used during queue file rebuild.
+.ip /var/spool/mqueue/xf*
+A transcript of the current session.
+.\".ro
+.\".ls 1
+.\".tp
+.\".sp 2i
+.\".in 0
+.\".ce 100
+.\".sz 24
+.\".b SENDMAIL
+.\".sz 14
+.\".sp
+.\"INSTALLATION AND OPERATION GUIDE
+.\".sp
+.\".sz 10
+.\"Eric Allman
+.\"Britton-Lee, Inc.
+.\".sp
+.\"Version 8.1
+.\".ce 0
+.pn 2
+.bp
+.ce
+.sz 12
+TABLE OF CONTENTS
+.sz 10
+.sp
+.\" remove some things to avoid "out of temp file space" problem
+.rm sh
+.rm (x
+.rm )x
+.rm ip
+.rm pp
+.rm lp
+.rm he
+.rm fo
+.rm eh
+.rm oh
+.rm ef
+.rm of
+.xp
diff --git a/usr.sbin/sendmail/doc/op/op.ps b/usr.sbin/sendmail/doc/op/op.ps
new file mode 100644 (file)
index 0000000..2841c70
--- /dev/null
@@ -0,0 +1,5020 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Bold
+%%+ font Times-Roman
+%%+ font Times-Italic
+%%+ font Symbol
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 59
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Bold
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Symbol
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Italic@0 ENC0/Times-Italic RE
+/Times-Roman@0 ENC0/Times-Roman RE/Times-Bold@0 ENC0/Times-Bold RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 16/Times-Bold@0 SF(SENDMAIL)244.888 143.4 Q/F1 12/Times-Bold@0 SF(INST)
+170.172 172.2 Q(ALLA)-1.08 E(TION AND OPERA)-1.14 E(TION GUIDE)-1.14 E/F2 10
+/Times-Roman@0 SF(Eric Allman)263.42 196.2 Q(Uni)219.725 208.2 Q -.15(ve)-.25 G
+(rsity of California, Berk).15 E(ele)-.1 E(y)-.15 E(Mammoth Project)251.75
+220.2 Q(eric@CS.Berk)239.41 232.2 Q(ele)-.1 E -.65(y.)-.15 G(EDU).65 E -1.11
+(Ve)265.225 256.2 S(rsion 8.1)1.11 E -.15(Fo)236.965 280.2 S 2.5(rS).15 G
+(endmail V)258.765 280.2 Q(ersion 8.1)-1.11 E/F3 10/Times-Italic@0 SF(Sendmail)
+97 324.6 Q F2 .699(implements a general purpose internetw)3.199 F .698
+(ork mail routing f)-.1 F .698(acility under the UNIX* operat-)-.1 F .378
+(ing system.)72 336.6 R .378(It is not tied to an)5.378 F 2.878(yo)-.15 G .378
+(ne transport protocol \212 its function may be lik)208.214 336.6 R .378
+(ened to a crossbar switch,)-.1 F 1.036
+(relaying messages from one domain into another)72 348.6 R 6.036(.I)-.55 G
+3.536(nt)284.502 348.6 S 1.036
+(he process, it can do a limited amount of message)295.818 348.6 R .604(header\
+ editing to put the message into a format that is appropriate for the recei)72
+360.6 R .604(ving domain.)-.25 F .604(All of this is)5.604 F
+(done under the control of a con\214guration \214le.)72 372.6 Q .711
+(Due to the requirements of \215e)97 388.8 R .711(xibility for)-.15 F F3
+(sendmail)3.211 E F2 3.211(,t)C .71(he con\214guration \214le can seem some)
+311.688 388.8 R .71(what unap-)-.25 F 2.893(proachable. Ho)72 400.8 R(we)-.25 E
+-.15(ve)-.25 G 1.193 -.4(r, t).15 H .393(here are only a fe).4 F 2.893(wb)-.25
+G .394(asic con\214gurations for most sites, for which standard con\214gu-)
+253.381 400.8 R .646(ration \214les ha)72 412.8 R .946 -.15(ve b)-.2 H .646
+(een supplied.).15 F .645(Most other con\214gurations can be b)5.646 F .645
+(uilt by adjusting an e)-.2 F .645(xisting con\214gura-)-.15 F
+(tion \214les incrementally)72 424.8 Q(.)-.65 E F3(Sendmail)97 441 Q F2 .15
+(is based on RFC822 \(Internet Mail F)2.65 F .15
+(ormat Protocol\), RFC821 \(Simple Mail T)-.15 F .15(ransport Pro-)-.35 F .129
+(tocol\), RFC1123 \(Internet Host Requirements\), and RFC1425 \(SMTP Service E\
+xtensions\).)72 453 R(Ho)5.129 E(we)-.25 E -.15(ve)-.25 G .929 -.4(r, s).15 H
+(ince).4 E F3(sendmail)72 465 Q F2 .749(is designed to w)3.249 F .749
+(ork in a wider w)-.1 F .749(orld, in man)-.1 F 3.25(yc)-.15 G .75
+(ases it can be con\214gured to e)309.31 465 R .75(xceed these proto-)-.15 F
+2.5(cols. These)72 477 R(cases are described herein.)2.5 E(Although)97 493.2 Q
+F3(sendmail)3.548 E F2 1.047(is intended to run without the need for monitorin\
+g, it has a number of features)3.548 F 1.972(that may be used to monitor or ad\
+just the operation under unusual circumstances.)72 505.2 R 1.972
+(These features are)6.972 F(described.)72 517.2 Q .817
+(Section one describes ho)97 533.4 R 3.317(wt)-.25 G 3.317(od)211.668 533.4 S
+3.317(oa)224.985 533.4 S(basic)-.001 E F3(sendmail)3.316 E F2 3.316
+(installation. Section)3.316 F(tw)3.316 E 3.316(oe)-.1 G .816
+(xplains the day-to-day)412.938 533.4 R .282(information you should kno)72
+545.4 R 2.782(wt)-.25 G 2.782(om)196.768 545.4 S .282
+(aintain your mail system.)212.33 545.4 R .282(If you ha)5.282 F .583 -.15
+(ve a r)-.2 H(elati).15 E -.15(ve)-.25 G .283(ly normal site, these tw).15 F(o)
+-.1 E .635(sections should contain suf)72 557.4 R .635
+(\214cient information for you to install)-.25 F F3(sendmail)3.135 E F2 .634
+(and k)3.135 F .634(eep it happ)-.1 F 4.434 -.65(y. S)-.1 H .634(ection three)
+.65 F .925(describes some parameters that may be safely tweak)72 569.4 R 3.425
+(ed. Section)-.1 F .925(four has information re)3.425 F -.05(ga)-.15 G .925
+(rding the com-).05 F .886(mand line ar)72 581.4 R 3.386(guments. Section)-.18
+F<8c76>3.386 E 3.386(ec)-.15 G .885
+(ontains the nitty-gritty information about the con\214guration \214le.)221.92
+581.4 R(This)5.885 E .501
+(section is for masochists and people who must write their o)72 593.4 R .501
+(wn con\214guration \214le.)-.25 F .501(Section six gi)5.501 F -.15(ve)-.25 G
+3.002(sab).15 G(rief)490.12 593.4 Q .355(description of dif)72 605.4 R .355
+(ferences in this v)-.25 F .355(ersion of)-.15 F F3(sendmail)2.855 E F2 5.355
+(.T)C .355(he appendix)298.85 605.4 R .355(es gi)-.15 F .654 -.15(ve a b)-.25 H
+.354(rief b).15 F .354(ut detailed e)-.2 F(xplanation)-.15 E
+(of a number of features not described in the rest of the paper)72 617.4 Q(.)
+-.55 E .32 LW 76 680.4 72 680.4 DL 80 680.4 76 680.4 DL 84 680.4 80 680.4 DL 88
+680.4 84 680.4 DL 92 680.4 88 680.4 DL 96 680.4 92 680.4 DL 100 680.4 96 680.4
+DL 104 680.4 100 680.4 DL 108 680.4 104 680.4 DL 112 680.4 108 680.4 DL 116
+680.4 112 680.4 DL 120 680.4 116 680.4 DL 124 680.4 120 680.4 DL 128 680.4 124
+680.4 DL 132 680.4 128 680.4 DL 136 680.4 132 680.4 DL 140 680.4 136 680.4 DL
+144 680.4 140 680.4 DL 148 680.4 144 680.4 DL 152 680.4 148 680.4 DL 156 680.4
+152 680.4 DL 160 680.4 156 680.4 DL 164 680.4 160 680.4 DL 168 680.4 164 680.4
+DL 172 680.4 168 680.4 DL 176 680.4 172 680.4 DL 180 680.4 176 680.4 DL 184
+680.4 180 680.4 DL 188 680.4 184 680.4 DL 192 680.4 188 680.4 DL 196 680.4 192
+680.4 DL 200 680.4 196 680.4 DL 204 680.4 200 680.4 DL 208 680.4 204 680.4 DL
+212 680.4 208 680.4 DL 216 680.4 212 680.4 DL/F4 8/Times-Roman@0 SF
+(*UNIX is a trademark of Bell Laboratories.)93.6 692.4 Q/F5 10/Times-Bold@0 SF
+(Sendmail Installation and Operation Guide)72 756 Q(SMM:08-1)457.9 756 Q EP
+%%Page: 5 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-5)457.9 60 Q 2.5(1. B)72 96 R(ASIC INST)-.3 E(ALLA)-.9 E(TION)-.95 E/F1
+10/Times-Italic@0 SF 1.121(This section is a very r)112 112.2 R 1.121(ough r)
+-.45 F -.15(ew)-.37 G 1.121(rite; please don').15 F 3.621(ta)-.3 G 1.122
+(ssume that it is alr)325.529 112.2 R 1.122(eady completely corr)-.37 F(ect.)
+-.37 E(Howe)87 124.2 Q(ver)-.15 E 2.5(,p)-1.11 G(lease send me sug)131.84 124.2
+Q -.1(ge)-.1 G(stions so that later ver).1 E(sions of this document can be mor)
+-.1 E 2.5(ea)-.37 G(ccur)450.59 124.2 Q(ate)-.15 E(.)-.15 E/F2 10/Times-Roman@0
+SF .234(There are tw)112 140.4 R 2.733(ob)-.1 G .233
+(asic steps to installing sendmail.)175.631 140.4 R .233(The hard part is to b)
+5.233 F .233(uild the con\214guration table.)-.2 F 1.186(This is a \214le that\
+ sendmail reads when it starts up that describes the mailers it kno)87 152.4 R
+1.186(ws about, ho)-.25 F 3.686(wt)-.25 G(o)499 152.4 Q .715
+(parse addresses, ho)87 164.4 R 3.215(wt)-.25 G 3.215(or)178.315 164.4 S -.25
+(ew)189.86 164.4 S .715(rite the message header).25 F 3.215(,a)-.4 G .715
+(nd the settings of v)306.75 164.4 R .714(arious options.)-.25 F .714
+(Although the)5.714 F .852(con\214guration table is quite comple)87 176.4 R
+.852(x, a con\214guration can usually be b)-.15 F .852(uilt by adjusting an e)
+-.2 F .852(xisting of)-.15 F(f-)-.25 E 1.078(the-shelf con\214guration.)87
+188.4 R 1.078(The second part is actually doing the installation, i.e., creati\
+ng the necessary)6.078 F(\214les, etc.)87 200.4 Q .192(The remainder of this s\
+ection will describe the installation of sendmail assuming you can use one)112
+216.6 R 1.432(of the e)87 228.6 R 1.432(xisting con\214gurations and that the \
+standard installation parameters are acceptable.)-.15 F 1.431(All path-)6.431 F
+8.62(names and e)87 240.6 R 8.62(xamples are gi)-.15 F -.15(ve)-.25 G 11.12(nf)
+.15 G 8.62(rom the root of the)257.57 240.6 R F1(sendmail)378.16 240.6 Q F2
+8.62(subtree, normally)425.39 240.6 R F1(/usr/sr)87 252.6 Q(c/usr)-.37 E
+(.sbin/sendmail)-1.11 E F2(on 4.3BSD.)2.5 E .511(If you are loading this of)112
+268.8 R 3.011(ft)-.25 G .511(he tape, continue with the ne)222.578 268.8 R .511
+(xt session.)-.15 F .511(If you ha)5.511 F .811 -.15(ve a r)-.2 H .511
+(unning binary).15 F
+(already on your system, you should probably skip to section 1.2.)87 280.8 Q F0
+2.5(1.1. Compiling)87 304.8 R(Sendmail)2.5 E F2 .434
+(All sendmail source is in the)127 321 R F1(sr)2.934 E(c)-.37 E F2
+(subdirectory)2.934 E 5.434(.I)-.65 G 2.934(fy)321.652 321 S .435
+(ou are running on a 4.4BSD system, com-)332.916 321 R(pile by typing \231mak)
+102 333 Q 2.5(e\232. On)-.1 F(other systems, you may ha)2.5 E .3 -.15(ve t)-.2
+H 2.5(om).15 G(ak)348.75 333 Q 2.5(es)-.1 G(ome other adjustments.)368.92 333 Q
+F0 2.5(1.1.1. Old)102 357 R -.1(ve)2.5 G(rsions of mak).1 E(e)-.1 E F2
+(If you are not running the ne)142 373.2 Q 2.5(wv)-.25 G(ersion of)270.74 373.2
+Q F0(mak)2.5 E(e)-.1 E F2(you will probably ha)2.5 E .3 -.15(ve t)-.2 H 2.5(ou)
+.15 G(se)444.16 373.2 Q(mak)157 389.4 Q 2.5<65ad>-.1 G 2.5(fM)186.7 389.4 S(ak)
+201.42 389.4 Q(e\214le.dist)-.1 E .885(This \214le does not assume se)117 405.6
+R -.15(ve)-.25 G .885(ral ne).15 F 3.385(ws)-.25 G(yntax)280.025 405.6 Q .885
+(es, including the \231+=\232 syntax in macro de\214nition)-.15 F
+(and the \231.include\232 syntax.)117 417.6 Q F0 2.5(1.1.2. Compilation)102
+441.6 R(\215ags)2.5 E F1(Sendmail)142 457.8 Q F2(supports tw)2.5 E 2.5(od)-.1 G
+(if)240.51 457.8 Q(ferent formats for the)-.25 E F1(aliases)2.5 E F2 2.5
+(database. These)2.5 F(formats are:)2.5 E 39.5(NDBM The)117 474 R -.74(``)3.166
+G(ne).74 E 3.166(wD)-.25 G(BM')240.432 474 Q 3.166('f)-.74 G .666(ormat, a)
+268.408 474 R -.25(va)-.2 G .666(ilable on nearly all systems around today).25
+F 5.667(.T)-.65 G(his)492.33 474 Q -.1(wa)189 486 S 3.541(st).1 G 1.041
+(he preferred format prior to 4.4BSD.)210.771 486 R 1.041(It allo)6.041 F 1.041
+(ws such comple)-.25 F 3.54(xt)-.15 G 1.04(hings as)470.46 486 R
+(multiple databases and closing a currently open database.)189 498 Q 32.84
+(NEWDB The)117 514.2 R(ne)3.323 E 3.323(wd)-.25 G .824
+(atabase package from Berk)232.606 514.2 R(ele)-.1 E 4.624 -.65(y. I)-.15 H
+3.324(fy).65 G .824(ou ha)382.716 514.2 R 1.124 -.15(ve t)-.2 H .824
+(his, use it.).15 F .824(It allo)5.824 F(ws)-.25 E .839
+(long records, multiple open databases, real in-memory caching, and so forth.)
+189 526.2 R -1.1(Yo)189 538.2 S 3.581(uc)1.1 G 1.081
+(an de\214ne this in conjunction with one of the other tw)213.141 538.2 R 1.082
+(o; if you do, old)-.1 F .693(databases are read, b)189 550.2 R .693
+(ut when a ne)-.2 F 3.193(wd)-.25 G .693
+(atabase is created it will be in NEWDB)341.681 550.2 R 4.285(format. As)189
+562.2 R 4.285(an)4.285 G 1.785(asty hack, if you ha)254.065 562.2 R 2.086 -.15
+(ve N)-.2 H 1.786(EWDB, NDBM, and YPCOMP).15 F -1.11(AT)-.92 G 1.163
+(de\214ned, and if the \214le)189 574.2 R F1(/var/yp/Mak)3.663 E(e\214le)-.1 E
+F2 -.15(ex)3.663 G 1.163(ists and is readable,).15 F F1(sendmail)3.662 E F2
+(will)3.662 E .344(create both ne)189 586.2 R 2.844(wa)-.25 G .344(nd old v)
+260.032 586.2 R .345(ersions of the alias \214le during a)-.15 F F1(ne)2.845 E
+(walias)-.15 E F2(command.)2.845 E 1.219
+(This is required because the Sun NIS/YP system reads the DBM v)189 598.2 R
+1.219(ersion of)-.15 F(the alias \214le.)189 610.2 Q(It')5 E 2.5(su)-.55 G
+(gly as sin, b)265.11 610.2 Q(ut it w)-.2 E(orks.)-.1 E 1.112
+(If neither of these are de\214ned,)117 626.4 R F1(sendmail)3.612 E F2 1.112
+(reads the alias \214le into memory on e)3.612 F -.15(ve)-.25 G 1.112(ry in).15
+F -.2(vo)-.4 G(cation.).2 E(This can be slo)117 638.4 Q 2.5(wa)-.25 G
+(nd should be a)191.18 638.4 Q -.2(vo)-.2 G(ided.).2 E .719
+(System V based systems can de\214ne SYSTEM5 to mak)142 654.6 R 3.219(es)-.1 G
+-2.15 -.25(ev e)378.083 654.6 T .719(ral small adjustments.).25 F(This)5.719 E
+1.076(changes the handling of timezones and uses the much less ef)117 666.6 R
+(\214cient)-.25 E F1(loc)3.576 E(kf)-.2 E F2 1.076(call in preference to)3.576
+F F1(\215oc)117 678.6 Q(k)-.2 E F2 7.225(.T)C 2.224(hese can be speci\214ed se\
+parately using the compilation \215ags SYS5TZ and LOCKF)151.515 678.6 R
+(respecti)117 690.6 Q -.15(ve)-.25 G(ly).15 E(.)-.65 E 1.646(If you don')142
+706.8 R 4.147(th)-.18 G -2.25 -.2(av e)202.03 706.8 T(the)4.347 E F1(unseten)
+4.147 E(v)-.4 E F2 1.647(routine in your system library)4.147 F 4.147(,d)-.65 G
+1.647(e\214ne the UNSETENV)411.276 706.8 R(compilation \215ag.)117 718.8 Q EP
+%%Page: 6 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 198.36(SMM:08-6 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF -1.1(Yo)142 96 S
+3.855(um)1.1 G 1.355(ay also ha)169.755 96 R 1.655 -.15(ve t)-.2 H 3.855(od).15
+G 1.355(e\214ne the compilation v)242.035 96 R 1.354
+(ariable LA_TYPE to describe ho)-.25 F 3.854(wy)-.25 G(our)490.67 96 Q(load a)
+117 108 Q -.15(ve)-.2 G(rage is computed.).15 E
+(This and other \215ags are detailed in section 6.1.)5 E F0 2.5
+(1.1.3. Compilation)102 132 R(and installation)2.5 E F1 .308
+(After making the local system con\214guration described abo)142 148.2 R -.15
+(ve)-.15 G 2.809(,Y).15 G .309(ou should be able to com-)398.855 148.2 R .87
+(pile and install the system.)117 162.2 R .87
+(Compilation can be performed using \231mak)5.87 F(e)-.1 E/F2 7/Times-Roman@0
+SF(1)412.24 158.2 Q F1 3.37<9a69>415.74 162.2 S 3.37(nt)426.33 162.2 S(he)
+437.48 162.2 Q F0(sendmail/sr)3.37 E(c)-.18 E F1(directory)117 174.2 Q 5(.Y)
+-.65 G(ou may be able to install using)166.07 174.2 Q(mak)157 190.4 Q 2.5(ei)
+-.1 G(nstall)183.84 190.4 Q 3.346
+(This should install the binary in /usr/sbin and create links from /usr/bin/ne)
+117 206.6 R -.1(wa)-.25 G 3.346(liases and).1 F 1.577
+(/usr/bin/mailq to /usr/sbin/sendmail.)117 218.6 R 1.577
+(On BSD4.4 systems it will also format and install man)6.577 F(pages.)117 230.6
+Q F0 2.5(1.2. Con\214guration)87 254.6 R(Files)2.5 E/F3 10/Times-Italic@0 SF
+(Sendmail)127 270.8 Q F1 .355(cannot operate without a con\214guration \214le.)
+2.855 F .355(The con\214guration de\214nes the mail sys-)5.355 F .286
+(tems understood at this site, ho)102 282.8 R 2.786(wt)-.25 G 2.786(oa)239.856
+282.8 S .286(ccess them, ho)252.082 282.8 R 2.786(wt)-.25 G 2.786(of)323.79
+282.8 S(orw)334.906 282.8 Q .286(ard email to remote mail systems, and)-.1 F
+3.113(an)102 294.8 S .613(umber of tuning parameters.)114.553 294.8 R .614
+(This con\214guration \214le is detailed in the later portion of this docu-)
+5.614 F(ment.)102 306.8 Q(The)127 323 Q F3(sendmail)2.764 E F1 .264
+(con\214guration can be daunting at \214rst.)2.764 F .264(The w)5.264 F .264
+(orld is comple)-.1 F .264(x, and the mail con-)-.15 F .108
+(\214guration re\215ects that.)102 335 R .108(The distrib)5.108 F .109
+(ution includes an m4-based con\214guration package that hides a lot)-.2 F
+(of the comple)102 347 Q(xity)-.15 E(.)-.65 E .47
+(These con\214guration \214les are simpler than old v)127 363.2 R .47
+(ersions lar)-.15 F .47(gely because the w)-.18 F .47(orld has become)-.1 F
+1.448(simpler; in particular)102 375.2 R 3.948(,t)-.4 G -.15(ex)197.604 375.2 S
+1.448(t-based host \214les are of).15 F 1.449(\214cially eliminated, ob)-.25 F
+1.449(viating the need to \231hide\232)-.15 F(hosts behind a re)102 387.2 Q
+(gistered internet g)-.15 E(ate)-.05 E -.1(wa)-.25 G -.65(y.).1 G .092(These \
+\214les also assume that most of your neighbors use domain-based UUCP addressi\
+ng; that)127 403.4 R .361(is, instead of naming hosts as \231host!user\232 the)
+102 415.4 R 2.861(yw)-.15 G .361(ill use \231host.domain!user\232.)299.435
+415.4 R .361(The con\214guration \214les)5.361 F(can be customized to w)102
+427.4 Q(ork around this, b)-.1 E(ut it is more comple)-.2 E(x.)-.15 E 2.828(Ih)
+127 443.6 S -2.25 -.2(av e)138.158 443.6 T(n').2 E 2.828(tt)-.18 G .328
+(ested these yet on an isolated LAN en)168.226 443.6 R .328
+(vironment with a single UUCP connection to)-.4 F 4.408(the outside w)102 455.6
+R 6.908(orld. If)-.1 F 4.409(you are in such an en)6.908 F 4.409
+(vironment, please send comments to send-)-.4 F(mail@ok)102 467.6 Q(eef)-.1 E
+(fe.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU.).65 E .658
+(Our con\214guration \214les are processed by)127 483.8 R F3(m4)3.158 E F1 .658
+(to f)3.158 F .657(acilitate local customization; the directory)-.1 F F3(cf)
+3.157 E F1 .396(of the sendmail distrib)102 495.8 R .396
+(ution directory contains the source \214les.)-.2 F .396
+(This directory contains se)5.396 F -.15(ve)-.25 G .397(ral sub-).15 F
+(directories:)102 507.8 Q 61.73(cf Both)102 524 R .56
+(site-dependent and site-independent descriptions of hosts.)3.06 F .56
+(These can be lit-)5.56 F .445(eral host names \(e.g., \231ucb)174 536 R -.25
+(va)-.15 G .445(x.mc\232\) when the hosts are g).25 F(ate)-.05 E -.1(wa)-.25 G
+.445(ys or more general).1 F 3.589(descriptions \(such as \231tcpproto.mc\232 \
+as a general description of an SMTP-)174 548 R .536(connected host or \231uucp\
+proto.mc\232 as a general description of a UUCP-connected)174 560 R 3.291
+(host\). Files)174 572 R(ending)3.291 E F0(.mc)3.291 E F1(\(`)3.291 E .791
+(`Master Con\214guration')-.74 F .791('\) are the input descriptions; the)-.74
+F 2.14(output is in the corresponding)174 584 R F0(.cf)4.64 E F1 4.64
+(\214le. The)4.64 F 2.14(general structure of these \214les is)4.64 F
+(described belo)174 596 Q -.65(w.)-.25 G 39.5(domain Site-dependent)102 612.2 R
+.428(subdomain descriptions.)2.928 F .428(These are tied to the w)5.428 F .428
+(ay your or)-.1 F -.05(ga)-.18 G(niza-).05 E .292(tion w)174 624.2 R .292
+(ants to do addressing.)-.1 F -.15(Fo)5.292 G 2.792(re).15 G(xample,)313.122
+624.2 Q F0(domain/cs.exposed.m4)2.792 E F1 .292(is our descrip-)2.792 F .443
+(tion for hosts in the CS.Berk)174 636.2 R(ele)-.1 E -.65(y.)-.15 G .443
+(EDU subdomain that w).65 F .442(ant their indi)-.1 F .442(vidual host-)-.25 F
+.962(name to be e)174 648.2 R .963(xternally visible;)-.15 F F0
+(domain/cs.hidden.m4)3.463 E F1 .963(is the same e)3.463 F .963(xcept that the)
+-.15 F 2.628(hostname is hidden \(e)174 660.2 R -.15(ve)-.25 G 2.628
+(rything looks lik).15 F 5.128(ei)-.1 G 5.128(tc)362.038 660.2 S 2.627
+(omes from CS.Berk)374.386 660.2 R(ele)-.1 E -.65(y.)-.15 G(EDU\).).65 E
+(These are referenced using the)174 672.2 Q/F4 9/Times-Roman@0 SF(DOMAIN)2.5 E
+F0(m4)2.5 E F1(macro in the)2.5 E F0(.mc)2.5 E F1(\214le.)2.5 E .32 LW 76 681.8
+72 681.8 DL 80 681.8 76 681.8 DL 84 681.8 80 681.8 DL 88 681.8 84 681.8 DL 92
+681.8 88 681.8 DL 96 681.8 92 681.8 DL 100 681.8 96 681.8 DL 104 681.8 100
+681.8 DL 108 681.8 104 681.8 DL 112 681.8 108 681.8 DL 116 681.8 112 681.8 DL
+120 681.8 116 681.8 DL 124 681.8 120 681.8 DL 128 681.8 124 681.8 DL 132 681.8
+128 681.8 DL 136 681.8 132 681.8 DL 140 681.8 136 681.8 DL 144 681.8 140 681.8
+DL 148 681.8 144 681.8 DL 152 681.8 148 681.8 DL 156 681.8 152 681.8 DL 160
+681.8 156 681.8 DL 164 681.8 160 681.8 DL 168 681.8 164 681.8 DL 172 681.8 168
+681.8 DL 176 681.8 172 681.8 DL 180 681.8 176 681.8 DL 184 681.8 180 681.8 DL
+188 681.8 184 681.8 DL 192 681.8 188 681.8 DL 196 681.8 192 681.8 DL 200 681.8
+196 681.8 DL 204 681.8 200 681.8 DL 208 681.8 204 681.8 DL 212 681.8 208 681.8
+DL 216 681.8 212 681.8 DL/F5 5/Times-Roman@0 SF(1)93.6 692.2 Q/F6 8
+/Times-Roman@0 SF(where you may ha)3.2 I .24 -.12(ve t)-.16 H 2(or).12 G
+(eplace \231mak)175.132 695.4 Q(e\232 with \231mak)-.08 E 2<65ad>-.08 G 2(fM)
+267.452 695.4 S(ak)279.228 695.4 Q(e\214le.dist\232 as appropriate.)-.08 E EP
+%%Page: 7 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-7)457.9 60 Q/F1 10/Times-Roman@0 SF 41.74(feature De\214nitions)102 96
+R .728(of speci\214c features that some particular host in your site might w)
+3.228 F(ant.)-.1 E 2.467(These are referenced using the)174 108 R/F2 9
+/Times-Roman@0 SF(FEA)4.966 E(TURE)-.999 E F0(m4)4.966 E F1 4.966(macro. An)
+4.966 F -.15(ex)4.966 G 2.466(ample feature is).15 F 1.316(use_cw_\214le \(whi\
+ch tells sendmail to read an /etc/sendmail.cw \214le on startup to)174 120 R
+(\214nd the set of local names\).)174 132 Q 50.62(hack Local)102 148.2 R 1.886
+(hacks, referenced using the)4.387 F F2(HA)4.386 E(CK)-.36 E F0(m4)4.386 E F1
+4.386(macro. T)4.386 F 1.886(ry to a)-.35 F -.2(vo)-.2 G 1.886(id these.).2 F
+(The)6.886 E(point of ha)174 160.2 Q(ving them here is to mak)-.2 E 2.5(ei)-.1
+G 2.5(tc)325.91 160.2 S(lear that the)335.63 160.2 Q 2.5(ys)-.15 G(mell.)394.08
+160.2 Q 56.72(m4 Site-independent)102 176.4 R/F3 10/Times-Italic@0 SF(m4)2.538
+E F1 .038(\(1\) include \214les that ha)B .338 -.15(ve i)-.2 H .038
+(nformation common to all con\214gu-).15 F(ration \214les.)174 188.4 Q
+(This can be thought of as a \231#include\232 directory)5 E(.)-.65 E 43.95
+(mailer De\214nitions)102 204.6 R .918(of mailers, referenced using the)3.418 F
+F2(MAILER)3.417 E F0(m4)3.417 E F1 3.417(macro. De\214ned)3.417 F(mailer)3.417
+E(types in this distrib)174 216.6 Q(ution are f)-.2 E
+(ax, local, smtp, uucp, and usenet.)-.1 E 43.39(ostype De\214nitions)102 232.8
+R 1.156(describing v)3.656 F 1.157(arious operating system en)-.25 F 1.157
+(vironments \(such as the loca-)-.4 F(tion of support \214les\).)174 244.8 Q
+(These are referenced using the)5 E F2(OSTYPE)2.5 E F0(m4)2.5 E F1(macro.)2.5 E
+60.61(sh Shell)102 261 R(\214les used by the)2.5 E F0(m4)2.5 E F1 -.2(bu)2.5 G
+(ild process.).2 E -1.1(Yo)5 G 2.5(us)1.1 G(houldn')362.97 261 Q 2.5(th)-.18 G
+-2.25 -.2(av e)404.18 261 T(to mess with these.)2.7 E 30.61(sitecon\214g Local)
+102 277.2 R .49(site con\214guration information, such as UUCP connecti)2.99 F
+(vity)-.25 E 5.49(.T)-.65 G(he)450.61 277.2 Q 2.99(yn)-.15 G(ormally)472.89
+277.2 Q(contain lists of site information, for e)174 289.2 Q(xample:)-.15 E
+(SITE\(contessa\))214 305.4 Q(SITE\(hoptoad\))214 317.4 Q(SITE\(nkainc\))214
+329.4 Q(SITE\(well\))214 341.4 Q(The)174 357.6 Q 2.5(ya)-.15 G
+(re referenced using the SITECONFIG macro:)201.34 357.6 Q
+(SITECONFIG\(site.con\214g.\214le, name_of_site, X\))214 373.8 Q(where)174 390
+Q F3(X)2.703 E F1 .203(is the macro/class name to use.)2.703 F .204
+(It can be U \(indicating locally connected)5.204 F(hosts\) or one of W)174 402
+Q 2.5(,X)-.92 G 2.5(,o)259.73 402 S 2.5(rYf)269.73 402 S
+(or up to three remote UUCP hubs.)288.61 402 Q .757(If you are in a ne)127
+418.2 R 3.257(wd)-.25 G .757(omain \(e.g., a compan)214.042 418.2 R .756
+(y\), you will probably w)-.15 F .756(ant to create a cf/domain)-.1 F .87
+(\214le for your domain.)102 430.2 R .871
+(This consists primarily of relay de\214nitions: for e)5.871 F .871
+(xample, Berk)-.15 F(ele)-.1 E(y')-.15 E 3.371(sd)-.55 G(omain)479 430.2 Q .16
+(de\214nition de\214nes relays for BitNET)102 442.2 R 2.66(,C)-.74 G(SNET)
+257.61 442.2 Q 2.66(,a)-.74 G .16(nd UUCP)291.47 442.2 R 5.16(.O)-1.11 G 2.66
+(ft)344.57 442.2 S .16(hese, only the UUCP relay is particu-)353.34 442.2 R .46
+(larly speci\214c to Berk)102 454.2 R(ele)-.1 E 4.26 -.65(y. A)-.15 H .46
+(ll of these are internet-style domain names.).65 F .46(Please check to mak)
+5.46 F 2.96(ec)-.1 G(er)493.1 454.2 Q(-)-.2 E(tain the)102 466.2 Q 2.5(ya)-.15
+G(re reasonable for your domain.)143.51 466.2 Q 1.407(Subdomains at Berk)127
+482.4 R(ele)-.1 E 3.907(ya)-.15 G 1.407
+(re also represented in the cf/domain directory)235.681 482.4 R 6.406(.F)-.65 G
+1.406(or e)439.408 482.4 R 1.406(xample, the)-.15 F 1.49(domain cs-e)102 494.4
+R 1.491(xposed is the Computer Science subdomain with the local hostname sho)
+-.15 F 1.491(wn to other)-.25 F 1.411(users; cs-hidden mak)102 506.4 R 1.411
+(es users appear to be from the CS.Berk)-.1 F(ele)-.1 E -.65(y.)-.15 G 1.41
+(EDU subdomain \(with no local).65 F 1.083(host information included\).)102
+518.4 R -1.1(Yo)6.083 G 3.583(uw)1.1 G 1.083(ill probably ha)246.332 518.4 R
+1.384 -.15(ve t)-.2 H 3.584(ou).15 G 1.084
+(pdate this directory to be appropriate for)335.866 518.4 R(your domain.)102
+530.4 Q -1.1(Yo)127 546.6 S 4.373(uw)1.1 G 1.873(ill ha)154.713 546.6 R 2.173
+-.15(ve t)-.2 H 4.373(ou).15 G 1.873(se or create)207.482 546.6 R F0(.mc)4.372
+E F1 1.872(\214les in the)4.372 F F3(cf/cf)4.372 E F1 1.872
+(subdirectory for your hosts.)4.372 F 1.872(This is)6.872 F
+(detailed in the cf/README \214le.)102 558.6 Q F0 2.5(1.3. Details)87 582.6 R
+(of Installation Files)2.5 E F1(This subsection describes the \214les that com\
+prise the sendmail installation.)127 598.8 Q F0 2.5(1.3.1. /usr/sbin/sendmail)
+102 622.8 R F1 .08(The binary for sendmail is located in /usr/sbin)142 641 R/F4
+7/Times-Roman@0 SF(2)326.708 637 Q F1 5.079(.I)330.208 641 S 2.579(ts)341.117
+641 S .079(hould be setuid root.)350.366 641 R -.15(Fo)5.079 G 2.579(rs).15 G
+.079(ecurity rea-)458.111 641 R .32 LW 76 669.2 72 669.2 DL 80 669.2 76 669.2
+DL 84 669.2 80 669.2 DL 88 669.2 84 669.2 DL 92 669.2 88 669.2 DL 96 669.2 92
+669.2 DL 100 669.2 96 669.2 DL 104 669.2 100 669.2 DL 108 669.2 104 669.2 DL
+112 669.2 108 669.2 DL 116 669.2 112 669.2 DL 120 669.2 116 669.2 DL 124 669.2
+120 669.2 DL 128 669.2 124 669.2 DL 132 669.2 128 669.2 DL 136 669.2 132 669.2
+DL 140 669.2 136 669.2 DL 144 669.2 140 669.2 DL 148 669.2 144 669.2 DL 152
+669.2 148 669.2 DL 156 669.2 152 669.2 DL 160 669.2 156 669.2 DL 164 669.2 160
+669.2 DL 168 669.2 164 669.2 DL 172 669.2 168 669.2 DL 176 669.2 172 669.2 DL
+180 669.2 176 669.2 DL 184 669.2 180 669.2 DL 188 669.2 184 669.2 DL 192 669.2
+188 669.2 DL 196 669.2 192 669.2 DL 200 669.2 196 669.2 DL 204 669.2 200 669.2
+DL 208 669.2 204 669.2 DL 212 669.2 208 669.2 DL 216 669.2 212 669.2 DL/F5 5
+/Times-Roman@0 SF(2)93.6 679.6 Q/F6 8/Times-Roman@0 SF .384
+(This is usually /usr/sbin on 4.4BSD and ne)3.2 J .384(wer systems; man)-.2 F
+2.385(ys)-.12 G .385(ystems install it in /usr/lib)302.957 682.8 R 4.385(.I)
+-.32 G .385(understand it is in /usr/ucblib on)398.739 682.8 R
+(System V Release 4.)72 692.4 Q EP
+%%Page: 8 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 198.36(SMM:08-8 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(sons, /, /usr)
+117 98 Q 2.5(,a)-.4 G(nd /usr/sbin should be o)171.6 98 Q
+(wned by root, mode 755)-.25 E/F2 7/Times-Roman@0 SF(3)364.4 94 Q F1(.)367.9 98
+Q F0 2.5(1.3.2. /etc/sendmail.cf)102 122 R F1 .781
+(This is the con\214guration \214le for sendmail.)142 138.2 R .78
+(This and the frozen con\214guration \214le are the)5.781 F 2.179(only tw)117
+152.2 R 4.679(on)-.1 G 2.179(on-library \214le names compiled into sendmail)
+164.038 152.2 R F2(4)354.642 148.2 Q F1 7.178(.S)358.142 152.2 S 2.178
+(ome older systems install it in)373.38 152.2 R F0(/usr/lib/sendmail.cf)117
+164.2 Q F1(.)A(If you w)142 180.4 Q(ant to mo)-.1 E .3 -.15(ve t)-.15 H
+(his \214le, change).15 E/F3 10/Times-Italic@0 SF(sr)2.5 E(c/pathnames.h)-.37 E
+F1(.)A .721(The con\214guration \214le is normally created using the distrib)
+142 196.6 R .721(ution \214les described abo)-.2 F -.15(ve)-.15 G 5.721(.I).15
+G(f)500.67 196.6 Q .64(you ha)117 208.6 R .94 -.15(ve a p)-.2 H .64
+(articularly unusual system con\214guration you may need to create a special v)
+.15 F(ersion.)-.15 E
+(The format of this \214le is detailed in later sections of this document.)117
+220.6 Q F0 2.5(1.3.3. /usr/ucb/newaliases)102 244.6 R F1 1.589
+(If you are running deli)142 260.8 R -.15(ve)-.25 G 1.589
+(rmail, it is critical that the).15 F F3(ne)4.089 E(waliases)-.15 E F1 1.59
+(command be replaced.)4.09 F(This can just be a link to)117 272.8 Q F3
+(sendmail)2.5 E F1(:)A(rm \255f /usr/ucb/ne)157 289 Q -.1(wa)-.25 G(liases).1 E
+(ln /usr/sbin/sendmail /usr/ucb/ne)157 301 Q -.1(wa)-.25 G(liases).1 E
+(This can be installed in whate)117 317.2 Q -.15(ve)-.25 G 2.5(rs).15 G
+(earch path you prefer for your system.)254.91 317.2 Q F0 2.5(1.3.4. /v)102
+341.2 R(ar/spool/mqueue)-.1 E F1 .218(The directory)142 357.4 R F3
+(/var/spool/mqueue)2.718 E F1 .217(should be created to hold the mail queue.)
+2.718 F .217(This directory)5.217 F(should be mode 700 and o)117 369.4 Q
+(wned by root.)-.25 E(The actual path of this directory is de\214ned in the)142
+385.6 Q F0(Q)2.5 E F1(option of the)2.5 E F3(sendmail.cf)2.5 E F1(\214le.)2.5 E
+F0 2.5(1.3.5. /etc/aliases*)102 409.6 R F1 1.492
+(The system aliases are held in \231/etc/aliases\232.)142 425.8 R 3.992(As)
+6.492 G 1.492(ample is gi)350.006 425.8 R -.15(ve)-.25 G 3.993(ni).15 G 3.993
+<6e99>417.694 425.8 S 1.493(lib/aliases\232 which)431.127 425.8 R
+(includes some aliases which)117 437.8 Q F3(must)2.5 E F1(be de\214ned:)2.5 E
+(cp lib/aliases /etc/aliases)157 454 Q F3(edit /etc/aliases)157 466 Q F1 -1.1
+(Yo)117 482.2 S 2.5(us)1.1 G(hould e)139.51 482.2 Q(xtend this \214le with an)
+-.15 E 2.5(ya)-.15 G(liases that are apropos to your system.)267.54 482.2 Q
+(Normally)142 498.4 Q F3(sendmail)3.61 E F1 1.109(looks at a v)3.61 F 1.109
+(ersion of these \214les maintained by the)-.15 F F3(dbm)3.609 E F1 1.109
+(\(3\) or)1.666 F F3(db)3.609 E F1(\(3\))1.666 E 3.46(routines. These)117 510.4
+R .96(are stored either in \231/etc/aliases.dir\232 and \231/etc/aliases.pag\
+\232 or \231/etc/aliases.db\232)3.46 F 1.022
+(depending on which database package you are using.)117 522.4 R 1.022
+(These can initially be created as empty)6.022 F(\214les, b)117 534.4 Q(ut the)
+-.2 E 2.5(yw)-.15 G(ill ha)180.54 534.4 Q .3 -.15(ve t)-.2 H 2.5(ob).15 G 2.5
+(ei)227.69 534.4 S(nitialized promptly)237.41 534.4 Q 5(.T)-.65 G
+(hese should be mode 644:)326.76 534.4 Q(cp /de)157 550.6 Q
+(v/null /etc/aliases.dir)-.25 E(cp /de)157 562.6 Q(v/null /etc/aliases.pag)-.25
+E(chmod 644 /etc/aliases.*)157 574.6 Q(ne)157 586.6 Q -.1(wa)-.25 G(liases).1 E
+(The)117 602.8 Q F3(db)2.79 E F1 .29(routines preset the mode reasonably)2.79 F
+2.79(,s)-.65 G 2.79(ot)301.68 602.8 S .29(his step can be skipped.)312.25 602.8
+R .29(The actual path of this)5.29 F(\214le is de\214ned in the)117 614.8 Q F0
+(A)2.5 E F1(option of the)2.5 E F3(sendmail.cf)2.5 E F1(\214le.)2.5 E .32 LW 76
+655.6 72 655.6 DL 80 655.6 76 655.6 DL 84 655.6 80 655.6 DL 88 655.6 84 655.6
+DL 92 655.6 88 655.6 DL 96 655.6 92 655.6 DL 100 655.6 96 655.6 DL 104 655.6
+100 655.6 DL 108 655.6 104 655.6 DL 112 655.6 108 655.6 DL 116 655.6 112 655.6
+DL 120 655.6 116 655.6 DL 124 655.6 120 655.6 DL 128 655.6 124 655.6 DL 132
+655.6 128 655.6 DL 136 655.6 132 655.6 DL 140 655.6 136 655.6 DL 144 655.6 140
+655.6 DL 148 655.6 144 655.6 DL 152 655.6 148 655.6 DL 156 655.6 152 655.6 DL
+160 655.6 156 655.6 DL 164 655.6 160 655.6 DL 168 655.6 164 655.6 DL 172 655.6
+168 655.6 DL 176 655.6 172 655.6 DL 180 655.6 176 655.6 DL 184 655.6 180 655.6
+DL 188 655.6 184 655.6 DL 192 655.6 188 655.6 DL 196 655.6 192 655.6 DL 200
+655.6 196 655.6 DL 204 655.6 200 655.6 DL 208 655.6 204 655.6 DL 212 655.6 208
+655.6 DL 216 655.6 212 655.6 DL/F4 5/Times-Roman@0 SF(3)93.6 666 Q/F5 8
+/Times-Roman@0 SF .149(Some v)3.2 J .15(endors ship them o)-.12 F .15
+(wned by bin; this creates a security hole that is not actually related to)-.2
+F/F6 8/Times-Italic@0 SF(sendmail)2.15 E F5 4.15(.O)C .15(ther important di-)
+447.26 669.2 R(rectories that should ha)72 678.8 Q .24 -.12(ve r)-.16 H
+(estricti).12 E .24 -.12(ve o)-.2 H(wnerships and permissions are /bin, /usr/b\
+in, /etc, /usr/etc, /lib, and /usr/lib)-.08 E(.)-.32 E F4(4)93.6 689.2 Q F5
+.588(The system libraries can reference other \214les; in particular)3.2 J
+2.589(,s)-.32 G .589
+(ystem library subroutines that sendmail calls probably reference)294.805 692.4
+R F6(/etc/passwd)72 702 Q F5(and)2 E F6(/etc/r)2 E(esolv)-.296 E(.conf)-.592 E
+F5(.)A EP
+%%Page: 9 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-9)457.9 60 Q 2.5(1.3.6. /etc/sendmail.fc)102 96 R/F1 10/Times-Roman@0
+SF .61(If you intend to install the frozen v)142 112.2 R .609
+(ersion of the con\214guration \214le \(for quick startup\) you)-.15 F
+(should create the \214le /etc/sendmail.fc and initialize it.)117 124.2 Q
+(This step may be safely skipped.)5 E(cp /de)157 140.4 Q
+(v/null /etc/sendmail.fc)-.25 E(chmod 644 /etc/sendmail.fc)157 152.4 Q
+(/usr/sbin/sendmail \255bz)157 164.4 Q 1.027
+(In general, freeze \214les are not w)117 180.6 R 1.028
+(orth doing unless your disks are much f)-.1 F 1.028(aster than your CPU;)-.1 F
+(this is seldom true an)117 192.6 Q 2.5(ym)-.15 G(ore.)217.13 192.6 Q 1.321
+(If your)142 208.8 R/F2 10/Times-Italic@0 SF(sendmail)3.821 E F1 -.1(wa)3.821 G
+3.821(sn).1 G 1.321(ot compiled with)238.834 208.8 R/F3 9/Times-Roman@0 SF(FR)
+3.821 E(OZENCONFIG)-.36 E F1 1.321(de\214ned, the)3.821 F F0(\255bz)3.821 E F1
+1.32(\215ag will be)3.821 F(ignored.)117 220.8 Q F0 2.5(1.3.7. /etc/r)102 244.8
+R(c)-.18 E F1 .155(It will be necessary to start up the sendmail daemon when y\
+our system reboots.)142 261 R .156(This dae-)5.156 F 1.538(mon performs tw)117
+273 R 4.037(of)-.1 G 1.537(unctions: it listens on the SMTP sock)201.223 273 R
+1.537(et for connections \(to recei)-.1 F 1.837 -.15(ve m)-.25 H(ail).15 E .442
+(from a remote system\) and it processes the queue periodically to insure that\
+ mail gets deli)117 285 R -.15(ve)-.25 G(red).15 E(when hosts come up.)117 297
+Q .505(Add the follo)142 313.2 R .505(wing lines to \231/etc/rc\232 \(or \231/\
+etc/rc.local\232 as appropriate\) in the area where it)-.25 F
+(is starting up the daemons:)117 325.2 Q
+(if [ \255f /usr/sbin/sendmail \255a \255f /etc/sendmail.cf ]; then)157 341.4 Q
+(\(cd /v)193 353.4 Q(ar/spool/mqueue; rm \255f [lnx]f*\))-.25 E
+(/usr/sbin/sendmail \255bd \255q30m &)193 365.4 Q(echo \255n ' sendmail' >/de)
+193 377.4 Q(v/console)-.25 E<8c>157 389.4 Q .173
+(The \231cd\232 and \231rm\232 commands insure that all lock \214les ha)117
+405.6 R .474 -.15(ve b)-.2 H .174(een remo).15 F -.15(ve)-.15 G .174(d; e).15 F
+.174(xtraneous lock \214les)-.15 F .005
+(may be left around if the system goes do)117 417.6 R .004
+(wn in the middle of processing a message.)-.25 F .004(The line that)5.004 F
+2.293(actually in)117 429.6 R -.2(vo)-.4 G -.1(ke).2 G(s).1 E F2(sendmail)4.793
+E F1 2.293(has tw)4.793 F 4.793<6f8d>-.1 G 2.293
+(ags: \231\255bd\232 causes it to listen on the SMTP port, and)272.935 429.6 R
+(\231\255q30m\232 causes it to run the queue e)117 441.6 Q -.15(ve)-.25 G
+(ry half hour).15 E(.)-.55 E .379(Some people use a more comple)142 457.8 R
+2.879(xs)-.15 G .379(tartup script, remo)285.214 457.8 R .378
+(ving zero length qf \214les and df \214les)-.15 F
+(for which there is no qf \214le.)117 469.8 Q -.15(Fo)5 G 2.5(re).15 G(xample:)
+253.9 469.8 Q EP
+%%Page: 10 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-10 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 2.5(#r)157 96 S
+(emo)167.83 96 Q .3 -.15(ve z)-.15 H(ero length qf \214les).15 E(for qf)157 108
+Q(\214le in qf*)-.25 E(do)157 120 Q(if [ \255r $qf)193 132 Q(\214le ])-.25 E
+(then)193 144 Q(if [ ! \255s $qf)229 156 Q(\214le ])-.25 E(then)229 168 Q
+(echo \255n " <zero: $qf)265 180 Q(\214le>" > /de)-.25 E(v/console)-.25 E
+(rm \255f $qf)265 192 Q(\214le)-.25 E<8c>229 204 Q<8c>193 216 Q(done)157 228 Q
+2.5(#r)157 240 S(ename tf \214les to be qf if the qf does not e)167.83 240 Q
+(xist)-.15 E(for tf)157 252 Q(\214le in tf*)-.25 E(do)157 264 Q(qf)193 276 Q
+(\214le=`echo $tf)-.25 E(\214le | sed ')-.25 E(s/t/q/'`)-.55 E(if [ \255r $tf)
+193 288 Q(\214le \255a ! \255f $qf)-.25 E(\214le ])-.25 E(then)193 300 Q
+(echo \255n " <reco)229 312 Q -.15(ve)-.15 G(ring: $tf).15 E(\214le>" > /de)
+-.25 E(v/console)-.25 E(mv $tf)229 324 Q(\214le $qf)-.25 E(\214le)-.25 E(else)
+193 336 Q(echo \255n " <e)229 348 Q(xtra: $tf)-.15 E(\214le>" > /de)-.25 E
+(v/console)-.25 E(rm \255f $tf)229 360 Q(\214le)-.25 E<8c>193 372 Q(done)157
+384 Q 2.5(#r)157 396 S(emo)167.83 396 Q .3 -.15(ve b)-.15 H(ogus qf \214les).15
+E(for df)157 408 Q(\214le in df*)-.25 E(do)157 420 Q(qf)193 432 Q
+(\214le=`echo $df)-.25 E(\214le | sed ')-.25 E(s/d/q/'`)-.55 E(if [ \255r $df)
+193 444 Q(\214le \255a ! \255f $qf)-.25 E(\214le ])-.25 E(then)193 456 Q
+(echo \255n " <incomplete: $df)229 468 Q(\214le>" > /de)-.25 E(v/console)-.25 E
+(rm \255f $df)229 480 Q(\214le)-.25 E<8c>193 492 Q(done)157 504 Q<8c>157 516 Q
+.755(If you are not running a v)142 536.4 R .755
+(ersion of UNIX that supports Berk)-.15 F(ele)-.1 E 3.256(yT)-.15 G(CP/IP)
+416.722 536.4 Q 3.256(,d)-1.11 G 3.256(on)450.268 536.4 S .756(ot include)
+463.524 536.4 R(the)117 548.4 Q F0(\255bd)2.5 E F1(\215ag.)2.5 E F0 2.5
+(1.3.8. /usr/lib/sendmail.hf)102 572.4 R F1 2.078
+(This is the help \214le used by the SMTP)142 588.6 R F0(HELP)4.578 E F1 4.578
+(command. It)4.578 F 2.078(should be copied from)4.578 F
+(\231lib/sendmail.hf\232:)117 600.6 Q(cp lib/sendmail.hf /usr/lib)157 616.8 Q
+(The actual path of this \214le is de\214ned in the)117 633 Q F0(H)2.5 E F1
+(option of the)2.5 E/F2 10/Times-Italic@0 SF(sendmail.cf)2.5 E F1(\214le.)2.5 E
+F0 2.5(1.3.9. /etc/sendmail.st)102 657 R F1 3.04
+(If you wish to collect statistics about your mail traf)142 673.2 R 3.04
+(\214c, you should create the \214le)-.25 F(\231/etc/sendmail.st\232:)117 685.2
+Q(cp /de)157 701.4 Q(v/null /etc/sendmail.st)-.25 E(chmod 666 /etc/sendmail.st)
+157 713.4 Q EP
+%%Page: 11 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-11)452.9 60 Q/F1 10/Times-Roman@0 SF .716(This \214le does not gro)117
+96 R 4.516 -.65(w. I)-.25 H 3.216(ti).65 G 3.216(sp)231.506 96 S .716
+(rinted with the program \231mailstats/mailstats.c.)243.612 96 R 5.715<9a54>-.7
+G .715(he actual path)447.03 96 R(of this \214le is de\214ned in the)117 108 Q
+F0(S)2.5 E F1(option of the)2.5 E/F2 10/Times-Italic@0 SF(sendmail.cf)2.5 E F1
+(\214le.)2.5 E F0 2.5(1.3.10. /usr/ucb/newaliases)102 132 R F1(If)142 148.2 Q
+F2(sendmail)3.255 E F1 .755(is in)3.255 F -.2(vo)-.4 G -.1(ke).2 G 3.255(da).1
+G 3.255<7399>240.42 148.2 S(ne)252.005 148.2 Q -.1(wa)-.25 G(liases,).1 E 3.255
+<9a69>-.7 G 3.255(tw)307.25 148.2 S .755(ill simulate the)320.505 148.2 R F0
+(\255bi)3.255 E F1 .756(\215ag \(i.e., will reb)3.256 F .756(uild the)-.2 F
+(alias database; see belo)117 160.2 Q 2.5(w\). This)-.25 F
+(should be a link to /usr/sbin/sendmail.)2.5 E F0 2.5(1.3.11. /usr/ucb/mailq)
+102 184.2 R F1(If)142 200.4 Q F2(sendmail)3.44 E F1 .94(is in)3.44 F -.2(vo)-.4
+G -.1(ke).2 G 3.44(da).1 G 3.44<7399>241.16 200.4 S(mailq,)252.93 200.4 Q 3.439
+<9a69>-.7 G 3.439(tw)288.169 200.4 S .939(ill simulate the)301.608 200.4 R F0
+(\255bp)3.439 E F1 .939(\215ag \(i.e.,)3.439 F F2(sendmail)3.439 E F1 .939
+(will print)3.439 F(the contents of the mail queue; see belo)117 212.4 Q 2.5
+(w\). This)-.25 F(should be a link to /usr/sbin/sendmail.)2.5 E F0 2.5
+(2. NORMAL)72 236.4 R(OPERA)2.5 E(TIONS)-.95 E 2.5(2.1. `)87 260.4 R(`Quick')
+-.63 E 2.5('C)-.63 G(on\214guration Startup)154.9 260.4 Q F1 .522(if the)127
+276.6 R/F3 9/Times-Roman@0 SF(FR)3.022 E(OZENCONFIG)-.36 E F1 .523
+(option is included during compilation, a precompiled \(`)3.023 F(`frozen')-.74
+E .523('\) v)-.74 F(er)-.15 E(-)-.2 E .068
+(sion of the con\214guration \214le can be created using the)102 288.6 R F0
+(\255bz)2.568 E F1 2.568(\215ag. This)2.568 F .068(is really only w)2.568 F
+.068(orthwhile doing)-.1 F .432(if you are on a slo)102 300.6 R 2.932(wp)-.25 G
+.432(rocessor with a relati)190.992 300.6 R -.15(ve)-.25 G .432(ly f).15 F .432
+(ast I/O system \(a V)-.1 F .432(AX 11/750 is a good e)-1.35 F(xample\).)-.15 E
+.132(Since it creates other problems, I recommend ag)102 312.6 R .131
+(ainst using the frozen con\214guration on most current)-.05 F(architectures.)
+102 324.6 Q 1.6 -.8(To c)127 340.8 T(reate the freeze \214le, use).8 E
+(/usr/sbin/sendmail \255bz)142 357 Q .761
+(This creates the frozen con\214guration \214le)102 373.2 R F2
+(/etc/sendmail.fc)3.261 E F1 5.761(.T)C .762(his \214le is an image of)348.397
+373.2 R F2(sendmail)3.262 E F1 1.862 -.55('s d)D(ata).55 E .693
+(space after reading in the con\214guration \214le.)102 385.2 R .692
+(If this \214le e)5.693 F .692(xists, it is used instead of)-.15 F F2
+(/etc/sendmail.cf)3.192 E(sendmail.fc)102 397.2 Q F1(must be reb)2.5 E
+(uilt manually e)-.2 E -.15(ve)-.25 G(ry time).15 E F2(sendmail.cf)2.5 E F1
+(is changed.)2.5 E .952(The frozen con\214guration \214le will be ignored if a)
+127 413.4 R F0<ad43>3.453 E F1 .953
+(\215ag is speci\214ed or if sendmail detects)3.453 F(that it is out of date.)
+102 425.4 Q(Ho)5 E(we)-.25 E -.15(ve)-.25 G .8 -.4(r, t).15 H
+(he heuristics are not strong so this should not be trusted.).4 E F0 2.5
+(2.2. The)87 449.4 R(System Log)2.5 E F1(The system log is supported by the)127
+465.6 Q F2(syslo)2.5 E(gd)-.1 E F1(\(8\) program.)1.666 E F0 2.5(2.2.1. F)102
+489.6 R(ormat)-.25 E F1 .574(Each line in the system log consists of a timesta\
+mp, the name of the machine that gener)142 505.8 R(-)-.2 E .848
+(ated it \(for logging from se)117 517.8 R -.15(ve)-.25 G .848(ral machines o)
+.15 F -.15(ve)-.15 G 3.349(rt).15 G .849(he local area netw)316.936 517.8 R
+.849(ork\), the w)-.1 F .849(ord \231sendmail:\232,)-.1 F(and a message.)117
+529.8 Q F0 2.5(2.2.2. Le)102 553.8 R -.1(ve)-.15 G(ls).1 E F1 .205(If you ha)
+142 570 R -.15(ve)-.2 G F2(syslo)2.855 E(gd)-.1 E F1 .205(\(8\) or an equi)
+1.666 F -.25(va)-.25 G .205(lent installed, you will be able to do logging.).25
+F .204(There is)5.204 F 2.787(al)117 582 S(ar)127.007 582 Q .287
+(ge amount of information that can be logged.)-.18 F .287
+(The log is arranged as a succession of le)5.287 F -.15(ve)-.25 G(ls.).15 E
+.651(At the lo)117 594 R .651(west le)-.25 F -.15(ve)-.25 G 3.151(lo).15 G .651
+(nly e)201.724 594 R .651(xtremely strange situations are logged.)-.15 F .65
+(At the highest le)5.651 F -.15(ve)-.25 G .65(l, e).15 F -.15(ve)-.25 G 3.15
+(nt).15 G(he)494.56 594 Q .825(most mundane and uninteresting e)117 606 R -.15
+(ve)-.25 G .825(nts are recorded for posterity).15 F 5.826(.A)-.65 G 3.326(sac)
+400.266 606 S(on)419.688 606 Q -.15(ve)-.4 G .826(ntion, log le).15 F -.15(ve)
+-.25 G(ls).15 E .201(under ten are considered generally \231useful;\232 log le)
+117 618 R -.15(ve)-.25 G .201(ls abo).15 F .501 -.15(ve 6)-.15 H 2.701(4a).15 G
+.2(re reserv)381.57 618 R .2(ed for deb)-.15 F .2(ugging pur)-.2 F(-)-.2 E 2.5
+(poses. Le)117 630 R -.15(ve)-.25 G(ls from 11\25564 are reserv).15 E(ed for v)
+-.15 E(erbose information that some sites might w)-.15 E(ant.)-.1 E 2.5(Ac)142
+646.2 S(omplete description of the log le)156.16 646.2 Q -.15(ve)-.25 G
+(ls is gi).15 E -.15(ve)-.25 G 2.5(ni).15 G 2.5(ns)340.35 646.2 S(ection 4.6.)
+351.74 646.2 Q F0 2.5(2.3. The)87 670.2 R(Mail Queue)2.5 E F1 .262
+(The mail queue should be processed transparently)127 686.4 R 5.262(.H)-.65 G
+-.25(ow)342.864 686.4 S -2.15 -.25(ev e).25 H 1.062 -.4(r, y).25 H .263
+(ou may \214nd that manual inter).4 F(-)-.2 E -.15(ve)102 698.4 S .082
+(ntion is sometimes necessary).15 F 5.081(.F)-.65 G .081(or e)240.256 698.4 R
+.081(xample, if a major host is do)-.15 F .081
+(wn for a period of time the queue)-.25 F .267(may become clogged.)102 710.4 R
+.268(Although sendmail ought to reco)5.268 F -.15(ve)-.15 G 2.768(rg).15 G .268
+(racefully when the host comes up, you)348.252 710.4 R
+(may \214nd performance unacceptably bad in the meantime.)102 722.4 Q EP
+%%Page: 12 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-12 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E 2.5(2.3.1. Printing)102 96 R(the queue)
+2.5 E/F1 10/Times-Roman@0 SF .526
+(The contents of the queue can be printed using the)142 112.2 R/F2 10
+/Times-Italic@0 SF(mailq)3.026 E F1 .526(command \(or by specifying the)3.026 F
+F0(\255bp)117 124.2 Q F1(\215ag to sendmail\):)2.5 E(mailq)157 140.4 Q 1.673
+(This will produce a listing of the queue id')117 156.6 R 1.673
+(s, the size of the message, the date the message)-.55 F
+(entered the queue, and the sender and recipients.)117 168.6 Q F0 2.5(2.3.2. F)
+102 192.6 R(or)-.25 E(cing the queue)-.18 E F2(Sendmail)142 208.8 Q F1 1.138
+(should run the queue automatically at interv)3.638 F 3.638(als. The)-.25 F
+1.137(algorithm is to read and)3.638 F .355
+(sort the queue, and then to attempt to process all jobs in order)117 220.8 R
+5.355(.W)-.55 G .356(hen it attempts to run the job,)384.365 220.8 R F2
+(sendmail)117 232.8 Q F1(\214rst checks to see if the job is lock)2.5 E 2.5
+(ed. If)-.1 F(so, it ignores the job)2.5 E(.)-.4 E .338
+(There is no attempt to insure that only one queue processor e)142 249 R .338
+(xists at an)-.15 F 2.838(yt)-.15 G .338(ime, since there)440.284 249 R .094
+(is no guarantee that a job cannot tak)117 261 R 2.595(ef)-.1 G(ore)272.065 261
+Q -.15(ve)-.25 G 2.595(rt).15 G 2.595(op)302.58 261 S .095(rocess \(ho)315.175
+261 R(we)-.25 E -.15(ve)-.25 G -.4(r,).15 G F2(sendmail)2.995 E F1 .095
+(does include heuris-)2.595 F 1.086
+(tics to try to abort jobs that are taking absurd amounts of time; technically)
+117 273 R 3.586(,t)-.65 G 1.086(his violates RFC)435.148 273 R .461(821, b)117
+285 R .461(ut is blessed by RFC 1123\).)-.2 F .461
+(Due to the locking algorithm, it is impossible for one job to)5.461 F 1.087
+(freeze the entire queue.)117 297 R(Ho)6.086 E(we)-.25 E -.15(ve)-.25 G 1.886
+-.4(r, a).15 H 3.586(nu).4 G(ncooperati)279.348 297 Q 1.386 -.15(ve r)-.25 H
+1.086(ecipient host or a program recipient that).15 F(ne)117 309 Q -.15(ve)-.25
+G 3.35(rr).15 G .85(eturns can accumulate man)145.49 309 R 3.351(yp)-.15 G .851
+(rocesses in your system.)269.822 309 R(Unfortunately)5.851 E 3.351(,t)-.65 G
+.851(here is no com-)439.517 309 R(pletely general w)117 321 Q(ay to solv)-.1 E
+2.5(et)-.15 G(his.)234.23 321 Q .082
+(In some cases, you may \214nd that a major host going do)142 337.2 R .082
+(wn for a couple of days may create)-.25 F 2.924(ap)117 349.2 S(rohibiti)
+129.364 349.2 Q -.15(ve)-.25 G .424(ly lar).15 F .424(ge queue.)-.18 F .424
+(This will result in)5.424 F F2(sendmail)2.924 E F1 .425
+(spending an inordinate amount of time)2.924 F 1.085(sorting the queue.)117
+361.2 R 1.085(This situation can be \214x)6.085 F 1.084(ed by mo)-.15 F 1.084
+(ving the queue to a temporary place and)-.15 F .022(creating a ne)117 373.2 R
+2.522(wq)-.25 G 2.522(ueue. The)182.626 373.2 R .022
+(old queue can be run later when the of)2.522 F .023
+(fending host returns to service.)-.25 F 1.6 -.8(To d)142 389.4 T 2.5(ot).8 G
+(his, it is acceptable to mo)170.09 389.4 Q .3 -.15(ve t)-.15 H
+(he entire queue directory:).15 E(cd /v)157 405.6 Q(ar/spool)-.25 E
+(mv mqueue omqueue; mkdir mqueue; chmod 700 mqueue)157 417.6 Q -1.1(Yo)117
+433.8 S 2.709(us)1.1 G .209(hould then kill the e)139.719 433.8 R .209
+(xisting daemon \(since it will still be processing in the old queue direc-)
+-.15 F(tory\) and create a ne)117 445.8 Q 2.5(wd)-.25 G(aemon.)213.1 445.8 Q
+1.6 -.8(To r)142 462 T(un the old mail queue, run the follo).8 E(wing command:)
+-.25 E(/usr/sbin/sendmail \255oQ/v)157 478.2 Q(ar/spool/omqueue \255q)-.25 E
+(The)117 494.4 Q F0(\255oQ)2.867 E F1 .367
+(\215ag speci\214es an alternate queue directory and the)2.867 F F0<ad71>2.867
+E F1 .367(\215ag says to just run e)2.867 F -.15(ve)-.25 G .368(ry job in).15 F
+.594(the queue.)117 506.4 R .594(If you ha)5.594 F .894 -.15(ve a t)-.2 H
+(endenc).15 E 3.093(yt)-.15 G -2.1 -.25(ow a)263.117 506.4 T .593(rd v).25 F
+-.1(oy)-.2 G .593(eurism, you can use the).1 F F0<ad76>3.093 E F1 .593
+(\215ag to w)3.093 F .593(atch what is)-.1 F(going on.)117 518.4 Q
+(When the queue is \214nally emptied, you can remo)142 534.6 Q .3 -.15(ve t)
+-.15 H(he directory:).15 E(rmdir /v)157 550.8 Q(ar/spool/omqueue)-.25 E F0 2.5
+(2.4. The)87 579 R(Alias Database)2.5 E F1 .36(The alias database e)127 595.2 R
+.36(xists in tw)-.15 F 2.86(of)-.1 G 2.861(orms. One)261.11 595.2 R .361
+(is a te)2.861 F .361(xt form, maintained in the \214le)-.15 F F2
+(/etc/aliases.)2.861 E F1(The aliases are of the form)102 607.2 Q
+(name: name1, name2, ...)142 623.4 Q(Only local names may be aliased; e.g.,)102
+639.6 Q(eric@prep.ai.MIT)142 655.8 Q(.EDU: eric@CS.Berk)-.74 E(ele)-.1 E -.65
+(y.)-.15 G(EDU).65 E .349(will not ha)102 672 R .649 -.15(ve t)-.2 H .349
+(he desired ef).15 F 2.849(fect. Aliases)-.25 F .349
+(may be continued by starting an)2.849 F 2.848(yc)-.15 G .348
+(ontinuation lines with a)408.786 672 R(space or a tab)102 684 Q 5(.B)-.4 G
+(lank lines and lines be)170.47 684 Q
+(ginning with a sharp sign \(\231#\232\) are comments.)-.15 E 1.593
+(The second form is processed by the)127 700.2 R F2(dbm)4.093 E F1 1.593
+(\(3\) \(or)1.666 F F2(db)4.093 E F1 1.593(\(3\)\) library)1.666 F 6.593(.T)
+-.65 G 1.593(his form is in the \214les)409.085 700.2 R F2(/etc/aliases.dir)102
+712.2 Q F1(and)3.029 E F2(/etc/aliases.pa)3.029 E -.15(g.)-.1 G F1 .529
+(This is the form that)5.679 F F2(sendmail)3.028 E F1 .528
+(actually uses to resolv)3.028 F 3.028(ea)-.15 G(liases.)479.28 712.2 Q
+(This technique is used to impro)102 724.2 Q .3 -.15(ve p)-.15 H(erformance.)
+.15 E EP
+%%Page: 13 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-13)452.9 60 Q/F1 10/Times-Roman@0 SF -1.1(Yo)127 96 S 2.5(uc)1.1 G
+(an also use)150.06 96 Q/F2 9/Times-Roman@0 SF(NIS)2.5 E F1
+(-based alias \214les.)A -.15(Fo)5 G 2.5(re).15 G(xample, the speci\214cation:)
+305.069 96 Q -.35(OA)142 112.2 S(/etc/aliases).35 E -.35(OA)142 124.2 S
+(nis:mail.aliases@my).35 E(.nis.domain)-.65 E(will \214rst search the /etc/ali\
+ases \214le and then the map named \231mail.aliases\232 in \231my)102 140.4 Q
+(.nis.domain\232.)-.65 E F0 2.5(2.4.1. Reb)102 164.4 R
+(uilding the alias database)-.2 E F1 .542(The DB or DBM v)142 180.6 R .542
+(ersion of the database may be reb)-.15 F .542(uilt e)-.2 F .542
+(xplicitly by e)-.15 F -.15(xe)-.15 G .542(cuting the com-).15 F(mand)117 192.6
+Q(ne)157 208.8 Q -.1(wa)-.25 G(liases).1 E(This is equi)117 225 Q -.25(va)-.25
+G(lent to gi).25 E(ving)-.25 E/F3 10/Times-Italic@0 SF(sendmail)2.5 E F1(the)
+2.5 E F0(\255bi)2.5 E F1(\215ag:)2.5 E(/usr/sbin/sendmail \255bi)157 241.2 Q
+.26(If the \231D\232 option is speci\214ed in the con\214guration,)142 261.6 R
+F3(sendmail)2.759 E F1 .259(will reb)2.759 F .259(uild the alias database)-.2 F
+1.92(automatically if possible when it is out of date.)117 273.6 R(Auto-reb)
+6.921 E 1.921(uild can be dangerous on hea)-.2 F(vily)-.2 E 1.451
+(loaded machines with lar)117 285.6 R 1.451(ge alias \214les; if it might tak)
+-.18 F 3.951(em)-.1 G 1.45(ore than \214v)355.66 285.6 R 3.95(em)-.15 G 1.45
+(inutes to reb)420.13 285.6 R 1.45(uild the)-.2 F
+(database, there is a chance that se)117 297.6 Q -.15(ve)-.25 G
+(ral processes will start the reb).15 E(uild process simultaneously)-.2 E(.)
+-.65 E 1.77(If you ha)142 313.8 R 2.07 -.15(ve m)-.2 H 1.77
+(ultiple aliases databases speci\214ed, the).15 F F0(\255bi)4.27 E F1 1.77
+(\215ag reb)4.27 F 1.77(uilds all the database)-.2 F
+(types it understands \(for e)117 325.8 Q(xample, it can reb)-.15 E
+(uild dbm databases b)-.2 E(ut not nis databases\).)-.2 E F0 2.5(2.4.2. P)102
+349.8 R(otential pr)-.2 E(oblems)-.18 E F1 1.131
+(There are a number of problems that can occur with the alias database.)142 366
+R(The)6.13 E 3.63(ya)-.15 G 1.13(ll result)472.59 366 R 1.103(from a)117 378 R
+F3(sendmail)3.603 E F1 1.103(process accessing the DBM v)3.603 F 1.103
+(ersion while it is only partially b)-.15 F 3.604(uilt. This)-.2 F(can)3.604 E
+1.249(happen under tw)117 390 R 3.749(oc)-.1 G 1.248
+(ircumstances: One process accesses the database while another process is)
+199.237 390 R(reb)117 402 Q .518(uilding it, or the process reb)-.2 F .518
+(uilding the database dies \(due to being killed or a system crash\))-.2 F
+(before completing the reb)117 414 Q(uild.)-.2 E .793(Sendmail has tw)142 430.2
+R 3.293(ot)-.1 G .792(echniques to try to relie)220.669 430.2 R 1.092 -.15
+(ve t)-.25 H .792(hese problems.).15 F .792(First, it ignores interrupts)5.792
+F .045(while reb)117 442.2 R .045(uilding the database; this a)-.2 F -.2(vo)-.2
+G .045(ids the problem of someone aborting the process lea).2 F .045(ving a)-.2
+F(partially reb)117 454.2 Q(uilt database.)-.2 E(Second, at the end of the reb)
+5 E(uild it adds an alias of the form)-.2 E(@: @)157 470.4 Q .336
+(\(which is not normally le)117 486.6 R -.05(ga)-.15 G 2.836(l\). Before).05 F
+.336(sendmail will access the database, it checks to insure that)2.836 F
+(this entry e)117 500.6 Q(xists)-.15 E/F4 7/Times-Roman@0 SF(5)179.63 496.6 Q
+F1(.)183.13 500.6 Q F0 2.5(2.4.3. List)102 524.6 R -.1(ow)2.5 G(ners).1 E F1
+.401(If an error occurs on sending to a certain address, say \231)142 540.8 R
+F3(x)A F1<9a2c>A F3(sendmail)2.9 E F1 .4(will look for an alias)2.9 F .417
+(of the form \231o)117 552.8 R(wner)-.25 E(-)-.2 E F3(x)A F1 2.917<9a74>C 2.917
+(or)212.628 552.8 S(ecei)223.875 552.8 Q .717 -.15(ve t)-.25 H .418(he errors.)
+.15 F .418(This is typically useful for a mailing list where the)5.418 F 1.117
+(submitter of the list has no control o)117 564.8 R -.15(ve)-.15 G 3.617(rt).15
+G 1.116(he maintenance of the list itself; in this case the list)288.406 564.8
+R(maintainer w)117 576.8 Q(ould be the o)-.1 E(wner of the list.)-.25 E -.15
+(Fo)5 G 2.5(re).15 G(xample:)309.38 576.8 Q
+(unix-wizards: eric@ucbarpa, wnj@monet, nosuchuser)157 593 Q(,)-.4 E
+(sam@matisse)193 605 Q -.25(ow)157 617 S(ner).25 E(-unix-wizards: eric@ucbarpa)
+-.2 E -.1(wo)117 633.2 S 1.959(uld cause \231eric@ucbarpa\232 to get the error\
+ that will occur when someone sends to unix-).1 F
+(wizards due to the inclusion of \231nosuchuser\232 on the list.)117 645.2 Q
+.32 LW 76 669.2 72 669.2 DL 80 669.2 76 669.2 DL 84 669.2 80 669.2 DL 88 669.2
+84 669.2 DL 92 669.2 88 669.2 DL 96 669.2 92 669.2 DL 100 669.2 96 669.2 DL 104
+669.2 100 669.2 DL 108 669.2 104 669.2 DL 112 669.2 108 669.2 DL 116 669.2 112
+669.2 DL 120 669.2 116 669.2 DL 124 669.2 120 669.2 DL 128 669.2 124 669.2 DL
+132 669.2 128 669.2 DL 136 669.2 132 669.2 DL 140 669.2 136 669.2 DL 144 669.2
+140 669.2 DL 148 669.2 144 669.2 DL 152 669.2 148 669.2 DL 156 669.2 152 669.2
+DL 160 669.2 156 669.2 DL 164 669.2 160 669.2 DL 168 669.2 164 669.2 DL 172
+669.2 168 669.2 DL 176 669.2 172 669.2 DL 180 669.2 176 669.2 DL 184 669.2 180
+669.2 DL 188 669.2 184 669.2 DL 192 669.2 188 669.2 DL 196 669.2 192 669.2 DL
+200 669.2 196 669.2 DL 204 669.2 200 669.2 DL 208 669.2 204 669.2 DL 212 669.2
+208 669.2 DL 216 669.2 212 669.2 DL/F5 5/Times-Roman@0 SF(5)93.6 679.6 Q/F6 8
+/Times-Roman@0 SF .389(The \231a\232 option is required in the con\214guration\
+ for this action to occur)3.2 J 4.389(.T)-.44 G .389
+(his should normally be speci\214ed unless you are run-)334.237 682.8 R(ning)72
+692.4 Q/F7 8/Times-Italic@0 SF(delivermail)2 E F6(in parallel with)2 E F7
+(sendmail.)2 E EP
+%%Page: 14 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-14 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF .959(List o)142
+96 R .959(wners also cause the en)-.25 F -.15(ve)-.4 G .959
+(lope sender address to be modi\214ed.).15 F .958(The contents of the)5.958 F
+-.25(ow)117 108 S .428(ner alias are used if the).25 F 2.928(yp)-.15 G .428
+(oint to a single user)236.358 108 R 2.928(,o)-.4 G .429
+(therwise the name of the alias itself is used.)326.428 108 R -.15(Fo)117 120 S
+2.5(rt).15 G(his reason, and to obe)136.02 120 Q 2.5(yI)-.15 G(nternet con)
+233.63 120 Q -.15(ve)-.4 G(ntions, a typical scheme w).15 E(ould be:)-.1 E
+18.49(list: some,)157 136.2 R(set, of, addresses)2.5 E 22.28
+(list-request: list,)157 148.2 R(administrators)2.5 E -.25(ow)157 160.2 S(ner)
+.25 E 26.62(-list: list-request)-.2 F F0 2.5(2.5. User)87 188.4 R(Inf)2.5 E
+(ormation Database)-.25 E F1 1.06(If you ha)127 204.6 R 1.36 -.15(ve a ve)-.2 H
+1.06(rsion of).15 F/F2 10/Times-Italic@0 SF(sendmail)3.559 E F1 1.059
+(with the user information database compiled in, and you)3.559 F(ha)102 216.6 Q
+2.205 -.15(ve s)-.2 H 1.905(peci\214ed one or more databases using the).15 F F0
+(U)4.406 E F1 1.906(option, the databases will be searched for a)4.406 F F2
+(user)102 228.6 Q F1(:maildrop entry)A 5(.I)-.65 G 2.5(ff)191.34 228.6 S
+(ound, the mail will be sent to the speci\214ed address.)200.5 228.6 Q 1.288
+(If the \214rst tok)127 244.8 R 1.288(en passed to user part of the \231local\
+\232 mailer is an at sign, the at sign will be)-.1 F(stripped of)102 256.8 Q
+2.5(fa)-.25 G(nd this step will be skipped.)155.07 256.8 Q F0 2.5(2.6. P)87
+280.8 R(er)-.2 E(-User F)-.37 E(orwarding \(.f)-.25 E(orward Files\))-.25 E F1
+.12(As an alternati)127 297 R .42 -.15(ve t)-.25 H 2.62(ot).15 G .12
+(he alias database, an)210.4 297 R 2.62(yu)-.15 G .121
+(ser may put a \214le with the name \231.forw)304.87 297 R .121(ard\232 in his)
+-.1 F .205(or her home directory)102 309 R 5.205(.I)-.65 G 2.705(ft)199.92 309
+S .205(his \214le e)208.735 309 R(xists,)-.15 E F2(sendmail)2.705 E F1 .205
+(redirects mail for that user to the list of addresses)2.705 F .908
+(listed in the .forw)102 321 R .908(ard \214le.)-.1 F -.15(Fo)5.908 G 3.408(re)
+.15 G .908(xample, if the home directory for user \231mckusick\232 has a .forw)
+233.978 321 R(ard)-.1 E(\214le with contents:)102 333 Q(mckusick@ernie)142
+349.2 Q(kirk@calder)142 361.2 Q(then an)102 377.4 Q 2.5(ym)-.15 G(ail arri)
+146.29 377.4 Q
+(ving for \231mckusick\232 will be redirected to the speci\214ed accounts.)-.25
+E(Actually)127 393.6 Q 3.375(,t)-.65 G .874
+(he con\214guration \214le de\214nes a sequence of \214lenames to check.)
+169.445 393.6 R .874(By def)5.874 F .874(ault, this is)-.1 F .687(the user')102
+405.6 R 3.187(s.)-.55 G(forw)146.424 405.6 Q .687(ard \214le, b)-.1 F .687
+(ut can be de\214ned to be more generally using the)-.2 F F0(J)3.187 E F1 3.188
+(option. If)3.188 F .688(you change)3.188 F .393(this, you will ha)102 417.6 R
+.693 -.15(ve t)-.2 H 2.893(oi).15 G .393
+(nform your user base of the change; .forw)193.065 417.6 R .393
+(ard is pretty well incorporated into)-.1 F(the collecti)102 429.6 Q .3 -.15
+(ve s)-.25 H(ubconscious.).15 E F0 2.5(2.7. Special)87 453.6 R(Header Lines)2.5
+E F1(Se)127 469.8 Q -.15(ve)-.25 G 1.897(ral header lines ha).15 F 2.197 -.15
+(ve s)-.2 H 1.897
+(pecial interpretations de\214ned by the con\214guration \214le.).15 F(Others)
+6.898 E(ha)102 481.8 Q 1.206 -.15(ve i)-.2 H .906(nterpretations b).15 F .906
+(uilt into)-.2 F F2(sendmail)3.406 E F1 .905
+(that cannot be changed without changing the code.)3.406 F(These)5.905 E -.2
+(bu)102 493.8 S(iltins are described here.).2 E F0 2.5(2.7.1. Retur)102 517.8 R
+(n-Receipt-T)-.15 E(o:)-.92 E F1 1.37
+(If this header is sent, a message will be sent to an)142 534 R 3.871(ys)-.15 G
+1.371(peci\214ed addresses when the \214nal)366.876 534 R(deli)117 546 Q -.15
+(ve)-.25 G .368(ry is complete, that is, when successfully deli).15 F -.15(ve)
+-.25 G .367(red to a mailer with the).15 F F0(l)2.867 E F1 .367
+(\215ag \(local deli)2.867 F(v-)-.25 E(ery\) set in the mailer descriptor)117
+558 Q(.)-.55 E F0 2.5(2.7.2. Err)102 582 R(ors-T)-.18 E(o:)-.92 E F1 .22
+(If errors occur an)142 598.2 R .22
+(ywhere during processing, this header will cause error messages to go to)-.15
+F(the listed addresses.)117 610.2 Q(This is intended for mailing lists.)5 E
+.385(The Errors-T)142 626.4 R .385(o: header w)-.8 F .384
+(as created in the bad old days when UUCP didn')-.1 F 2.884(tu)-.18 G .384
+(nderstand the)450.016 626.4 R .889(distinction between an en)117 638.4 R -.15
+(ve)-.4 G .889(lope and a header; this w).15 F .889(as a hack to pro)-.1 F .89
+(vide what should no)-.15 F 3.39(wb)-.25 G(e)499.56 638.4 Q(passed as the en)
+117 650.4 Q -.15(ve)-.4 G(lope sender address.).15 E(It should go a)5 E -.1(wa)
+-.15 G 3.8 -.65(y. I).1 H 2.5(ti).65 G 2.5(so)365.22 650.4 S(nly used if the)
+376.61 650.4 Q F0(l)2.5 E F1(option is set.)2.5 E F0 2.5(2.7.3. A)102 674.4 R
+(ppar)-.25 E(ently-T)-.18 E(o:)-.92 E F1 .22
+(If a message comes in with no recipients listed in the message \(in a T)142
+690.6 R .22(o:, Cc:, or Bcc: line\))-.8 F(then)117 702.6 Q F2(sendmail)2.789 E
+F1 .289(will add an \231)2.789 F(Apparently-T)-.8 E .289
+(o:\232 header line for an)-.8 F 2.789(yr)-.15 G .29(ecipients it is a)378.08
+702.6 R -.1(wa)-.15 G .29(re of.).1 F .29(This is)5.29 F
+(not put in as a standard recipient line to w)117 714.6 Q(arn an)-.1 E 2.5(yr)
+-.15 G(ecipients that the list is not complete.)319.77 714.6 Q EP
+%%Page: 15 12
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-15)452.9 60 Q/F1 10/Times-Roman@0 SF
+(At least one recipient line is required under RFC 822.)142 96 Q F0 2.5
+(2.8. IDENT)87 120 R(Pr)2.5 E(otocol Support)-.18 E/F2 10/Times-Italic@0 SF
+(Sendmail)127 136.2 Q F1 1.835
+(supports the IDENT protocol as de\214ned in RFC 1413.)4.335 F 1.835
+(Although this enhances)6.835 F .289
+(identi\214cation of the author of an email message by doing a `)102 148.2 R
+.29(`call back')-.74 F 2.79('t)-.74 G 2.79(ot)396.17 148.2 S .29
+(he originating system to)406.74 148.2 R .469(include the o)102 160.2 R .469(w\
+ner of a particular TCP connection in the audit trail it is in no sense perfec\
+t; a deter)-.25 F(-)-.2 E 1.293(mined for)102 172.2 R 1.294
+(ger can easily spoof the IDENT protocol.)-.18 F 1.294(The follo)6.294 F 1.294
+(wing description is e)-.25 F 1.294(xcerpted from)-.15 F(RFC 1413: 6.)102 184.2
+Q(Security Considerations)5 E .006
+(The information returned by this protocol is at most as trustw)127 200.4 R
+(orth)-.1 E 2.505(ya)-.05 G 2.505(st)400.505 200.4 S .005(he host pro)409.68
+200.4 R .005(viding it OR)-.15 F .273(the or)127 212.4 R -.05(ga)-.18 G .273
+(nization operating the host.).05 F -.15(Fo)5.273 G 2.773(re).15 G .274
+(xample, a PC in an open lab has fe)295.308 212.4 R 2.774(wi)-.25 G 2.774(fa)
+448.612 212.4 S .574 -.15(ny c)459.156 212.4 T(ontrols).15 E .987(on it to pre)
+127 224.4 R -.15(ve)-.25 G .986(nt a user from ha).15 F .986
+(ving this protocol return an)-.2 F 3.486(yi)-.15 G .986
+(denti\214er the user w)378.056 224.4 R 3.486(ants. Lik)-.1 F(e-)-.1 E 1.441(w\
+ise, if the host has been compromised the information returned may be complete\
+ly erro-)127 236.4 R(neous and misleading.)127 248.4 Q .521(The Identi\214cati\
+on Protocol is not intended as an authorization or access control protocol.)127
+264.6 R(At)5.52 E 1.036(best, it pro)127 276.6 R 1.037
+(vides some additional auditing information with respect to TCP connections.)
+-.15 F(At)6.037 E -.1(wo)127 288.6 S(rst, it can pro).1 E
+(vide misleading, incorrect, or maliciously incorrect information.)-.15 E 1.006
+(The use of the information returned by this protocol for other than auditing \
+is strongly dis-)127 304.8 R 2.697(couraged. Speci\214cally)127 316.8 R 2.697
+(,u)-.65 G .197(sing Identi\214cation Protocol information to mak)228.114 316.8
+R 2.697(ea)-.1 G .197(ccess control deci-)429.186 316.8 R .514(sions - either \
+as the primary method \(i.e., no other checks\) or as an adjunct to other meth\
+ods)127 328.8 R(may result in a weak)127 340.8 Q(ening of normal host security)
+-.1 E(.)-.65 E 1.778(An Identi\214cation serv)127 357 R 1.778(er may re)-.15 F
+-.15(ve)-.25 G 1.778
+(al information about users, entities, objects or processes).15 F .337
+(which might normally be considered pri)127 369 R -.25(va)-.25 G 2.836(te. An)
+.25 F .336(Identi\214cation serv)2.836 F .336(er pro)-.15 F .336
+(vides service which)-.15 F .806
+(is a rough analog of the CallerID services pro)127 381 R .806
+(vided by some phone companies and man)-.15 F 3.306(yo)-.15 G(f)500.67 381 Q
+1.398(the same pri)127 393 R -.25(va)-.25 G 1.698 -.15(cy c).25 H 1.398
+(onsiderations and ar).15 F 1.398
+(guments that apply to the CallerID service apply to)-.18 F 3.545
+(Identi\214cation. If)127 405 R 1.045(you w)3.545 F(ouldn')-.1 E 3.545(tr)-.18
+G 1.045(un a "\214nger" serv)260.33 405 R 1.046(er due to pri)-.15 F -.25(va)
+-.25 G 1.346 -.15(cy c).25 H 1.046(onsiderations you may).15 F(not w)127 417 Q
+(ant to run this protocol.)-.1 E F0 2.5(3. ARGUMENTS)72 441 R F1 .018
+(The complete list of ar)112 457.2 R .018(guments to)-.18 F F2(sendmail)2.517 E
+F1 .017(is described in detail in Appendix A.)2.517 F .017(Some important)5.017
+F(ar)87 469.2 Q(guments are described here.)-.18 E F0 2.5(3.1. Queue)87 493.2 R
+(Inter)2.5 E -.1(va)-.1 G(l).1 E F1 .455(The amount of time between forking a \
+process to run through the queue is de\214ned by the)127 509.4 R F0<ad71>2.956
+E F1 2.706(\215ag. If)102 521.4 R .206(you run in mode)2.706 F F0(f)2.706 E F1
+(or)2.706 E F0(a)2.706 E F1 .206(this can be relati)2.706 F -.15(ve)-.25 G .206
+(ly lar).15 F .206(ge, since it will only be rele)-.18 F -.25(va)-.25 G .205
+(nt when a host).25 F .07(that w)102 533.4 R .07(as do)-.1 F .07
+(wn comes back up.)-.25 F .07(If you run in)5.07 F F0(q)2.57 E F1 .07
+(mode it should be relati)2.57 F -.15(ve)-.25 G .07
+(ly short, since it de\214nes the).15 F
+(maximum amount of time that a message may sit in the queue.)102 545.4 Q 1.336
+(RFC 1123 section 5.3.1.1 says that this v)127 561.6 R 1.335
+(alue should be at least 30 minutes \(although that)-.25 F(probably doesn')102
+573.6 Q 2.5(tm)-.18 G(ak)179.59 573.6 Q 2.5(es)-.1 G(ense if you use `)199.76
+573.6 Q(`queue-only')-.74 E 2.5('m)-.74 G(ode\).)329.08 573.6 Q F0 2.5
+(3.2. Daemon)87 597.6 R(Mode)2.5 E F1 .084(If you allo)127 613.8 R 2.584(wi)
+-.25 G .084(ncoming mail o)181.162 613.8 R -.15(ve)-.15 G 2.585(ra).15 G 2.585
+(nI)263.605 613.8 S .085(PC connection, you should ha)274.52 613.8 R .385 -.15
+(ve a d)-.2 H .085(aemon running.).15 F(This)5.085 E .07(should be set by your)
+102 625.8 R F2(/etc/r)2.57 E(c)-.37 E F1 .07(\214le using the)2.57 F F0(\255bd)
+2.57 E F1 2.569(\215ag. The)2.57 F F0(\255bd)2.569 E F1 .069(\215ag and the)
+2.569 F F0<ad71>2.569 E F1 .069(\215ag may be combined)2.569 F(in one call:)102
+637.8 Q(/usr/sbin/sendmail \255bd \255q30m)142 654 Q F0 2.5(3.3. F)87 682.2 R
+(or)-.25 E(cing the Queue)-.18 E F1 .04(In some cases you may \214nd that the \
+queue has gotten clogged for some reason.)127 698.4 R -1.1(Yo)5.04 G 2.54(uc)
+1.1 G .04(an force)471.48 698.4 R 3.185(aq)102 710.4 S .685(ueue run using the)
+114.625 710.4 R F0<ad71>3.184 E F1 .684(\215ag \(with no v)3.184 F 3.184
+(alue\). It)-.25 F .684(is entertaining to use the)3.184 F F0<ad76>3.184 E F1
+.684(\215ag \(v)3.184 F .684(erbose\) when)-.15 F(this is done to w)102 722.4 Q
+(atch what happens:)-.1 E EP
+%%Page: 16 13
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-16 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF
+(/usr/sbin/sendmail \255q \255v)142 96 Q -1.1(Yo)127 116.4 S 4.004(uc)1.1 G
+1.504(an also limit the jobs to those with a particular queue identi\214er)
+151.564 116.4 R 4.004(,s)-.4 G(ender)428.362 116.4 Q 4.004(,o)-.4 G 4.004(rr)
+461.676 116.4 S(ecipient)472.34 116.4 Q .687
+(using one of the queue modi\214ers.)102 128.4 R -.15(Fo)5.687 G 3.187(re).15 G
+.687(xample, \231\255qRberk)265.659 128.4 R(ele)-.1 E .686
+(y\232 restricts the queue run to jobs that)-.15 F(ha)102 140.4 Q .525 -.15
+(ve t)-.2 H .225(he string \231berk).15 F(ele)-.1 E .225(y\232 some)-.15 F .225
+(where in one of the recipient addresses.)-.25 F(Similarly)5.226 E 2.726<2c99>
+-.65 G .226(\255qSstring\232 lim-)441.184 140.4 R(its the run to particular se\
+nders and \231\255qIstring\232 limits it to particular identi\214ers.)102 152.4
+Q F0 2.5(3.4. Deb)87 176.4 R(ugging)-.2 E F1 1.365(There are a f)127 192.6 R
+1.365(airly lar)-.1 F 1.365(ge number of deb)-.18 F 1.365(ug \215ags b)-.2 F
+1.365(uilt into)-.2 F/F2 10/Times-Italic@0 SF(sendmail)3.865 E F1 6.365(.E)C
+1.365(ach deb)417.65 192.6 R 1.365(ug \215ag has a)-.2 F 1.116(number and a le)
+102 204.6 R -.15(ve)-.25 G 1.116(l, where higher le).15 F -.15(ve)-.25 G 1.116
+(ls means to print out more information.).15 F 1.116(The con)6.116 F -.15(ve)
+-.4 G 1.116(ntion is).15 F .294(that le)102 216.6 R -.15(ve)-.25 G .294
+(ls greater than nine are \231absurd,).15 F 2.794<9a69>-.7 G .294(.e., the)
+274.018 216.6 R 2.794(yp)-.15 G .293(rint out so much information that you w)
+313.616 216.6 R(ouldn')-.1 E(t)-.18 E .691(normally w)102 228.6 R .692
+(ant to see them e)-.1 F .692(xcept for deb)-.15 F .692
+(ugging that particular piece of code.)-.2 F(Deb)5.692 E .692
+(ug \215ags are set)-.2 F(using the)102 240.6 Q F0<ad64>2.5 E F1
+(option; the syntax is:)2.5 E(deb)142 256.8 Q(ug-\215ag:)-.2 E F0<ad64>200.13
+256.8 Q F1(deb)2.5 E(ug-list)-.2 E(deb)142 268.8 Q 13.05(ug-list: deb)-.2 F
+(ug-option [ , deb)-.2 E(ug-option ])-.2 E(deb)142 280.8 Q -.28(ug-option: deb)
+-.2 F(ug-range [ . deb)-.2 E(ug-le)-.2 E -.15(ve)-.25 G 2.5(l]).15 G(deb)142
+292.8 Q 3.07(ug-range: inte)-.2 F(ger | inte)-.15 E(ger \255 inte)-.15 E(ger)
+-.15 E(deb)142 304.8 Q(ug-le)-.2 E -.15(ve)-.25 G 6.24(l: inte).15 F(ger)-.15 E
+(where spaces are for reading ease only)102 321 Q 5(.F)-.65 G(or e)268.64 321 Q
+(xample,)-.15 E 34.99(\255d12 Set)142 337.2 R(\215ag 12 to le)2.5 E -.15(ve)
+-.25 G 2.5(l1).15 G 27.49(\255d12.3 Set)142 349.2 R(\215ag 12 to le)2.5 E -.15
+(ve)-.25 G 2.5(l3).15 G 26.66(\255d3-17 Set)142 361.2 R
+(\215ags 3 through 17 to le)2.5 E -.15(ve)-.25 G 2.5(l1).15 G 19.16
+(\255d3-17.4 Set)142 373.2 R(\215ags 3 through 17 to le)2.5 E -.15(ve)-.25 G
+2.5(l4).15 G -.15(Fo)102 389.4 S 4.066(rac).15 G 1.566(omplete list of the a)
+132.752 389.4 R -.25(va)-.2 G 1.565(ilable deb).25 F 1.565
+(ug \215ags you will ha)-.2 F 1.865 -.15(ve t)-.2 H 4.065(ol).15 G 1.565
+(ook at the code \(the)380.9 389.4 R 4.065(ya)-.15 G 1.565(re too)479.385 389.4
+R(dynamic to k)102 401.4 Q(eep this documentation up to date\).)-.1 E F0 2.5
+(3.5. T)87 425.4 R(rying a Differ)-.74 E(ent Con\214guration File)-.18 E F1
+(An alternati)127 441.6 Q .3 -.15(ve c)-.25 H
+(on\214guration \214le can be speci\214ed using the).15 E F0<ad43>2.5 E F1
+(\215ag; for e)2.5 E(xample,)-.15 E(/usr/sbin/sendmail \255Ctest.cf)142 457.8 Q
+.428(uses the con\214guration \214le)102 474 R F2(test.cf)2.928 E F1 .428
+(instead of the def)2.928 F(ault)-.1 E F2(/etc/sendmail.cf)2.928 E(.)-.15 E F1
+.428(If the)5.428 F F0<ad43>2.928 E F1 .429(\215ag has no v)2.928 F(alue)-.25 E
+(it def)102 486 Q(aults to)-.1 E F2(sendmail.cf)2.5 E F1
+(in the current directory)2.5 E(.)-.65 E F0 2.5(3.6. Changing)87 510 R(the V)
+2.5 E(alues of Options)-.92 E F1(Options can be o)127 526.2 Q -.15(ve)-.15 G
+(rridden using the).15 E F0<ad6f>2.5 E F1 2.5(\215ag. F)2.5 F(or e)-.15 E
+(xample,)-.15 E(/usr/sbin/sendmail \255oT2m)142 542.4 Q(sets the)102 558.6 Q F0
+(T)2.5 E F1(\(timeout\) option to tw)2.5 E 2.5(om)-.1 G
+(inutes for this run only)246.63 558.6 Q(.)-.65 E .182(Some options ha)127
+574.8 R .482 -.15(ve s)-.2 H .182(ecurity implications.).15 F .182
+(Sendmail allo)5.182 F .181(ws you to set these, b)-.25 F .181
+(ut refuses to run)-.2 F(as root thereafter)102 586.8 Q(.)-.55 E F0 2.5
+(4. TUNING)72 610.8 R F1 1.922
+(There are a number of con\214guration parameters you may w)112 627 R 1.922
+(ant to change, depending on the)-.1 F .367(requirements of your site.)87 639 R
+.366(Most of these are set using an option in the con\214guration \214le.)5.367
+F -.15(Fo)5.366 G 2.866(re).15 G(xample,)472.06 639 Q(the line \231O)87 651 Q
+(T5d\232 sets option \231T\232 to the v)-.4 E(alue \2315d\232 \(\214v)-.25 E
+2.5(ed)-.15 G(ays\).)312.55 651 Q .735(Most of these options ha)112 667.2 R
+1.035 -.15(ve a)-.2 H .735(ppropriate def).15 F .735(aults for most sites.)-.1
+F(Ho)5.735 E(we)-.25 E -.15(ve)-.25 G 1.535 -.4(r, s).15 H .735(ites ha).4 F
+.735(ving v)-.2 F .735(ery high)-.15 F .046(mail loads may \214nd the)87 679.2
+R 2.546(yn)-.15 G .046(eed to tune them as appropriate for their mail load.)
+193.47 679.2 R .045(In particular)5.045 F 2.545(,s)-.4 G .045(ites e)459.395
+679.2 R(xperi-)-.15 E 1.087(encing a lar)87 691.2 R 1.087
+(ge number of small messages, man)-.18 F 3.587(yo)-.15 G 3.588(fw)294.496 691.2
+S 1.088(hich are deli)308.634 691.2 R -.15(ve)-.25 G 1.088(red to man).15 F
+3.588(yr)-.15 G 1.088(ecipients, may \214nd)425.994 691.2 R(that the)87 703.2 Q
+2.5(yn)-.15 G(eed to adjust the parameters dealing with queue priorities.)
+129.07 703.2 Q EP
+%%Page: 17 14
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-17)452.9 60 Q 2.5(4.1. T)87 96 R(imeouts)-.18 E/F1 10/Times-Roman@0 SF
+.583(All time interv)127 112.2 R .583(als are set using a scaled syntax.)-.25 F
+-.15(Fo)5.583 G 3.083(re).15 G .583
+(xample, \23110m\232 represents ten minutes,)346.14 112.2 R
+(whereas \2312h30m\232 represents tw)102 124.2 Q 2.5(oa)-.1 G(nd a half hours.)
+241.3 124.2 Q(The full set of scales is:)5 E 16.11(ss)142 140.4 S(econds)165.89
+140.4 Q 12.22(mm)142 152.4 S(inutes)169.78 152.4 Q 15(hh)142 164.4 S(ours)167
+164.4 Q 15(dd)142 176.4 S(ays)167 176.4 Q 12.78(ww)142 188.4 S(eeks)169.22
+188.4 Q F0 2.5(4.1.1. Queue)102 216.6 R(inter)2.5 E -.1(va)-.1 G(l).1 E F1 .18
+(The ar)142 232.8 R .18(gument to the)-.18 F F0<ad71>2.68 E F1 .18
+(\215ag speci\214es ho)2.68 F 2.68(wo)-.25 G .18
+(ften a sub-daemon will run the queue.)319.25 232.8 R .18(This is)5.18 F .968
+(typically set to between \214fteen minutes and one hour)117 244.8 R 5.968(.R)
+-.55 G .967(FC 1123 section 5.3.1.1 recommends)350.972 244.8 R
+(that this be at least 30 minutes.)117 256.8 Q F0 2.5(4.1.2. Read)102 280.8 R
+(timeouts)2.5 E F1 .51(It is possible to time out when reading the standard in\
+put or when reading from a remote)142 297 R .324(SMTP serv)117 309 R(er)-.15 E
+5.324(.T)-.55 G .324(hese timeouts are set using the)183.608 309 R F0(r)2.824 E
+F1 .324(option in the con\214guration \214le.)2.824 F .324(The ar)5.324 F
+(gument)-.18 E .842(is a list of)117 321 R/F2 10/Times-Italic@0 SF -.1(ke)3.342
+G(ywor)-.2 E(d=value)-.37 E F1 3.342(pairs. The)3.342 F .842(recognized k)3.342
+F -.15(ey)-.1 G -.1(wo).15 G .842(rds, their def).1 F .842(ault v)-.1 F .843
+(alues, and the mini-)-.25 F(mum v)117 333 Q(alues allo)-.25 E
+(wed by RFC 1123 section 5.3.2 are:)-.25 E 46.16(initial The)117 349.2 R -.1
+(wa)2.5 G(it for the initial 220 greeting message [5m, 5m].).1 E 52.28
+(helo The)117 365.4 R -.1(wa)4.227 G 1.727
+(it for a reply from a HELO or EHLO command [5m, unspeci\214ed].).1 F .1
+(This may require a host name lookup, so \214v)189 377.4 R 2.6(em)-.15 G .1
+(inutes is probably a reasonable)380.29 377.4 R(minimum.)189 389.4 Q 46.72
+(mail\207 The)117 405.6 R -.1(wa)2.5 G
+(it for a reply from a MAIL command [10m, 5m].).1 E 48.95(rcpt\207 The)117
+421.8 R -.1(wa)3.482 G .982(it for a reply from a RCPT command [1h, 5m].).1 F
+.981(This should be long)5.981 F
+(because it could be pointing at a list that tak)189 433.8 Q
+(es a long time to e)-.1 E(xpand.)-.15 E 34.5(datainit\207 The)117 450 R -.1
+(wa)2.5 G(it for a reply from a D).1 E -1.21 -1.11(AT A)-.4 H
+(command [5m, 2m].)3.61 E 25.62(datablock\207 The)117 466.2 R -.1(wa)2.696 G
+.196(it for reading a data block \(that is, the body of the message\).).1 F
+.196([1h, 3m].)5.196 F .621
+(This should be long because it also applies to programs piping input to)189
+478.2 R F2(send-)3.12 E(mail)189 490.2 Q F1(which ha)2.5 E .3 -.15(ve n)-.2 H
+2.5(og).15 G(uarantee of promptness.)274.75 490.2 Q 30.06(data\214nal\207 The)
+117 506.4 R -.1(wa)2.806 G .306
+(it for a reply from the dot terminating a message.).1 F .306([1h, 10m].)5.306
+F .306(If this is)5.306 F .884
+(shorter than the time actually needed for the recei)189 518.4 R -.15(ve)-.25 G
+3.383(rt).15 G 3.383(od)412.881 518.4 S(eli)426.264 518.4 Q -.15(ve)-.25 G
+3.383(rt).15 G .883(he message,)454.797 518.4 R(duplicates will be generated.)
+189 530.4 Q(This is discussed in RFC 1047.)5 E 55.06(rset The)117 546.6 R -.1
+(wa)2.5 G(it for a reply from a RSET command [5m, unspeci\214ed].).1 E 53.94
+(quit The)117 562.8 R -.1(wa)2.5 G(it for a reply from a Q).1 E
+(UIT command [2m, unspeci\214ed].)-.1 E 50.61(misc The)117 579 R -.1(wa)2.76 G
+.261(it for a reply from miscellaneous \(b).1 F .261
+(ut short\) commands such as NOOP)-.2 F(\(no-operation\) and VERB \(go into v)
+189 591 Q(erbose mode\).)-.15 E([2m, unspeci\214ed].)5 E 25.06(command\207 In)
+117 607.2 R(serv)2.5 E(er SMTP)-.15 E 2.5(,t)-1.11 G(he time to w)259.4 607.2 Q
+(ait for another command.)-.1 E([1h, 5m].)5 E -.15(Fo)117 623.4 S 3.634(rc).15
+G 1.134(ompatibility with old con\214guration \214les, if no `)138.814 623.4 R
+(`k)-.74 E -.15(ey)-.1 G -.1(wo).15 G(rd=').1 E 3.634('i)-.74 G 3.634(ss)
+390.856 623.4 S 1.133(peci\214ed, all the timeouts)402.27 623.4 R(mark)117
+635.4 Q(ed with \207 are set to the indicated v)-.1 E(alue.)-.25 E(Man)142
+651.6 Q 2.5(yo)-.15 G 2.5(ft)172.68 651.6 S(he RFC 1123 minimum v)181.29 651.6
+Q .001(alues may well be too short.)-.25 F F2(Sendmail)5.001 E F1 -.1(wa)2.501
+G 2.501(sd).1 G .001(esigned to)463.169 651.6 R .067
+(the RFC 822 protocols, which did not specify read timeouts; hence,)117 663.6 R
+F2(sendmail)2.566 E F1 .066(does not guarantee)2.566 F .437
+(to reply to messages promptly)117 675.6 R 5.438(.I)-.65 G 2.938(np)249.918
+675.6 S(articular)262.856 675.6 Q 2.938(,a\231)-.4 G .438
+(RCPT\232 command specifying a mailing list will)313.032 675.6 R -.15(ex)117
+689.6 S .205(pand and v).15 F .205(erify the entire list; a lar)-.15 F .205
+(ge list on a slo)-.18 F 2.705(ws)-.25 G .205(ystem may tak)339.81 689.6 R
+2.705(em)-.1 G .205(ore than \214v)413.375 689.6 R 2.705(em)-.15 G(inutes)
+474.11 689.6 Q/F3 7/Times-Roman@0 SF(6)498 685.6 Q F1(.)501.5 689.6 Q EP
+%%Page: 18 15
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-18 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 3.037(Ir)117 96
+S .536(ecommend a one hour timeout \212 since this f)126.697 96 R .536
+(ailure is rare, a long timeout is not onerous and)-.1 F
+(may ultimately help reduce netw)117 108 Q(ork load.)-.1 E -.15(Fo)142 124.2 S
+2.5(re).15 G(xample, the line:)162.53 124.2 Q(Orcommand=25m,datablock=3h)157
+140.4 Q .343(sets the serv)117 156.6 R .344(er SMTP command timeout to 25 minu\
+tes and the input data block timeout to three)-.15 F(hours.)117 168.6 Q F0 2.5
+(4.1.3. Message)102 192.6 R(timeouts)2.5 E F1 .238
+(After sitting in the queue for a fe)142 208.8 R 2.737(wd)-.25 G .237
+(ays, a message will time out.)289.733 208.8 R .237(This is to insure that at)
+5.237 F .282(least the sender is a)117 220.8 R -.1(wa)-.15 G .282
+(re of the inability to send a message.).1 F .283
+(The timeout is typically set to three)5.282 F 2.5(days. This)117 232.8 R
+(timeout is set using the)2.5 E F0(T)2.5 E F1
+(option in the con\214guration \214le.)2.5 E .413(The time of submission is se\
+t in the queue, rather than the amount of time left until time-)142 249 R 3.262
+(out. As)117 261 R 3.262(ar)3.262 G .762
+(esult, you can \215ush messages that ha)163.446 261 R 1.062 -.15(ve b)-.2 H
+.763(een hanging for a short period by running).15 F
+(the queue with a short message timeout.)117 273 Q -.15(Fo)5 G 2.5(re).15 G
+(xample,)302.79 273 Q(/usr/sbin/sendmail \255oT1d \255q)157 289.2 Q
+(will run the queue and \215ush an)117 305.4 Q(ything that is one day old.)-.15
+E 1.077(Since this option is global, and since you can not)142 321.6 R/F2 10
+/Times-Italic@0 SF 3.577(ap)3.577 G(riori)364.397 321.6 Q F1(kno)3.577 E 3.577
+(wh)-.25 G 1.577 -.25(ow l)416.861 321.6 T 1.076(ong another host).25 F .475
+(outside your domain will be do)117 333.6 R .475(wn, a \214v)-.25 F 2.975(ed)
+-.15 G .475(ay timeout is recommended.)291.78 333.6 R .476(This allo)5.476 F
+.476(ws a recipient)-.25 F 1.58(to \214x the problem e)117 345.6 R -.15(ve)-.25
+G 4.08(ni).15 G 4.08(fi)222.55 345.6 S 4.08(to)232.74 345.6 S 1.579
+(ccurs at the be)244.6 345.6 R 1.579(ginning of a long week)-.15 F 4.079
+(end. RFC)-.1 F 1.579(1123 section)4.079 F
+(5.3.1.1 says that this parameter should be `)117 357.6 Q
+(`at least 4\2555 days')-.74 E('.)-.74 E(The)142 373.8 Q F0(T)2.71 E F1 .21
+(option can also tak)2.71 F -5.209 2.71(ea s)-.1 H .211
+(econd timeout indicating a time after which a w)263.631 373.8 R .211
+(arning mes-)-.1 F(sage should be sent; the tw)117 385.8 Q 2.5(ot)-.1 G
+(imeouts are separated by a slash.)234.67 385.8 Q -.15(Fo)5 G 2.5(re).15 G
+(xample, the v)391.28 385.8 Q(alue)-.25 E(5d/4h)157 402 Q .972
+(causes email to f)117 418.2 R .971(ail after \214v)-.1 F 3.471(ed)-.15 G .971
+(ays, b)245.329 418.2 R .971(ut a w)-.2 F .971
+(arning message will be sent after four hours.)-.1 F(This)5.971 E
+(should be lar)117 430.2 Q(ge enough that the message will ha)-.18 E .3 -.15
+(ve b)-.2 H(een tried se).15 E -.15(ve)-.25 G(ral times.).15 E F0 2.5(4.2. F)87
+454.2 R(orking During Queue Runs)-.25 E F1 .302(By setting the)127 470.4 R F0
+(Y)2.802 E F1(option,)2.802 E F2(sendmail)2.802 E F1 .302
+(will fork before each indi)2.802 F .302(vidual message while running the)-.25
+F 2.514(queue. This)102 482.4 R .013(will pre)2.514 F -.15(ve)-.25 G(nt).15 E
+F2(sendmail)2.513 E F1 .013(from consuming lar)2.513 F .013
+(ge amounts of memory)-.18 F 2.513(,s)-.65 G 2.513(oi)421.995 482.4 S 2.513(tm)
+432.288 482.4 S .013(ay be useful in)445.361 482.4 R .591(memory-poor en)102
+494.4 R 3.091(vironments. Ho)-.4 F(we)-.25 E -.15(ve)-.25 G 1.391 -.4(r, i).15
+H 3.091(ft).4 G(he)275.384 494.4 Q F0(Y)3.091 E F1 .591(option is not set,)
+3.091 F F2(sendmail)3.091 E F1 .592(will k)3.092 F .592(eep track of hosts)-.1
+F(that are do)102 506.4 Q(wn during a queue run, which can impro)-.25 E .3 -.15
+(ve p)-.15 H(erformance dramatically).15 E(.)-.65 E(If the)127 522.6 Q F0(Y)2.5
+E F1(option is set,)2.5 E F2(sendmail)2.5 E F1(can not use connection caching.)
+2.5 E F0 2.5(4.3. Queue)87 546.6 R(Priorities)2.5 E F1(Ev)127 562.8 Q 1.128(er\
+y message is assigned a priority when it is \214rst instantiated, consisting o\
+f the message)-.15 F .002(size \(in bytes\) of)102 574.8 R .002
+(fset by the message class times the \231w)-.25 F .002(ork class f)-.1 F .003
+(actor\232 and the number of recipients)-.1 F .638(times the \231w)102 586.8 R
+.638(ork recipient f)-.1 F(actor)-.1 E 4.538 -.7(.\232 T)-.55 H .637
+(he priority is used to order the queue.).7 F .637(Higher numbers for the)5.637
+F(priority mean that the message will be processed later when running the queu\
+e.)102 598.8 Q .328(The message size is included so that lar)127 615 R .329
+(ge messages are penalized relati)-.18 F .629 -.15(ve t)-.25 H 2.829(os).15 G
+.329(mall messages.)443.121 615 R .285(The message class allo)102 627 R .285(w\
+s users to send \231high priority\232 messages by including a \231Precedence:\
+\232 \214eld)-.25 F .007(in their message; the v)102 639 R .007
+(alue of this \214eld is look)-.25 F .008(ed up in the)-.1 F F0(P)2.508 E F1
+.008(lines of the con\214guration \214le.)2.508 F .008(Since the)5.008 F 1.967
+(number of recipients af)102 651 R 1.967
+(fects the amount of load a message presents to the system, this is also)-.25 F
+(included into the priority)102 663 Q(.)-.65 E .32 LW 76 678.8 72 678.8 DL 80
+678.8 76 678.8 DL 84 678.8 80 678.8 DL 88 678.8 84 678.8 DL 92 678.8 88 678.8
+DL 96 678.8 92 678.8 DL 100 678.8 96 678.8 DL 104 678.8 100 678.8 DL 108 678.8
+104 678.8 DL 112 678.8 108 678.8 DL 116 678.8 112 678.8 DL 120 678.8 116 678.8
+DL 124 678.8 120 678.8 DL 128 678.8 124 678.8 DL 132 678.8 128 678.8 DL 136
+678.8 132 678.8 DL 140 678.8 136 678.8 DL 144 678.8 140 678.8 DL 148 678.8 144
+678.8 DL 152 678.8 148 678.8 DL 156 678.8 152 678.8 DL 160 678.8 156 678.8 DL
+164 678.8 160 678.8 DL 168 678.8 164 678.8 DL 172 678.8 168 678.8 DL 176 678.8
+172 678.8 DL 180 678.8 176 678.8 DL 184 678.8 180 678.8 DL 188 678.8 184 678.8
+DL 192 678.8 188 678.8 DL 196 678.8 192 678.8 DL 200 678.8 196 678.8 DL 204
+678.8 200 678.8 DL 208 678.8 204 678.8 DL 212 678.8 208 678.8 DL 216 678.8 212
+678.8 DL/F3 5/Times-Roman@0 SF(6)93.6 689.2 Q/F4 8/Times-Roman@0 SF .343
+(This v)3.2 J .343(eri\214cation includes looking up e)-.12 F -.12(ve)-.2 G
+.344(ry address with the name serv).12 F .344(er; this in)-.12 F -.16(vo)-.32 G
+(lv).16 E .344(es netw)-.12 F .344(ork delays, and can in some cases)-.08 F
+(can be considerable.)72 702 Q EP
+%%Page: 19 16
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-19)452.9 60 Q/F1 10/Times-Roman@0 SF .894(The recipient and class f)127
+96 R .895(actors can be set in the con\214guration \214le using the)-.1 F F0(y)
+3.395 E F1(and)3.395 E F0(z)3.395 E F1(options)3.395 E(respecti)102 108 Q -.15
+(ve)-.25 G(ly).15 E 5.963(.T)-.65 G(he)163.843 108 Q 3.463(yd)-.15 G(ef)186.596
+108 Q .963(ault to 30000 \(for the recipient f)-.1 F .962
+(actor\) and 1800 \(for the class f)-.1 F 3.462(actor\). The)-.1 F
+(initial priority is:)102 120 Q/F2 10/Times-Italic@0 SF(pri)251.936 138 Q/F3 10
+/Symbol SF(=)1.666 E F1(\()A F2(class)A F3<b4>1.666 E F0(z\))A F3(+)A F1(\()A
+F2(nr)A(cpt)-.37 E F3<b4>1.666 E F0(y\))A F1(\(Remember)102 156 Q 3.328(,h)-.4
+G .828(igher v)159.638 156 R .828
+(alues for this parameter actually mean that the job will be treated with lo)
+-.25 F(wer)-.25 E(priority)102 168 Q(.\))-.65 E 1.519(The priority of a job ca\
+n also be adjusted each time it is processed \(that is, each time an)127 184.2
+R .256(attempt is made to deli)102 196.2 R -.15(ve)-.25 G 2.756(ri).15 G .256
+(t\) using the \231w)212.04 196.2 R .256(ork time f)-.1 F(actor)-.1 E 1.656 -.7
+(,\232 s)-.4 H .256(et by the).7 F F0(Z)2.756 E F1 2.756(option. This)2.756 F
+.256(is added to the)2.756 F(priority)102 208.2 Q 2.703(,s)-.65 G 2.703(oi)
+140.443 208.2 S 2.703(tn)150.926 208.2 S .203
+(ormally decreases the precedence of the job, on the grounds that jobs that ha)
+161.409 208.2 R .502 -.15(ve f)-.2 H(ailed).05 E(man)102 220.2 Q 2.5(yt)-.15 G
+(imes will tend to f)129.35 220.2 Q(ail ag)-.1 E(ain in the future.)-.05 E(The)
+5 E F0(Z)2.5 E F1(option def)2.5 E(aults to 90000.)-.1 E F0 2.5(4.4. Load)87
+244.2 R(Limiting)2.5 E F2(Sendmail)127 260.4 Q F1 .101(can be ask)2.601 F .101
+(ed to queue \(b)-.1 F .101(ut not deli)-.2 F -.15(ve)-.25 G .101
+(r\) mail if the system load a).15 F -.15(ve)-.2 G .102(rage gets too high).15
+F .627(using the)102 272.4 R F0(x)3.127 E F1 3.126(option. When)3.126 F .626
+(the load a)3.126 F -.15(ve)-.2 G .626(rage e).15 F .626(xceeds the v)-.15 F
+.626(alue of the)-.25 F F0(x)3.126 E F1 .626(option, the deli)3.126 F -.15(ve)
+-.25 G .626(ry mode is).15 F .986(set to)102 284.4 R F0(q)3.486 E F1 .986
+(\(queue only\) if the)3.486 F F2 .987(Queue F)3.487 F(actor)-.75 E F1(\()3.487
+E F0(q)A F1 .987(option\) di)3.487 F .987(vided by the dif)-.25 F .987
+(ference in the current load)-.25 F -2.25 -.2(av e)102 296.4 T 1.269
+(rage and the).2 F F0(x)3.769 E F1 1.269(option plus one e)3.769 F 1.269
+(xceeds the priority of the message \212 that is, the message is)-.15 F
+(queued if)102 308.4 Q(f:)-.25 E F2(pri)273.854 326.431 Q F1(>)1.666 E F2(LA)
+2.5 .057 M F3(-)1.666 E F0(x)A F3(+)A F1(1)A .4 LW 298.83 326.408 293.83
+326.408 DL 301.146 326.408 296.146 326.408 DL 306.146 326.408 301.146 326.408
+DL 311.146 326.408 306.146 326.408 DL 316.146 326.408 311.146 326.408 DL
+321.146 326.408 316.146 326.408 DL 326.146 326.408 321.146 326.408 DL 331.146
+326.408 326.146 326.408 DL F0(q)309.708 326.385 Q F1(The)102 344.472 Q F0(q)
+3.142 E F1 .642(option def)3.142 F .642
+(aults to 200000, so each point of load a)-.1 F -.15(ve)-.2 G .643(rage is w)
+.15 F .643(orth 200000 priority points \(as)-.1 F(described abo)102 356.472 Q
+-.15(ve)-.15 G(\).).15 E -.15(Fo)127 372.672 S 2.887(rd).15 G .387
+(rastic cases, the)148.627 372.672 R F0(X)2.887 E F1 .387
+(option de\214nes a load a)2.887 F -.15(ve)-.2 G .387
+(rage at which sendmail will refuse to accept).15 F(netw)102 384.672 Q
+(ork connections.)-.1 E
+(Locally generated mail \(including incoming UUCP mail\) is still accepted.)5 E
+F0 2.5(4.5. Deli)87 408.672 R -.1(ve)-.1 G(ry Mode).1 E F1 .416
+(There are a number of deli)127 424.872 R -.15(ve)-.25 G .416(ry modes that).15
+F F2(sendmail)2.916 E F1 .417
+(can operate in, set by the \231d\232 con\214gura-)2.916 F(tion option.)102
+436.872 Q(These modes specify ho)5 E 2.5(wq)-.25 G(uickly mail will be deli)
+263.96 436.872 Q -.15(ve)-.25 G 2.5(red. Le).15 F -.05(ga)-.15 G 2.5(lm).05 G
+(odes are:)418.9 436.872 Q 17.22(id)142 453.072 S(eli)167 453.072 Q -.15(ve)
+-.25 G 2.5(ri).15 G(nteracti)194.65 453.072 Q -.15(ve)-.25 G
+(ly \(synchronously\)).15 E 15(bd)142 465.072 S(eli)167 465.072 Q -.15(ve)-.25
+G 2.5(ri).15 G 2.5(nb)194.65 465.072 S(ackground \(asynchronously\))207.15
+465.072 Q 15(qq)142 477.072 S(ueue only \(don')167 477.072 Q 2.5(td)-.18 G(eli)
+240.42 477.072 Q -.15(ve)-.25 G(r\)).15 E 1.491(There are tradeof)102 493.272 R
+3.991(fs. Mode)-.25 F 1.491
+(\231i\232 passes the maximum amount of information to the sender)3.991 F 3.99
+(,b)-.4 G 1.49(ut is)485.56 493.272 R .432(hardly e)102 505.272 R -.15(ve)-.25
+G 2.932(rn).15 G(ecessary)155.224 505.272 Q 5.432(.M)-.65 G .433
+(ode \231q\232 puts the minimum load on your machine, b)205.266 505.272 R .433
+(ut means that deli)-.2 F -.15(ve)-.25 G(ry).15 E .437
+(may be delayed for up to the queue interv)102 517.272 R 2.937(al. Mode)-.25 F
+.437(\231b\232 is probably a good compromise.)2.937 F(Ho)5.436 E(we)-.25 E -.15
+(ve)-.25 G -.4(r,).15 G .032(this mode can cause lar)102 529.272 R .032
+(ge numbers of processes if you ha)-.18 F .332 -.15(ve a m)-.2 H .032
+(ailer that tak).15 F .032(es a long time to deli)-.1 F -.15(ve)-.25 G(r).15 E
+2.5(am)102 541.272 S(essage.)116.72 541.272 Q 1.208
+(If you run in mode \231q\232 \(queue only\))127 557.472 R F2(sendmail)3.708 E
+F1 1.208(will not e)3.708 F 1.208(xpand aliases and follo)-.15 F 3.708(w.)-.25
+G(forw)472.45 557.472 Q(ard)-.1 E(\214les upon initial receipt of the mail.)102
+569.472 Q(This speeds up the response to RCPT commands.)5 E F0 2.5(4.6. Log)87
+593.472 R(Le)2.5 E -.1(ve)-.15 G(l).1 E F1 .189(The le)127 609.672 R -.15(ve)
+-.25 G 2.689(lo).15 G 2.689(fl)171.968 609.672 S .189
+(ogging can be set for sendmail.)180.767 609.672 R .189(The def)5.189 F .19
+(ault using a standard con\214guration table)-.1 F(is le)102 621.672 Q -.15(ve)
+-.25 G 2.5(l9).15 G 5(.T)137.71 621.672 S(he le)151.32 621.672 Q -.15(ve)-.25 G
+(ls are as follo).15 E(ws:)-.25 E 31(0N)102 637.872 S 2.5(ol)145.22 637.872 S
+(ogging.)155.5 637.872 Q 31(1S)102 654.072 S(erious system f)143.56 654.072 Q
+(ailures and potential security problems.)-.1 E 31(2L)102 670.272 S
+(ost communications \(netw)144.11 670.272 Q(ork problems\) and protocol f)-.1 E
+(ailures.)-.1 E 31(3O)102 686.472 S(ther serious f)145.22 686.472 Q(ailures.)
+-.1 E 31(4M)102 702.672 S(inor f)146.89 702.672 Q(ailures.)-.1 E EP
+%%Page: 20 17
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-20 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 31(5M)102 96 S
+(essage collection statistics.)146.89 96 Q 31(6C)102 112.2 S
+(reation of error messages, VRFY and EXPN commands.)144.67 112.2 Q 31(7D)102
+128.4 S(eli)145.22 128.4 Q -.15(ve)-.25 G(ry f).15 E
+(ailures \(host or user unkno)-.1 E(wn, etc.\).)-.25 E 31(8S)102 144.6 S
+(uccessful deli)143.56 144.6 Q -.15(ve)-.25 G(ries.).15 E 31(9M)102 160.8 S
+(essages being deferred \(due to a host being do)146.89 160.8 Q(wn, etc.\).)
+-.25 E 23.5(10 Database)102 177 R -.15(ex)2.5 G(pansion \(alias, forw).15 E
+(ard, and userdb lookups\).)-.1 E 23.5(15 Automatic)102 193.2 R
+(alias database reb)2.5 E(uilds.)-.2 E 23.5(20 Logs)102 209.4 R .603
+(attempts to run lock)3.103 F .603(ed queue \214les.)-.1 F .603
+(These are not errors, b)5.603 F .603(ut can be useful to note if)-.2 F
+(your queue appears to be clogged.)138 221.4 Q 23.5(30 Lost)102 237.6 R
+(locks \(only if using lockf instead of \215ock\).)2.5 E(Additionally)102 253.8
+Q 3.683(,v)-.65 G 1.183(alues abo)162.843 253.8 R 1.483 -.15(ve 6)-.15 H 3.683
+(4a).15 G 1.183(re reserv)232.462 253.8 R 1.183(ed for e)-.15 F 1.183
+(xtremely v)-.15 F 1.184(erbose deb)-.15 F 1.184(uggging output.)-.2 F 1.184
+(No normal)6.184 F(site w)102 265.8 Q(ould e)-.1 E -.15(ve)-.25 G 2.5(rs).15 G
+(et these.)168.99 265.8 Q F0 2.5(4.7. File)87 289.8 R(Modes)2.5 E F1 .813
+(There are a number of \214les that may ha)127 306 R 1.113 -.15(ve a n)-.2 H
+.813(umber of modes.).15 F .813(The modes depend on what)5.813 F
+(functionality you w)102 318 Q(ant and the le)-.1 E -.15(ve)-.25 G 2.5(lo).15 G
+2.5(fs)253.15 318 S(ecurity you require.)262.87 318 Q F0 2.5(4.7.1. T)102 342 R
+2.5(os)-.92 G(uid or not to suid?)146.64 342 Q/F2 10/Times-Italic@0 SF
+(Sendmail)142 358.2 Q F1 .933(can safely be made setuid to root.)3.433 F .934
+(At the point where it is about to)5.934 F F2 -.2(ex)3.434 G(ec).2 E F1 .934
+(\(2\) a)1.666 F(mailer)117 370.2 Q 2.583(,i)-.4 G 2.583(tc)150.013 370.2 S
+.082(hecks to see if the userid is zero; if so, it resets the userid and group\
+id to a def)159.816 370.2 R .082(ault \(set)-.1 F .576(by the)117 382.2 R F0(u)
+3.076 E F1(and)3.076 E F0(g)3.076 E F1 3.076(options\). \(This)3.076 F .576
+(can be o)3.076 F -.15(ve)-.15 G .576(rridden by setting the).15 F F0(S)3.076 E
+F1 .577(\215ag to the mailer for mailers)3.077 F 1.532
+(that are trusted and must be called as root.\))117 394.2 R(Ho)6.531 E(we)-.25
+E -.15(ve)-.25 G 2.331 -.4(r, t).15 H 1.531
+(his will cause mail processing to be).4 F(accounted \(using)117 406.2 Q F2(sa)
+2.5 E F1(\(8\)\) to root rather than to the user sending the mail.)1.666 E F0
+2.5(4.7.2. Should)102 430.2 R(my alias database be writable?)2.5 E F1 .058
+(At Berk)142 446.4 R(ele)-.1 E 2.558(yw)-.15 G 2.558(eh)200.186 446.4 S -2.25
+-.2(av e)212.184 446.4 T .058(the alias database \(/etc/aliases*\) mode 644.)
+2.758 F .058(While this is not as \215e)5.058 F(x-)-.15 E 1.719
+(ible as if the database were more 666, it a)117 458.4 R -.2(vo)-.2 G 1.718
+(ids potential security problems with a globally).2 F(writable database.)117
+470.4 Q 1.19(The database that)142 486.6 R F2(sendmail)3.69 E F1 1.191
+(actually used is represented by the tw)3.691 F 3.691<6f8c>-.1 G(les)429.118
+486.6 Q F2(aliases.dir)3.691 E F1(and)3.691 E F2(aliases.pa)117 498.6 Q(g)-.1 E
+F1 .159(\(both in /etc\) \(or)2.659 F F2(aliases.db)2.659 E F1 .159
+(if you are running with the ne)2.659 F 2.658(wB)-.25 G(erk)412.854 498.6 Q
+(ele)-.1 E 2.658(yd)-.15 G .158(atabase prim-)449.692 498.6 R(iti)117 510.6 Q
+-.15(ve)-.25 G 3.606(s\). The).15 F 1.107
+(mode on these \214les should match the mode on /etc/aliases.)3.606 F(If)6.107
+E F2(aliases)3.607 E F1 1.107(is writable)3.607 F 1.624(and the DBM \214les \()
+117 522.6 R F2(aliases.dir)A F1(and)4.124 E F2(aliases.pa)4.124 E(g)-.1 E F1
+4.124(\)a)C 1.624(re not, users will be unable to re\215ect their)324.648 522.6
+R .719(desired changes through to the actual database.)117 534.6 R(Ho)5.719 E
+(we)-.25 E -.15(ve)-.25 G 1.519 -.4(r, i).15 H(f).4 E F2(aliases)3.219 E F1 .72
+(is read-only and the DBM)3.219 F(\214les are writable, a slightly sophisticat\
+ed user can arrange to steal mail an)117 546.6 Q(yw)-.15 E(ay)-.1 E(.)-.65 E
+.621(If your DBM \214les are not writable by the w)142 562.8 R .62
+(orld or you do not ha)-.1 F .92 -.15(ve a)-.2 H(uto-reb).15 E .62
+(uild enabled)-.2 F .564(\(with the \231D\232 option\), then you must be caref\
+ul to reconstruct the alias database each time you)117 574.8 R(change the te)
+117 586.8 Q(xt v)-.15 E(ersion:)-.15 E(ne)157 603 Q -.1(wa)-.25 G(liases).1 E
+(If this step is ignored or for)117 619.2 Q(gotten an)-.18 E 2.5(yi)-.15 G
+(ntended changes will also be ignored or for)273.32 619.2 Q(gotten.)-.18 E F0
+2.5(4.8. Connection)87 643.2 R(Caching)2.5 E F1 .494
+(When processing the queue,)127 659.4 R F0(sendmail)2.994 E F1 .493
+(will try to k)2.994 F .493(eep the last fe)-.1 F 2.993(wo)-.25 G .493
+(pen connections open to)405.591 659.4 R -.2(avo)102 671.4 S
+(id startup and shutdo).2 E(wn costs.)-.25 E
+(This only applies to IPC connections.)5 E .286
+(When trying to open a connection the cache is \214rst searched.)127 687.6 R
+.287(If an open connection is found,)5.286 F .92
+(it is probed to see if it is still acti)102 699.6 R 1.22 -.15(ve b)-.25 H 3.42
+(ys).15 G .92(ending a)270.892 699.6 R/F3 9/Times-Roman@0 SF(NOOP)3.42 E F1
+3.42(command. It)3.42 F .92(is not an error if this f)3.42 F(ails;)-.1 E
+(instead, the connection is closed and reopened.)102 711.6 Q EP
+%%Page: 21 18
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-21)452.9 60 Q/F1 10/Times-Roman@0 SF -1 -.8(Tw o)127 96 T .207
+(parameters control the connection cache.)3.506 F(The)5.207 E F0(k)2.707 E F1
+.207(option de\214nes the number of simultane-)2.707 F 1.82
+(ous open connections that will be permitted.)102 108 R 1.819
+(If it is set to zero, connections will be closed as)6.82 F .795
+(quickly as possible.)102 120 R .796(The def)5.796 F .796(ault is one.)-.1 F
+.796(This should be set as appropriate for your system size; it)5.796 F
+(will limit the amount of system resources that)102 132 Q F0(sendmail)2.5 E F1
+(will use during queue runs.)2.5 E(The)127 148.2 Q F0(K)3.648 E F1 1.148
+(option speci\214es the maximum time that an)3.648 F 3.648(yc)-.15 G 1.148
+(ached connection will be permitted to)347.452 148.2 R 2.895(idle. When)102
+160.2 R .395(the idle time e)2.895 F .395(xceeds this v)-.15 F .396
+(alue the connection is closed.)-.25 F .396(This number should be small)5.396 F
+.163(\(under ten minutes\) to pre)102 172.2 R -.15(ve)-.25 G .163
+(nt you from grabbing too man).15 F 2.663(yr)-.15 G .162
+(esources from other hosts.)347.49 172.2 R .162(The def)5.162 F(ault)-.1 E
+(is \214v)102 184.2 Q 2.5(em)-.15 G(inutes.)136.3 184.2 Q F0 2.5(4.9. Name)87
+208.2 R(Ser)2.5 E -.1(ve)-.1 G 2.5(rA).1 G(ccess)172.33 208.2 Q F1 .421
+(If your system supports the name serv)127 224.4 R(er)-.15 E 2.921(,t)-.4 G
+.421(hen the probability is that)297.147 224.4 R/F2 10/Times-Italic@0 SF
+(sendmail)2.921 E F1 .422(will be using it)2.922 F(re)102 236.4 Q -.05(ga)-.15
+G .154(rdless of ho).05 F 2.654(wy)-.25 G .154(ou con\214gure sendmail.)180.602
+236.4 R(Ho)5.154 E(we)-.25 E -.15(ve)-.25 G .954 -.4(r, i).15 H 2.654(fy).4 G
+.153(ou ha)331.962 236.4 R .453 -.15(ve n)-.2 H(ameserv).15 E .153
+(er support which you are)-.15 F .979(not using, sendmail will get a \231conne\
+ction refused\232 message when it tries to connect to the name)102 248.4 R
+(serv)102 260.4 Q .592(er \(either by calling)-.15 F F2 -.1(ge)3.091 G
+(thostbyname).1 E F1 .591(or by trying to look up the MX records\).)3.091 F
+.591(If the)5.591 F F0(I)3.091 E F1 .591(option is)3.091 F(set,)102 272.4 Q F2
+(sendmail)3.339 E F1 .839(will interpret this to mean a temporary f)3.339 F .84
+(ailure; otherwise, it ignores the name serv)-.1 F(er)-.15 E 2.59(data. If)102
+284.4 R .09(your name serv)2.59 F .09(er is running properly)-.15 F 2.59(,t)
+-.65 G .09(he setting of this option is not rele)291.6 284.4 R -.25(va)-.25 G
+.09(nt; ho).25 F(we)-.25 E -.15(ve)-.25 G .89 -.4(r, i).15 H 2.59(ti).4 G(s)
+500.11 284.4 Q(important that it be set properly to mak)102 296.4 Q 2.5(ee)-.1
+G(rror handling w)269.66 296.4 Q(ork properly)-.1 E(.)-.65 E .632
+(This option also allo)127 312.6 R .633(ws you to tweak name serv)-.25 F .633
+(er options.)-.15 F .633(The command line tak)5.633 F .633(es a series)-.1 F
+.442(of \215ags as documented in)102 324.6 R F2 -.37(re)2.942 G(solver).37 E F1
+.442(\(3\) \(with the leading \231RES_\232 deleted\).)B .442
+(Each can be preceded by)5.442 F(an optional `+' or `)102 336.6 Q/F3 10/Symbol
+SF(-)A F1 2.5('. F)B(or e)-.15 E(xample, the line)-.15 E(OIT)142 352.8 Q
+(rue +AA)-.35 E(ONL)-.55 E(Y)-1 E F3(-)2.5 E F1(DNSRCH)A .861(turns on the AA)
+102 369 R(ONL)-.55 E 3.361(Y\()-1 G .861(accept authoritati)201.654 369 R 1.161
+-.15(ve a)-.25 H .861(nswers only\) and turns of).15 F 3.362(ft)-.25 G .862
+(he DNSRCH \(search the)402.824 369 R 2.039(domain path\) options.)102 381 R
+2.039(Most resolv)7.039 F 2.039(er libraries def)-.15 F 2.039
+(ault DNSRCH, DEFN)-.1 F 2.039(AMES, and RECURSE)-.35 F .186
+(\215ags on and all others of)102 393 R 2.686(f. Note)-.25 F .186
+(the use of the initial `)2.686 F(`T)-.74 E(rue')-.35 E -5.185 2.686('\212 t)
+-.74 H .187(his is for compatibility with pre)365.815 393 R(vi-)-.25 E(ous v)
+102 405 Q(ersions of sendmail, b)-.15 E(ut is not otherwise necessary)-.2 E(.)
+-.65 E -1.11(Ve)127 421.2 S 2.257(rsion le)1.11 F -.15(ve)-.25 G 4.757(l1c).15
+G 2.256(on\214gurations turn DNSRCH and DEFN)200.301 421.2 R 2.256(AMES of)-.35
+F 4.756(fw)-.25 G 2.256(hen doing deli)424.898 421.2 R -.15(ve)-.25 G(ry).15 E
+2.06(lookups, b)102 433.2 R 2.06(ut lea)-.2 F 2.36 -.15(ve t)-.2 H 2.06
+(hem on e).15 F -.15(ve)-.25 G 2.06(rywhere else.).15 F -1.11(Ve)7.06 G 2.06
+(rsion 6 of)1.11 F F2(sendmail)4.56 E F1 2.06(ignores them when doing)4.56 F
+.313(canoni\214cation lookups \(that is, when using $[ ... $]\), and al)102
+445.2 R -.1(wa)-.1 G .313(ys does the search.).1 F .313(If you don')5.313 F
+2.812(tw)-.18 G(ant)491.78 445.2 Q(to do automatic name e)102 457.2 Q
+(xtension, don')-.15 E 2.5(tc)-.18 G(all $[ ... $].)261.93 457.2 Q .189
+(The search rules for $[ ... $] are some)127 473.4 R .189(what dif)-.25 F .189
+(ferent than usual.)-.25 F .189(If the name \(that is, the `)5.189 F(`...)-.74
+E -.74('')-.7 G(\)).74 E .11(has at least one dot, it al)102 485.4 R -.1(wa)-.1
+G .11(ys tries the unmodi\214ed name \214rst.).1 F .109(If that f)5.109 F .109
+(ails, it tries the reduced search)-.1 F .124
+(path, and lastly tries the unmodi\214ed name \(b)102 497.4 R .124
+(ut only for names without a dot, since names with a dot)-.2 F(ha)102 509.4 Q
+.789 -.15(ve a)-.2 H .489(lready been tried\).).15 F .489(This allo)5.489 F
+.489(ws names such as `)-.25 F(`utc.CS')-.74 E 2.989('t)-.74 G 2.988(om)362.81
+509.4 S .488(atch the site in Czechoslo)378.578 509.4 R -.25(va)-.15 G(kia).25
+E 1.587(rather than the site in your local Computer Science department.)102
+521.4 R 1.588(It also prefers A and CN)6.587 F(AME)-.35 E .513(records o)102
+533.4 R -.15(ve)-.15 G 3.013(rM).15 G 3.013(Xr)163.816 533.4 S .513
+(ecords \212 that is, if it \214nds an MX record it mak)177.379 533.4 R .512
+(es note of it, b)-.1 F .512(ut k)-.2 F .512(eeps looking.)-.1 F 1.541(This w)
+102 545.4 R(ay)-.1 E 4.041(,i)-.65 G 4.041(fy)149.052 545.4 S 1.541(ou ha)
+161.423 545.4 R 1.841 -.15(ve a w)-.2 H 1.541
+(ildcard MX record matching your domain, it will not assume that all).15 F
+(names match.)102 557.4 Q F0 2.5(4.10. Mo)87 581.4 R(ving the P)-.1 E(er)-.2 E
+(-User F)-.37 E(orward Files)-.25 E F1 .772(Some sites mount each user')127
+597.6 R 3.272(sh)-.55 G .772(ome directory from a local disk on their w)256.13
+597.6 R .772(orkstation, so that)-.1 F .575(local access is f)102 609.6 R 3.075
+(ast. Ho)-.1 F(we)-.25 E -.15(ve)-.25 G 1.375 -.4(r, t).15 H .575
+(he result is that .forw).4 F .575(ard \214le lookups are slo)-.1 F 4.376 -.65
+(w. I)-.25 H 3.076(ns).65 G .576(ome cases, mail)439.248 609.6 R .216(can e)102
+621.6 R -.15(ve)-.25 G 2.716(nb).15 G 2.716(ed)144.792 621.6 S(eli)156.948
+621.6 Q -.15(ve)-.25 G .216
+(red on machines inappropriately because of a \214le serv).15 F .216
+(er being do)-.15 F 2.716(wn. The)-.25 F(perfor)2.716 E(-)-.2 E
+(mance can be especially bad if you run the automounter)102 633.6 Q(.)-.55 E
+(The)127 649.8 Q F0(J)2.5 E F1(option allo)2.5 E(ws you to set a path of forw)
+-.25 E(ard \214les.)-.1 E -.15(Fo)5 G 2.5(re).15 G
+(xample, the con\214g \214le line)366.6 649.8 Q(OJ/v)142 666 Q(ar/forw)-.25 E
+(ard/$u:$z/.forw)-.1 E(ard)-.1 E -.1(wo)102 682.2 S .207
+(uld \214rst look for a \214le with the same name as the user').1 F 2.708(sl)
+-.55 G .208(ogin in /v)343.184 682.2 R(ar/forw)-.25 E .208
+(ard; if that is not found)-.1 F .13
+(\(or is inaccessible\) the \214le \231.forw)102 694.2 R .129
+(ard\232 in the user')-.1 F 2.629(sh)-.55 G .129(ome directory is searched.)
+311.907 694.2 R 2.629(At)5.129 G .129(ruly perv)435.022 694.2 R .129(erse site)
+-.15 F(could also search by sender by using $r)102 706.2 Q 2.5(,$)-.4 G
+(s, or $f.)269.07 706.2 Q EP
+%%Page: 22 19
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-22 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF .69
+(If you create a directory such as /v)127 96 R(ar/forw)-.25 E .69
+(ard, it should be mode 1777 \(that is, the stick)-.1 F 3.19(yb)-.15 G(it)
+498.44 96 Q(should be set\).)102 108 Q
+(Users should create the \214les mode 644.)5 E F0 2.5(4.11. Fr)87 132 R
+(ee Space)-.18 E F1 1.123(On systems that ha)127 148.2 R 1.423 -.15(ve t)-.2 H
+(he).15 E/F2 10/Times-Italic@0 SF(statfs)3.623 E F1 1.123
+(\(2\) system call, you can specify a minimum number of free)B .61
+(blocks on the queue \214lesystem using the)102 160.2 R F0(b)3.11 E F1 3.11
+(option. If)3.11 F .61(there are fe)3.11 F .61
+(wer than the indicated number of)-.25 F .407
+(blocks free on the \214lesystem on which the queue is mounted the SMTP serv)
+102 172.2 R .406(er will reject mail with)-.15 F(the 452 error code.)102 184.2
+Q(This in)5 E(vites the SMTP client to try ag)-.4 E(ain later)-.05 E(.)-.55 E
+(Be)127 200.4 Q -.1(wa)-.25 G .746(re of setting this option too high; it can \
+cause rejection of email when that mail w).1 F(ould)-.1 E
+(be processed without dif)102 212.4 Q(\214culty)-.25 E(.)-.65 E 1.773
+(This option can also specify an adv)127 228.6 R 1.772
+(ertised \231maximum message size\232 for hosts that speak)-.15 F(ESMTP)102
+240.6 Q(.)-1.11 E F0 2.5(4.12. Pri)87 264.6 R -.1(va)-.1 G(cy Flags).1 E F1
+(The)127 280.8 Q F0(p)3.59 E F1 1.09(option allo)3.59 F 1.091
+(ws you to set certain `)-.25 F(`pri)-.74 E -.25(va)-.25 G -.15(cy).25 G 2.571
+-.74('' \215).15 H 3.591(ags. Actually).74 F 3.591(,m)-.65 G(an)409.266 280.8 Q
+3.591(yo)-.15 G 3.591(ft)432.147 280.8 S 1.091(hem don')441.848 280.8 R 3.591
+(tg)-.18 G -2.15 -.25(iv e)492.18 280.8 T .254(you an)102 292.8 R 2.754(ye)-.15
+G .254(xtra pri)141.088 292.8 R -.25(va)-.25 G -.15(cy).25 G 2.754(,r)-.5 G
+.254(ather just insisting that client SMTP serv)196.666 292.8 R .254
+(ers use the HELO command before)-.15 F(using certain commands.)102 304.8 Q
+.123(The option tak)127 321 R .124
+(es a series of \215ag names; the \214nal pri)-.1 F -.25(va)-.25 G .424 -.15
+(cy i).25 H 2.624(st).15 G .124(he inclusi)367.706 321 R .424 -.15(ve o)-.25 H
+2.624(ro).15 G 2.624(ft)434.058 321 S .124(hose \215ags.)442.792 321 R -.15(Fo)
+5.124 G(r).15 E -.15(ex)102 333 S(ample:).15 E(Op needmailhelo, noe)142 349.2 Q
+(xpn)-.15 E .928(insists that the HELO or EHLO command be used before a MAIL c\
+ommand is accepted and dis-)102 365.4 R(ables the EXPN command.)102 377.4 Q
+.244(The \231restrictmailq\232 option restricts printing the queue to the grou\
+p that o)127 393.6 R .245(wns the queue direc-)-.25 F(tory)102 405.6 Q 5(.I)
+-.65 G 2.5(ti)128.29 405.6 S 2.5(sa)136.35 405.6 S
+(bsurd to set this if you don')147.18 405.6 Q 2.5(ta)-.18 G
+(lso protect the logs.)266.72 405.6 Q F0 2.5(4.13. Send)87 429.6 R(to Me T)2.5
+E(oo)-.92 E F1(Normally)127 445.8 Q(,)-.65 E F2(sendmail)3.424 E F1 .924
+(deletes the \(en)3.424 F -.15(ve)-.4 G .923(lope\) sender from an).15 F 3.423
+(yl)-.15 G .923(ist e)375.488 445.8 R 3.423(xpansions. F)-.15 F .923(or e)-.15
+F .923(xample, if)-.15 F .761(\231matt\232 sends to a list that contains \231m\
+att\232 as one of the members he w)102 457.8 R(on')-.1 E 3.261(tg)-.18 G .761
+(et a cop)416.705 457.8 R 3.261(yo)-.1 G 3.261(ft)462.488 457.8 S .761(he mes-)
+471.859 457.8 R 3.067(sage. If)102 469.8 R(the)3.067 E F0<ad6d>3.067 E F1 .567
+(\(me too\) command line \215ag, or if the)3.067 F F0(m)3.066 E F1 .566
+(option is set in the con\214guration \214le, this)3.066 F(beha)102 481.8 Q
+(viour is supressed.)-.2 E(Some sites lik)5 E 2.5(et)-.1 G 2.5(or)265.58 481.8
+S(un the)276.41 481.8 Q/F3 9/Times-Roman@0 SF(SMTP)2.5 E F1(daemon with)2.5 E
+F0<ad6d>2.5 E F1(.)A F0 2.5(5. THE)72 505.8 R(WHOLE SCOOP ON THE CONFIGURA)2.5
+E(TION FILE)-.95 E F1 .264(This section describes the con\214guration \214le i\
+n detail, including hints on ho)112 522 R 2.764(wt)-.25 G 2.764(ow)426.294 522
+S .264(rite one of your)441.278 522 R -.25(ow)87 534 S 2.5(ni).25 G 2.5(fy)
+109.25 534 S(ou ha)120.08 534 Q .3 -.15(ve t)-.2 H(o.).15 E .648(There is one \
+point that should be made clear immediately: the syntax of the con\214guration\
+ \214le is)112 550.2 R 1.076
+(designed to be reasonably easy to parse, since this is done e)87 562.2 R -.15
+(ve)-.25 G 1.077(ry time).15 F F2(sendmail)3.577 E F1 1.077
+(starts up, rather than)3.577 F(easy for a human to read or write.)87 574.2 Q
+(On the \231future project\232 list is a con\214guration-\214le compiler)5 E(.)
+-.55 E(An o)112 590.4 Q -.15(ve)-.15 G(rvie).15 E 2.5(wo)-.25 G 2.5(ft)170.88
+590.4 S(he con\214guration \214le is gi)179.49 590.4 Q -.15(ve)-.25 G 2.5<6e8c>
+.15 G(rst, follo)301.59 590.4 Q(wed by details of the semantics.)-.25 E F0 2.5
+(5.1. Con\214guration)87 614.4 R(File Lines)2.5 E F1 1.316
+(The con\214guration \214le is or)127 630.6 R -.05(ga)-.18 G 1.316
+(nized as a series of lines, each of which be).05 F 1.315(gins with a single)
+-.15 F .741(character de\214ning the semantics for the rest of the line.)102
+642.6 R .742(Lines be)5.742 F .742(ginning with a space or a tab are)-.15 F
+1.149
+(continuation lines \(although the semantics are not well de\214ned in man)102
+654.6 R 3.648(yp)-.15 G 3.648(laces\). Blank)407.516 654.6 R 1.148(lines and)
+3.648 F(lines be)102 666.6 Q(ginning with a sharp symbol \(`#'\) are comments.)
+-.15 E F0 2.5(5.1.1. R)102 690.6 R(and S \212 r)2.5 E(ewriting rules)-.18 E F1
+.406(The core of address parsing are the re)142 706.8 R .406(writing rules.)
+-.25 F .407(These are an ordered production sys-)5.407 F(tem.)117 718.8 Q F2
+(Sendmail)5.283 E F1 .283(scans through the set of re)2.783 F .282
+(writing rules looking for a match on the left hand side)-.25 F EP
+%%Page: 23 20
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-23)452.9 60 Q/F1 10/Times-Roman@0 SF .131(\(LHS\) of the rule.)117 96 R
+.131(When a rule matches, the address is replaced by the right hand side \(RHS\
+\) of)5.131 F(the rule.)117 108 Q 1.126(There are se)142 124.2 R -.15(ve)-.25 G
+1.126(ral sets of re).15 F 1.126(writing rules.)-.25 F 1.126(Some of the re)
+6.126 F 1.125(writing sets are used internally)-.25 F .21(and must ha)117 136.2
+R .51 -.15(ve s)-.2 H .21(peci\214c semantics.).15 F .21(Other re)5.21 F .21
+(writing sets do not ha)-.25 F .51 -.15(ve s)-.2 H .21
+(peci\214cally assigned seman-).15 F
+(tics, and may be referenced by the mailer de\214nitions or by other re)117
+148.2 Q(writing sets.)-.25 E(The syntax of these tw)142 164.4 Q 2.5(oc)-.1 G
+(ommands are:)244.38 164.4 Q F0(S)157 180.6 Q/F2 10/Times-Italic@0 SF(n)A F1
+.278(Sets the current ruleset being collected to)117 196.8 R F2(n)2.778 E F1
+5.278(.I)C 2.778(fy)302.524 196.8 S .278(ou be)313.632 196.8 R .278
+(gin a ruleset more than once it deletes the)-.15 F(old de\214nition.)117 208.8
+Q F0(R)157 225 Q F2(lhs rhs comments)A F1 .303(The \214elds must be separated \
+by at least one tab character; there may be embedded spaces in the)117 241.2 R
+2.739(\214elds. The)117 253.2 R F2(lhs)2.739 E F1 .239
+(is a pattern that is applied to the input.)2.739 F .238
+(If it matches, the input is re)5.238 F .238(written to the)-.25 F F2(rhs)117
+265.2 Q F1 5(.T)C(he)143.39 265.2 Q F2(comments)2.5 E F1(are ignored.)2.5 E
+2.265(Macro e)142 281.4 R 2.265(xpansions of the form)-.15 F F0($)4.765 E F2(x)
+A F1 2.266(are performed when the con\214guration \214le is read.)4.765 F .081
+(Expansions of the form)117 293.4 R F0($&)2.581 E F2(x)A F1 .081
+(are performed at run time using a some)2.581 F .08
+(what less general algorithm.)-.25 F .639
+(This for is intended only for referencing internally de\214ned macros such as)
+117 305.4 R F0($h)3.139 E F1 .639(that are changed)3.139 F(at runtime.)117
+317.4 Q F0 2.5(5.1.1.1. The)117 341.4 R(left hand side)2.5 E F1 1.617
+(The left hand side of re)157 357.6 R 1.617(writing rules contains a pattern.)
+-.25 F 1.617(Normal w)6.617 F 1.617(ords are simply)-.1 F(matched directly)132
+369.6 Q 5(.M)-.65 G(etasyntax is introduced using a dollar sign.)214.67 369.6 Q
+(The metasymbols are:)5 E F0($*)172 385.8 Q F1(Match zero or more tok)192.14
+385.8 Q(ens)-.1 E F0($+)172 397.8 Q F1(Match one or more tok)9.44 E(ens)-.1 E
+F0<24ad>172 409.8 Q F1(Match e)9.44 E(xactly one tok)-.15 E(en)-.1 E F0($=)172
+421.8 Q F2(x)A F1(Match an)5 E 2.5(yp)-.15 G(hrase in class)241.98 421.8 Q F2
+(x)2.5 E F0($~)172 433.8 Q F2(x)A F1(Match an)7.37 E 2.5(yw)-.15 G
+(ord not in class)244.1 433.8 Q F2(x)2.5 E F1 .498(If an)132 450 R 2.998(yo)
+-.15 G 2.998(ft)163.946 450 S .499(hese match, the)173.054 450 R 2.999(ya)-.15
+G .499(re assigned to the symbol)248.271 450 R F0($)2.999 E F2(n)A F1 .499
+(for replacement on the right hand)2.999 F(side, where)132 462 Q F2(n)2.5 E F1
+(is the inde)2.5 E 2.5(xi)-.15 G 2.5(nt)238.78 462 S(he LHS.)249.06 462 Q -.15
+(Fo)5 G 2.5(re).15 G(xample, if the LHS:)307.92 462 Q($\255:$+)172 478.2 Q
+(is applied to the input:)132 494.4 Q(UCB)172 510.6 Q(ARP)-.35 E(A:eric)-.92 E
+(the rule will match, and the v)132 526.8 Q(alues passed to the RHS will be:)
+-.25 E 7.5($1 UCB)172 543 R(ARP)-.35 E(A)-.92 E 7.5($2 eric)172 555 R
+(Additionally)157 575.4 Q 3.398(,t)-.65 G .898(he LHS can include)215.588 575.4
+R F0($@)3.398 E F1 .898(to match zero tok)3.398 F 3.398(ens. This)-.1 F(is)
+3.398 E F2(not)3.398 E F1 .898(bound to a)3.398 F F0($)132 587.4 Q F2(N)A F1
+.837(on the RHS, and is normally only used when it stands alone in order to ma\
+tch the null)3.337 F(input.)132 599.4 Q F0 2.5(5.1.1.2. The)117 623.4 R
+(right hand side)2.5 E F1 .526(When the left hand side of a re)157 639.6 R .525
+(writing rule matches, the input is deleted and replaced)-.25 F .931
+(by the right hand side.)132 651.6 R -.8(To)5.932 G -.1(ke).8 G .932
+(ns are copied directly from the RHS unless the).1 F 3.432(yb)-.15 G -.15(eg)
+457.846 651.6 S .932(in with a).15 F(dollar sign.)132 663.6 Q(Metasymbols are:)
+5 E EP
+%%Page: 24 21
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-24 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E($)172 96 Q/F1 10/Times-Italic@0 SF(n)A
+/F2 10/Times-Roman@0 SF(Substitute inde\214nite tok)222.55 96 Q(en)-.1 E F1(n)
+2.5 E F2(from LHS)2.5 E F0($[)172 108 Q F1(name)A F0($])A F2(Canonicalize)
+222.55 108 Q F1(name)2.5 E F0($\()172 120 Q F1(map k)A -.3(ey)-.1 G F0($@)2.8 E
+F1(ar)A(guments)-.37 E F0($:)2.5 E F1(default)A F0($\))2.5 E F2(Generalized k)
+222.55 132 Q -.15(ey)-.1 G(ed mapping function).15 E F0($>)172 144 Q F1(n)A F2
+(\231Call\232 ruleset)222.55 144 Q F1(n)2.5 E F0($#)172 156 Q F1(mailer)A F2
+(Resolv)222.55 156 Q 2.5(et)-.15 G(o)259.9 156 Q F1(mailer)2.5 E F0($@)172 168
+Q F1(host)A F2(Specify)222.55 168 Q F1(host)2.5 E F0($:)172 180 Q F1(user)A F2
+(Specify)222.55 180 Q F1(user)2.5 E F2(The)157 200.4 Q F0($)3.013 E F1(n)A F2
+.513(syntax substitutes the corresponding v)3.013 F .513(alue from a)-.25 F F0
+($+)3.013 E F2(,)A F0<24ad>3.013 E F2(,)A F0($*)3.012 E F2(,)A F0($=)3.012 E F2
+3.012(,o)C(r)461.876 200.4 Q F0($~)3.012 E F2(match)3.012 E(on the LHS.)132
+212.4 Q(It may be used an)5 E(ywhere.)-.15 E 2.7(Ah)157 228.6 S .2
+(ost name enclosed between)171.92 228.6 R F0($[)2.7 E F2(and)2.7 E F0($])2.7 E
+F2 .2(is look)2.7 F .201(ed up using the)-.1 F F1 -.1(ge)2.701 G(thostent).1 E
+F2 .201(\(3\) routines)1.666 F 3.333(and replaced by the canonical name)132
+242.6 R/F3 7/Times-Roman@0 SF(7)291.675 238.6 Q F2 8.333(.F)295.175 242.6 S
+3.333(or e)311.418 242.6 R 3.332
+(xample, \231$[csam$]\232 might become \231lbl-)-.15 F 1.923
+(csam.arpa\232 and \231$[[128.32.130.2]$]\232 w)132 254.6 R 1.923
+(ould become \231v)-.1 F(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU.)
+.65 E<9a>-.7 E F1(Send-)6.924 E(mail)132 266.6 Q F2 .436(recognizes it')2.936 F
+2.936(sn)-.55 G .436(umeric IP address without calling the name serv)218.578
+266.6 R .435(er and replaces it with)-.15 F(it')132 278.6 Q 2.5(sc)-.55 G
+(anonical name.)151.17 278.6 Q(The)157 294.8 Q F0($\()2.861 E F2(...)2.861 E F0
+($\))5.361 E F2 .361
+(syntax is a more general form of lookup; it uses a named map instead of)2.861
+F .125(an implicit map.)132 306.8 R .125(If no lookup is found, the indicted)
+5.125 F F1(default)2.625 E F2 .124(is inserted; if no def)2.625 F .124
+(ault is speci-)-.1 F(\214ed and no lookup matches, the v)132 318.8 Q
+(alue is left unchanged.)-.25 E(The)157 335 Q F0($>)3.571 E F1(n)A F2 1.071
+(syntax causes the remainder of the line to be substituted as usual and then)
+3.571 F .572(passed as the ar)132 347 R .572(gument to ruleset)-.18 F F1(n)
+3.072 E F2 5.572(.T)C .572(he \214nal v)288.854 347 R .572(alue of ruleset)-.25
+F F1(n)3.072 E F2 .571(then becomes the substitu-)3.072 F(tion for this rule.)
+132 359 Q(The)157 375.2 Q F0($#)3.096 E F2 .596(syntax should)3.096 F F1(only)
+3.096 E F2 .597(be used in ruleset zero.)3.096 F .597(It causes e)5.597 F -.25
+(va)-.25 G .597(luation of the ruleset).25 F .607(to terminate immediately)132
+387.2 R 3.107(,a)-.65 G .607
+(nd signals to sendmail that the address has completely resolv)243.161 387.2 R
+(ed.)-.15 E(The complete syntax is:)132 399.2 Q F0($#)172 415.4 Q F1(mailer)A
+F0($@)2.5 E F1(host)A F0($:)2.5 E F1(user)A F2 .394
+(This speci\214es the {mailer)132 431.6 R 2.894(,h)-.4 G .394
+(ost, user} 3-tuple necessary to direct the mailer)245.466 431.6 R 5.394(.I)
+-.55 G 2.894(ft)447.548 431.6 S .394(he mailer is)456.552 431.6 R .135
+(local the host part may be omitted)132 445.6 R F3(8)268.91 441.6 Q F2 5.135
+(.T)272.41 445.6 S(he)286.155 445.6 Q F1(mailer)2.635 E F2 .136
+(must be a single w)2.636 F .136(ord, b)-.1 F .136(ut the)-.2 F F1(host)2.636 E
+F2(and)2.636 E F1(user)2.636 E F2 .252(may be multi-part.)132 457.6 R .252
+(If the)5.252 F F1(mailer)2.752 E F2 .252(is the b)2.752 F .252
+(uiltin IPC mailer)-.2 F 2.752(,t)-.4 G(he)369.722 457.6 Q F1(host)2.752 E F2
+.251(may be a colon-separated)2.752 F 2.439
+(list of hosts that are searched in order for the \214rst w)132 469.6 R 2.439
+(orking address \(e)-.1 F 2.439(xactly lik)-.15 F 4.939(eM)-.1 G(X)496.78 469.6
+Q(records\).)132 481.6 Q 3.795(AR)157 497.8 S 1.295
+(HS may also be preceded by a)174.685 497.8 R F0($@)3.795 E F2 1.295(or a)3.795
+F F0($:)3.795 E F2 1.294(to control e)3.795 F -.25(va)-.25 G 3.794(luation. A)
+.25 F F0($@)3.794 E F2(pre\214x)3.794 E .61
+(causes the ruleset to return with the remainder of the RHS as the v)132 509.8
+R 3.111(alue. A)-.25 F F0($:)3.111 E F2 .611(pre\214x causes)3.111 F .432
+(the rule to terminate immediately)132 521.8 R 2.931(,b)-.65 G .431
+(ut the ruleset to continue; this can be used to a)276.629 521.8 R -.2(vo)-.2 G
+.431(id con-).2 F(tinued application of a rule.)132 533.8 Q
+(The pre\214x is stripped before continuing.)5 E(The)157 550 Q F0($@)2.5 E F2
+(and)2.5 E F0($:)2.5 E F2(pre\214x)2.5 E(es may precede a)-.15 E F0($>)2.5 E F2
+(spec; for e)2.5 E(xample:)-.15 E 20.19(R$+ $:)172 566.2 R($>7 $1)2.5 E .256
+(matches an)132 582.4 R .256(ything, passes that to ruleset se)-.15 F -.15(ve)
+-.25 G .256(n, and continues; the).15 F F0($:)2.756 E F2 .256
+(is necessary to a)2.756 F -.2(vo)-.2 G .256(id an).2 F(in\214nite loop.)132
+594.4 Q .051(Substitution occurs in the order described, that is, parameters f\
+rom the LHS are substi-)157 610.6 R .556(tuted, hostnames are canonicalized, \
+\231subroutines\232 are called, and \214nally)132 622.6 R F0($#)3.056 E F2(,)A
+F0($@)3.056 E F2 3.056(,a)C(nd)467.346 622.6 Q F0($:)3.057 E F2(are)3.057 E
+(processed.)132 634.6 Q .32 LW 76 655.6 72 655.6 DL 80 655.6 76 655.6 DL 84
+655.6 80 655.6 DL 88 655.6 84 655.6 DL 92 655.6 88 655.6 DL 96 655.6 92 655.6
+DL 100 655.6 96 655.6 DL 104 655.6 100 655.6 DL 108 655.6 104 655.6 DL 112
+655.6 108 655.6 DL 116 655.6 112 655.6 DL 120 655.6 116 655.6 DL 124 655.6 120
+655.6 DL 128 655.6 124 655.6 DL 132 655.6 128 655.6 DL 136 655.6 132 655.6 DL
+140 655.6 136 655.6 DL 144 655.6 140 655.6 DL 148 655.6 144 655.6 DL 152 655.6
+148 655.6 DL 156 655.6 152 655.6 DL 160 655.6 156 655.6 DL 164 655.6 160 655.6
+DL 168 655.6 164 655.6 DL 172 655.6 168 655.6 DL 176 655.6 172 655.6 DL 180
+655.6 176 655.6 DL 184 655.6 180 655.6 DL 188 655.6 184 655.6 DL 192 655.6 188
+655.6 DL 196 655.6 192 655.6 DL 200 655.6 196 655.6 DL 204 655.6 200 655.6 DL
+208 655.6 204 655.6 DL 212 655.6 208 655.6 DL 216 655.6 212 655.6 DL/F4 5
+/Times-Roman@0 SF(7)93.6 666 Q/F5 8/Times-Roman@0 SF
+(This is actually completely equi)3.2 I -.2(va)-.2 G(lent to $\(host).2 E/F6 8
+/Times-Italic@0 SF(hostname)2 E F5 2($\). In)B(particular)2 E 2(,a)-.32 G/F7 8
+/Times-Bold@0 SF($:)A F5(def)2 E(ault can be used.)-.08 E F4(8)93.6 679.6 Q F5
+-.88(Yo)3.2 K 2.208(um).88 G .208(ay w)117.428 682.8 R .208
+(ant to use it for special \231per user\232 e)-.08 F 2.208(xtensions. F)-.12 F
+.208(or e)-.12 F .208
+(xample, at CMU you can send email to \231jgm+foo\232; the part af-)-.12 F(ter\
+ the plus sign is not part of the user name, and is passed to the local mailer\
+ for local use.)72 692.4 Q EP
+%%Page: 25 22
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-25)452.9 60 Q 2.5(5.1.1.3. Semantics)117 96 R(of r)2.5 E
+(ewriting rule sets)-.18 E/F1 10/Times-Roman@0 SF 2.922(There are \214v)157
+112.2 R 5.422(er)-.15 G -.25(ew)226.976 112.2 S 2.922(riting sets that ha).25 F
+3.222 -.15(ve s)-.2 H 2.922(peci\214c semantics.).15 F 2.921
+(These are related as)7.921 F(depicted by \214gure 2.)132 124.2 Q 1.091
+(Ruleset three should turn the address into \231canonical form.)157 140.4 R
+6.092<9a54>-.7 G 1.092(his form should ha)416.914 140.4 R -.15(ve)-.2 G
+(the basic syntax:)132 152.4 Q(local-part@host-domain-spec)172 168.6 Q 1.296
+(If no \231@\232 sign is speci\214ed, then the host-domain-spec)132 184.8 R/F2
+10/Times-Italic@0 SF(may)3.796 E F1 1.295(be appended from the sender)3.796 F
+1.284(address \(if the)132 196.8 R F0(C)3.784 E F1 1.284
+(\215ag is set in the mailer de\214nition corresponding to the)3.784 F F2
+(sending)3.784 E F1(mailer\).)3.784 E
+(Ruleset three is applied by sendmail before doing an)132 208.8 Q
+(ything with an)-.15 E 2.5(ya)-.15 G(ddress.)411.39 208.8 Q .506(Ruleset zero \
+is applied after ruleset three to addresses that are going to actually spec-)
+157 225 R .295(ify recipients.)132 237 R .295(It must resolv)5.295 F 2.795(et)
+-.15 G 2.795(oa)258.035 237 S F2({mailer).001 E 2.796(,h)-1.11 G .296
+(ost, user})312.362 237 R F1 2.796(triple. The)2.796 F F2(mailer)2.796 E F1
+.296(must be de\214ned in)2.796 F .561
+(the mailer de\214nitions from the con\214guration \214le.)132 249 R(The)5.561
+E F2(host)3.061 E F1 .56(is de\214ned into the)3.061 F F0($h)3.06 E F1 .56
+(macro for)3.06 F(use in the ar)132 261 Q(gv e)-.18 E
+(xpansion of the speci\214ed mailer)-.15 E(.)-.55 E 1.356(Rulesets one and tw)
+157 277.2 R 3.856(oa)-.1 G 1.357
+(re applied to all sender and recipient addresses respecti)254.534 277.2 R -.15
+(ve)-.25 G(ly).15 E(.)-.65 E(The)132 289.2 Q 2.5(ya)-.15 G
+(re applied before an)159.34 289.2 Q 2.5(ys)-.15 G
+(peci\214cation in the mailer de\214nition.)250.27 289.2 Q(The)5 E 2.5(ym)-.15
+G(ust ne)429 289.2 Q -.15(ve)-.25 G 2.5(rr).15 G(esolv)470.81 289.2 Q(e.)-.15 E
+.266(Ruleset four is applied to all addresses in the message.)157 305.4 R .265
+(It is typically used to translate)5.265 F(internal to e)132 317.4 Q
+(xternal form.)-.15 E F0 2.5(5.1.1.4. IPC)117 341.4 R(mailers)2.5 E F1 .332
+(Some special processing occurs if the ruleset zero resolv)157 357.6 R .333
+(es to an IPC mailer \(that is, a)-.15 F .242
+(mailer that has \231[IPC]\232 listed as the P)132 369.6 R .241(ath in the)-.15
+F F0(M)2.741 E F1 .241(con\214guration line.)2.741 F .241(The host name passed)
+5.241 F .884(after \231$@\232 has MX e)132 381.6 R .885
+(xpansion performed; this looks the name up in DNS to \214nd alternate)-.15 F
+(deli)132 393.6 Q -.15(ve)-.25 G(ry sites.).15 E(The host name can also be pro)
+157 409.8 Q(vided as a dotted quad in square brack)-.15 E(ets; for e)-.1 E
+(xample:)-.15 E([128.32.149.78])172 426 Q(This causes direct con)132 442.2 Q
+-.15(ve)-.4 G(rsion of the numeric v).15 E(alue to a TCP/IP host address.)-.25
+E .894(The host name passed in after the \231$@\232 may also be a colon-separa\
+ted list of hosts.)157 458.4 R .629(Each is separately MX e)132 470.4 R .629
+(xpanded and the results are concatenated to mak)-.15 F 3.13(e\()-.1 G .63
+(essentially\) one)440.88 470.4 R .4 LW 77 494.4 72 494.4 DL 79 494.4 74 494.4
+DL 84 494.4 79 494.4 DL 89 494.4 84 494.4 DL 94 494.4 89 494.4 DL 99 494.4 94
+494.4 DL 104 494.4 99 494.4 DL 109 494.4 104 494.4 DL 114 494.4 109 494.4 DL
+119 494.4 114 494.4 DL 124 494.4 119 494.4 DL 129 494.4 124 494.4 DL 134 494.4
+129 494.4 DL 139 494.4 134 494.4 DL 144 494.4 139 494.4 DL 149 494.4 144 494.4
+DL 154 494.4 149 494.4 DL 159 494.4 154 494.4 DL 164 494.4 159 494.4 DL 169
+494.4 164 494.4 DL 174 494.4 169 494.4 DL 179 494.4 174 494.4 DL 184 494.4 179
+494.4 DL 189 494.4 184 494.4 DL 194 494.4 189 494.4 DL 199 494.4 194 494.4 DL
+204 494.4 199 494.4 DL 209 494.4 204 494.4 DL 214 494.4 209 494.4 DL 219 494.4
+214 494.4 DL 224 494.4 219 494.4 DL 229 494.4 224 494.4 DL 234 494.4 229 494.4
+DL 239 494.4 234 494.4 DL 244 494.4 239 494.4 DL 249 494.4 244 494.4 DL 254
+494.4 249 494.4 DL 259 494.4 254 494.4 DL 264 494.4 259 494.4 DL 269 494.4 264
+494.4 DL 274 494.4 269 494.4 DL 279 494.4 274 494.4 DL 284 494.4 279 494.4 DL
+289 494.4 284 494.4 DL 294 494.4 289 494.4 DL 299 494.4 294 494.4 DL 304 494.4
+299 494.4 DL 309 494.4 304 494.4 DL 314 494.4 309 494.4 DL 319 494.4 314 494.4
+DL 324 494.4 319 494.4 DL 329 494.4 324 494.4 DL 334 494.4 329 494.4 DL 339
+494.4 334 494.4 DL 344 494.4 339 494.4 DL 349 494.4 344 494.4 DL 354 494.4 349
+494.4 DL 359 494.4 354 494.4 DL 364 494.4 359 494.4 DL 369 494.4 364 494.4 DL
+374 494.4 369 494.4 DL 379 494.4 374 494.4 DL 384 494.4 379 494.4 DL 389 494.4
+384 494.4 DL 394 494.4 389 494.4 DL 399 494.4 394 494.4 DL 404 494.4 399 494.4
+DL 409 494.4 404 494.4 DL 414 494.4 409 494.4 DL 419 494.4 414 494.4 DL 424
+494.4 419 494.4 DL 429 494.4 424 494.4 DL 434 494.4 429 494.4 DL 439 494.4 434
+494.4 DL 444 494.4 439 494.4 DL 449 494.4 444 494.4 DL 454 494.4 449 494.4 DL
+459 494.4 454 494.4 DL 464 494.4 459 494.4 DL 469 494.4 464 494.4 DL 474 494.4
+469 494.4 DL 479 494.4 474 494.4 DL 484 494.4 479 494.4 DL 489 494.4 484 494.4
+DL 494 494.4 489 494.4 DL 499 494.4 494 494.4 DL 504 494.4 499 494.4 DL(addr)
+91.915 588.8 Q 133.2 586.8 111.6 586.8 DL 133.2 586.8 126 588.6 DL 133.2 586.8
+126 585 DL(3)141.5 588.8 Q 133.2 576 133.2 597.6 DL 154.8 576 133.2 576 DL
+154.8 597.6 154.8 576 DL 133.2 597.6 154.8 597.6 DL 176.4 586.8 154.8 586.8 DL
+176.4 586.8 169.2 588.6 DL 176.4 586.8 169.2 585 DL(D)183.59 588.8 Q 176.4 576
+176.4 597.6 DL 198 576 176.4 576 DL 198 597.6 198 576 DL 176.4 597.6 198 597.6
+DL 219.6 586.8 198 586.8 DL 277.2 568.8 255.6 568.8 DL 277.2 568.8 270 570.6 DL
+277.2 568.8 270 567 DL(1)285.5 570.8 Q 277.2 558 277.2 579.6 DL 298.8 558 277.2
+558 DL 298.8 579.6 298.8 558 DL 277.2 579.6 298.8 579.6 DL 320.4 568.8 298.8
+568.8 DL 320.4 568.8 313.2 570.6 DL 320.4 568.8 313.2 567 DL(S)328.42 570.8 Q
+320.4 558 320.4 579.6 DL 342 558 320.4 558 DL 342 579.6 342 558 DL 320.4 579.6
+342 579.6 DL 363.6 568.8 342 568.8 DL 277.2 604.8 255.6 604.8 DL 277.2 604.8
+270 606.6 DL 277.2 604.8 270 603 DL(2)285.5 606.8 Q 277.2 594 277.2 615.6 DL
+298.8 594 277.2 594 DL 298.8 615.6 298.8 594 DL 277.2 615.6 298.8 615.6 DL
+320.4 604.8 298.8 604.8 DL 320.4 604.8 313.2 606.6 DL 320.4 604.8 313.2 603 DL
+(R)327.865 606.8 Q 320.4 594 320.4 615.6 DL 342 594 320.4 594 DL 342 615.6 342
+594 DL 320.4 615.6 342 615.6 DL 363.6 604.8 342 604.8 DL 421.2 586.8 399.6
+586.8 DL 421.2 586.8 414 588.6 DL 421.2 586.8 414 585 DL(4)429.5 588.8 Q 421.2
+576 421.2 597.6 DL 442.8 576 421.2 576 DL 442.8 597.6 442.8 576 DL 421.2 597.6
+442.8 597.6 DL 464.4 586.8 442.8 586.8 DL 464.4 586.8 457.2 588.6 DL 464.4
+586.8 457.2 585 DL(msg)466.865 588.8 Q 255.6 568.8 219.6 586.8 DL 255.6 604.8
+219.6 586.8 DL 399.6 586.8 363.6 568.8 DL 399.6 586.8 363.6 604.8 DL 208.8
+532.8 187.2 532.8 DL 208.8 532.8 201.6 534.6 DL 208.8 532.8 201.6 531 DL(0)
+217.1 534.8 Q 208.8 522 208.8 543.6 DL 230.4 522 208.8 522 DL 230.4 543.6 230.4
+522 DL 208.8 543.6 230.4 543.6 DL 252 532.8 230.4 532.8 DL 252 532.8 244.8
+534.6 DL 252 532.8 244.8 531 DL(resolv)265.69 534.8 Q(ed address)-.15 E 187.2
+532.8 162 586.8 DL(Figure 2 \212 Re)216.045 634.8 Q(writing set semantics)-.25
+E 2.5(D\212s)209.35 646.8 S(ender domain addition)235.46 646.8 Q 2.5(S\212m)
+209.35 658.8 S(ailer)237.69 658.8 Q(-speci\214c sender re)-.2 E(writing)-.25 E
+2.5(R\212m)209.35 670.8 S(ailer)238.8 670.8 Q(-speci\214c recipient re)-.2 E
+(writing)-.25 E 77 682.8 72 682.8 DL 79 682.8 74 682.8 DL 84 682.8 79 682.8 DL
+89 682.8 84 682.8 DL 94 682.8 89 682.8 DL 99 682.8 94 682.8 DL 104 682.8 99
+682.8 DL 109 682.8 104 682.8 DL 114 682.8 109 682.8 DL 119 682.8 114 682.8 DL
+124 682.8 119 682.8 DL 129 682.8 124 682.8 DL 134 682.8 129 682.8 DL 139 682.8
+134 682.8 DL 144 682.8 139 682.8 DL 149 682.8 144 682.8 DL 154 682.8 149 682.8
+DL 159 682.8 154 682.8 DL 164 682.8 159 682.8 DL 169 682.8 164 682.8 DL 174
+682.8 169 682.8 DL 179 682.8 174 682.8 DL 184 682.8 179 682.8 DL 189 682.8 184
+682.8 DL 194 682.8 189 682.8 DL 199 682.8 194 682.8 DL 204 682.8 199 682.8 DL
+209 682.8 204 682.8 DL 214 682.8 209 682.8 DL 219 682.8 214 682.8 DL 224 682.8
+219 682.8 DL 229 682.8 224 682.8 DL 234 682.8 229 682.8 DL 239 682.8 234 682.8
+DL 244 682.8 239 682.8 DL 249 682.8 244 682.8 DL 254 682.8 249 682.8 DL 259
+682.8 254 682.8 DL 264 682.8 259 682.8 DL 269 682.8 264 682.8 DL 274 682.8 269
+682.8 DL 279 682.8 274 682.8 DL 284 682.8 279 682.8 DL 289 682.8 284 682.8 DL
+294 682.8 289 682.8 DL 299 682.8 294 682.8 DL 304 682.8 299 682.8 DL 309 682.8
+304 682.8 DL 314 682.8 309 682.8 DL 319 682.8 314 682.8 DL 324 682.8 319 682.8
+DL 329 682.8 324 682.8 DL 334 682.8 329 682.8 DL 339 682.8 334 682.8 DL 344
+682.8 339 682.8 DL 349 682.8 344 682.8 DL 354 682.8 349 682.8 DL 359 682.8 354
+682.8 DL 364 682.8 359 682.8 DL 369 682.8 364 682.8 DL 374 682.8 369 682.8 DL
+379 682.8 374 682.8 DL 384 682.8 379 682.8 DL 389 682.8 384 682.8 DL 394 682.8
+389 682.8 DL 399 682.8 394 682.8 DL 404 682.8 399 682.8 DL 409 682.8 404 682.8
+DL 414 682.8 409 682.8 DL 419 682.8 414 682.8 DL 424 682.8 419 682.8 DL 429
+682.8 424 682.8 DL 434 682.8 429 682.8 DL 439 682.8 434 682.8 DL 444 682.8 439
+682.8 DL 449 682.8 444 682.8 DL 454 682.8 449 682.8 DL 459 682.8 454 682.8 DL
+464 682.8 459 682.8 DL 469 682.8 464 682.8 DL 474 682.8 469 682.8 DL 479 682.8
+474 682.8 DL 484 682.8 479 682.8 DL 489 682.8 484 682.8 DL 494 682.8 489 682.8
+DL 499 682.8 494 682.8 DL 504 682.8 499 682.8 DL EP
+%%Page: 26 23
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-26 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF .379
+(long MX list.)132 96 R .378(The intent here is to create \231f)5.379 F(ak)-.1
+E .378(e\232 MX records that are not published in DNS)-.1 F(for pri)132 108 Q
+-.25(va)-.25 G(te internal netw).25 E(orks.)-.1 E .17
+(As a \214nal special case, the host name can be passed in as a te)157 124.2 R
+.17(xt string in square brack-)-.15 F(ets:)132 136.2 Q([ucb)172 152.4 Q -.25
+(va)-.15 G(x.berk).25 E(ele)-.1 E -.65(y.)-.15 G(edu]).65 E 1.245(This form a)
+132 168.6 R -.2(vo)-.2 G 1.245(ids the MX mapping.).2 F F0(N.B.:)6.244 E F1
+1.244(This is intended only for situations where you)3.744 F(ha)132 180.6 Q
+.814 -.15(ve a n)-.2 H(etw).15 E .514(ork \214re)-.1 F -.1(wa)-.25 G .514
+(ll, so that your MX record points to a g).1 F(ate)-.05 E -.1(wa)-.25 G 3.014
+(ym).1 G .514(achine; this machine)420.762 180.6 R 1.604
+(could then do direct deli)132 192.6 R -.15(ve)-.25 G 1.604
+(ry to machines within your local domain.).15 F 1.603(Use of this feature)6.603
+F(directly violates RFC 1123 section 5.3.5: it should not be used lightly)132
+204.6 Q(.)-.65 E F0 2.5(5.1.2. D)102 228.6 R 2.5<8a64>2.5 G(e\214ne macr)157.28
+228.6 Q(o)-.18 E F1 .546(Macros are named with a single character)142 244.8 R
+5.546(.T)-.55 G .547(hese may be selected from the entire ASCII)325.492 244.8 R
+.892(set, b)117 256.8 R .892(ut user)-.2 F .892
+(-de\214ned macros should be selected from the set of upper case letters only)
+-.2 F 5.892(.L)-.65 G -.25(ow)484.26 256.8 S(er).25 E
+(case letters and special symbols are used internally)117 268.8 Q(.)-.65 E
+(The syntax for macro de\214nitions is:)142 285 Q F0(D)157 301.2 Q/F2 10
+/Times-Italic@0 SF 1.666(xv)C(al)-1.666 E F1(where)117 317.4 Q F2(x)2.5 E F1
+(is the name of the macro and)2.5 E F2(val)2.5 E F1(is the v)2.5 E
+(alue it should ha)-.25 E -.15(ve)-.2 G(.).15 E 1.085
+(Macros are interpolated using the construct)142 333.6 R F0($)3.585 E F2(x)A F1
+3.585(,w)C(here)346.775 333.6 Q F2(x)3.585 E F1 1.085
+(is the name of the macro to be)3.585 F 3.45(interpolated. This)117 345.6 R .95
+(interpolation is done when the con\214guration \214le is read, e)3.45 F .95
+(xcept in)-.15 F F0(M)3.45 E F1(lines.)3.45 E(The special construct)117 357.6 Q
+F0($&)2.5 E F2(x)A F1(can be used in)2.5 E F0(R)2.5 E F1
+(lines to get deferred interpolation.)2.5 E
+(Conditionals can be speci\214ed using the syntax:)142 373.8 Q($?x te)157 390 Q
+(xt1 $| te)-.15 E(xt2 $.)-.15 E .245(This interpolates)117 406.2 R F2(te)2.745
+E(xt1)-.2 E F1 .245(if the macro)2.745 F F0($x)2.745 E F1 .245(is set, and)
+2.745 F F2(te)2.745 E(xt2)-.2 E F1 2.745(otherwise. The)2.745 F .246
+(\231else\232 \()2.746 F F0($|)A F1 2.746(\)c)C .246(lause may be)451.298 406.2
+R(omitted.)117 418.2 Q(Lo)142 434.4 Q .262(wer case macro names are reserv)-.25
+F .262(ed to ha)-.15 F .561 -.15(ve s)-.2 H .261
+(pecial semantics, used to pass information).15 F 1.163
+(in or out of sendmail, and special characters are reserv)117 446.4 R 1.163
+(ed to pro)-.15 F 1.163(vide conditionals, etc.)-.15 F(Upper)6.163 E
+(case names \(that is,)117 458.4 Q F0($A)2.5 E F1(through)2.5 E F0($Z)2.5 E F1
+2.5(\)a)C(re speci\214cally reserv)267.53 458.4 Q
+(ed for con\214guration \214le authors.)-.15 E(The follo)142 474.6 Q
+(wing macros)-.25 E F2(must)2.5 E F1(be de\214ned to transmit information into)
+2.5 E F2(sendmail:)2.5 E F1 15.56(eT)157 490.8 S(he SMTP entry message)183.11
+490.8 Q 17.22(jT)157 502.8 S(he \231of)183.11 502.8 Q
+(\214cial\232 domain name for this site)-.25 E 17.22(lT)157 514.8 S
+(he format of the UNIX from line)183.11 514.8 Q 15(nT)157 526.8 S
+(he name of the daemon \(for error messages\))183.11 526.8 Q 15(oT)157 538.8 S
+(he set of "operators" in addresses)183.11 538.8 Q 15(qd)157 550.8 S(ef)182
+550.8 Q(ault format of sender address)-.1 E(The)117 567 Q F0($e)2.657 E F1 .157
+(macro is printed out when SMTP starts up.)2.657 F .157(The \214rst w)5.157 F
+.157(ord must be the)-.1 F F0($j)2.657 E F1 2.656(macro. The)2.656 F F0($j)
+2.656 E F1 .536(macro should be in RFC821 format.)117 579 R(The)5.536 E F0($l)
+3.036 E F1(and)3.036 E F0($n)3.036 E F1 .536
+(macros can be considered constants e)3.036 F(xcept)-.15 E .783
+(under terribly unusual circumstances.)117 591 R(The)5.783 E F0($o)3.283 E F1
+.783(macro consists of a list of characters which will)3.283 F .497
+(be considered tok)117 603 R .498(ens and which will separate tok)-.1 F .498
+(ens when doing parsing.)-.1 F -.15(Fo)5.498 G 2.998(re).15 G .498
+(xample, if \231@\232)441.864 603 R .997(were in the)117 615 R F0($o)3.497 E F1
+.997(macro, then the input \231a@b\232 w)3.497 F .996
+(ould be scanned as three tok)-.1 F .996(ens: \231a,)-.1 F 3.496<9a99>-.7 G(@,)
+470.614 615 Q 3.496<9a61>-.7 G(nd)494 615 Q<9962>117 627 Q 5.594 -.7(.\232 F)
+-.4 H(inally).7 E 4.194(,t)-.65 G(he)176.138 627 Q F0($q)4.194 E F1 1.694
+(macro speci\214es ho)4.194 F 4.194(wa)-.25 G 4.194(na)297.948 627 S 1.695
+(ddress should appear in a message when it is)311.582 627 R(def)117 639 Q 2.5
+(aulted. F)-.1 F(or e)-.15 E(xample, on our system these de\214nitions are:)
+-.15 E EP
+%%Page: 27 24
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-27)452.9 60 Q/F1 10/Times-Roman@0 SF(De$j Sendmail $v/$Z ready at $b)
+157 96 Q(DnMAILER-D)157 108 Q(AEMON)-.4 E(DlFrom $g)157 120 Q($d)5 E
+(Do.:%@!^/[])157 132 Q(Dq$?x$x <$g>$|$g$.)157 144 Q(Dj$w)157 156 Q .068
+(An acceptable alternati)117 172.2 R .367 -.15(ve f)-.25 H .067(or the).15 F F0
+($q)2.567 E F1 .067(macro is \231$g$?x \($x\)$.)2.567 F 2.567(\232. These)-.7 F
+.067(correspond to the follo)2.567 F(wing)-.25 E(tw)117 184.2 Q 2.5(of)-.1 G
+(ormats:)137.73 184.2 Q(Eric Allman <eric@CS.Berk)157 200.4 Q(ele)-.1 E -.65
+(y.)-.15 G(EDU>).65 E(eric@CS.Berk)157 212.4 Q(ele)-.1 E -.65(y.)-.15 G
+(EDU \(Eric Allman\)).65 E/F2 10/Times-Italic@0 SF(Sendmail)117 228.6 Q F1
+(properly quotes names that ha)2.5 E .3 -.15(ve s)-.2 H
+(pecial characters if the \214rst form is used.).15 E .239
+(Some macros are de\214ned by)142 244.8 R F2(sendmail)2.739 E F1 .239
+(for interpolation into ar)2.739 F(gv')-.18 E 2.739(sf)-.55 G .24
+(or mailers or for other)414.73 244.8 R(conte)117 256.8 Q 2.5(xts. These)-.15 F
+(macros are:)2.5 E 15.56(aT)157 273 S(he origination date in RFC 822 format)
+183.11 273 Q 15(bT)157 285 S(he current date in RFC 822 format)183.11 285 Q
+15.56(cT)157 297 S(he hop count)183.11 297 Q 15(dT)157 309 S
+(he date in UNIX \(ctime\) format)183.11 309 Q 16.67(fT)157 321 S
+(he sender \(from\) address)183.11 321 Q 15(gT)157 333 S
+(he sender address relati)183.11 333 Q .3 -.15(ve t)-.25 H 2.5(ot).15 G
+(he recipient)301.29 333 Q 15(hT)157 345 S(he recipient host)183.11 345 Q 17.22
+(iT)157 357 S(he queue id)183.11 357 Q 15(kT)157 369 S
+(he UUCP node name \(from the uname system call\))183.11 369 Q 12.22(mT)157 381
+S(he domain part of the)183.11 381 Q F2 -.1(ge)2.5 G(thostname).1 E F1
+(return v)2.5 E(alue)-.25 E 15(pS)157 393 S(endmail')182.56 393 Q 2.5(sp)-.55 G
+(id)228.95 393 Q 16.67(rP)157 405 S(rotocol used to recei)182.56 405 Q .3 -.15
+(ve t)-.25 H(he message).15 E 16.11(sS)157 417 S(ender')182.56 417 Q 2.5(sh)
+-.55 G(ost name)218.94 417 Q 17.22(tA)157 429 S
+(numeric representation of the current time)186.72 429 Q 15(uT)157 441 S
+(he recipient user)183.11 441 Q 15(vT)157 453 S(he v)183.11 453 Q
+(ersion number of sendmail)-.15 E 12.78(wT)157 465 S(he hostname of this site)
+183.11 465 Q 15(xT)157 477 S(he full name of the sender)183.11 477 Q 15.56(zT)
+157 489 S(he home directory of the recipient)183.11 489 Q 15(_T)157 501 S(he v)
+183.11 501 Q(alidated sender address)-.25 E .918
+(There are three types of dates that can be used.)142 521.4 R(The)5.918 E F0
+($a)3.418 E F1(and)3.418 E F0($b)3.418 E F1 .917(macros are in RFC 822)3.418 F
+(format;)117 533.4 Q F0($a)3.046 E F1 .546(is the time as e)3.046 F .547
+(xtracted from the \231Date:\232 line of the message \(if there w)-.15 F .547
+(as one\), and)-.1 F F0($b)117 545.4 Q F1 .145
+(is the current date and time \(used for postmarks\).)2.645 F .145
+(If no \231Date:\232 line is found in the incoming)5.145 F(message,)117 557.4 Q
+F0($a)2.546 E F1 .046(is set to the current time also.)2.546 F(The)5.046 E F0
+($d)2.546 E F1 .046(macro is equi)2.546 F -.25(va)-.25 G .047(lent to the).25 F
+F0($b)2.547 E F1 .047(macro in UNIX)2.547 F(\(ctime\) format.)117 569.4 Q(The)
+142 585.6 Q F0($f)3.115 E F1 .614(macro is the id of the sender as originally \
+determined; when mailing to a speci\214c)3.115 F .601(host the)117 597.6 R F0
+($g)3.101 E F1 .601(macro is set to the address of the sender)3.101 F F2 -.37
+(re)3.102 G .602(lative to the r).37 F(ecipient.)-.37 E F1 -.15(Fo)5.602 G
+3.102(re).15 G .602(xample, if I)456.416 597.6 R 1.65
+(send to \231bollard@matisse.CS.Berk)117 609.6 R(ele)-.1 E -.65(y.)-.15 G 1.65
+(EDU\232 from the machine \231v).65 F(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)
+-.15 G(EDU\232).65 E(the)117 621.6 Q F0($f)2.5 E F1
+(macro will be \231eric\232 and the)2.5 E F0($g)2.5 E F1
+(macro will be \231eric@v)2.5 E(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G
+(EDU.).65 E<9a>-.7 E(The)142 637.8 Q F0($x)3.837 E F1 1.338
+(macro is set to the full name of the sender)3.837 F 6.338(.T)-.55 G 1.338
+(his can be determined in se)369.13 637.8 R -.15(ve)-.25 G(ral).15 E -.1(wa)117
+649.8 S 2.953(ys. It).1 F .453(can be passed as \215ag to)2.953 F F2(sendmail.)
+2.953 E F1 .453(The second choice is the v)5.453 F .453
+(alue of the \231Full-name:\232)-.25 F .512(line in the header if it e)117
+661.8 R .513
+(xists, and the third choice is the comment \214eld of a \231From:\232 line.)
+-.15 F .513(If all)5.513 F 1.149(of these f)117 673.8 R 1.149
+(ail, and if the message is being originated locally)-.1 F 3.648(,t)-.65 G
+1.148(he full name is look)369.684 673.8 R 1.148(ed up in the)-.1 F F2
+(/etc/passwd)117 685.8 Q F1(\214le.)2.5 E .438(When sending, the)142 702 R F0
+($h)2.938 E F1(,)A F0($u)2.938 E F1 2.938(,a)C(nd)256.96 702 Q F0($z)2.938 E F1
+.438(macros get set to the host, user)2.938 F 2.939(,a)-.4 G .439
+(nd home directory \(if)417.423 702 R 1.455(local\) of the recipient.)117 714 R
+1.455(The \214rst tw)6.455 F 3.955(oa)-.1 G 1.454(re set from the)278.445 714 R
+F0($@)3.954 E F1(and)3.954 E F0($:)3.954 E F1 1.454(part of the re)3.954 F
+1.454(writing rules,)-.25 F EP
+%%Page: 28 25
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-28 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(respecti)117 96
+Q -.15(ve)-.25 G(ly).15 E(.)-.65 E(The)142 112.2 Q F0($p)2.806 E F1(and)2.806 E
+F0($t)2.806 E F1 .306(macros are used to create unique strings \(e.g., for the\
+ \231Message-Id:\232 \214eld\).)2.806 F(The)117 124.2 Q F0($i)2.538 E F1 .037(\
+macro is set to the queue id on this host; if put into the timestamp line it c\
+an be e)2.538 F(xtremely)-.15 E .407(useful for tracking messages.)117 136.2 R
+(The)5.407 E F0($v)2.907 E F1 .407(macro is set to be the v)2.907 F .407
+(ersion number of)-.15 F/F2 10/Times-Italic@0 SF(sendmail)2.907 E F1 2.907(;t)C
+.408(his is)482.752 136.2 R 2.109(normally put in timestamps and has been pro)
+117 148.2 R -.15(ve)-.15 G 4.609(ne).15 G 2.109(xtremely useful for deb)334.515
+148.2 R 4.609(ugging. The)-.2 F F0($w)4.609 E F1 1.221
+(macro is set to the name of this host if it can be determined.)117 160.2 R
+(The)6.222 E F0($c)3.722 E F1 1.222(\214eld is set to the \231hop)3.722 F
+(count,)117 172.2 Q 3.333<9a69>-.7 G .833
+(.e., the number of times this message has been processed.)151.573 172.2 R .832
+(This can be determined by)5.832 F(the)117 184.2 Q F0<ad68>2.5 E F1
+(\215ag on the command line or by counting the timestamps in the message.)2.5 E
+(The)142 200.4 Q F0($r)3.426 E F1(and)3.426 E F0($s)3.426 E F1 .926
+(\214elds are set to the protocol used to communicate with sendmail and the)
+3.426 F .969(sending hostname.)117 212.4 R(The)5.969 E F0($_)3.469 E F1 .969
+(is set to a v)3.469 F .969(alidated sender host name.)-.25 F .968
+(If the sender is running an)5.969 F(RFC 1413 compliant IDENT serv)117 224.4 Q
+(er)-.15 E 2.5(,i)-.4 G 2.5(tw)267.55 224.4 S
+(ill include the user name on that host.)280.05 224.4 Q F0 2.5(5.1.3. C)102
+248.4 R(and F \212 de\214ne classes)2.5 E F1 .197
+(Classes of phrases may be de\214ned to match on the left hand side of re)142
+264.6 R .197(writing rules, where)-.25 F 2.791<6199>117 276.6 S .291
+(phrase\232 is a sequence of characters that do not contain space characters.)
+128.671 276.6 R -.15(Fo)5.29 G 2.79(re).15 G .29(xample a class)445.1 276.6 R
+.356(of all local names for this site might be created so that attempts to sen\
+d to oneself can be elimi-)117 288.6 R 2.89(nated. These)117 300.6 R .39(can e\
+ither be de\214ned directly in the con\214guration \214le or read in from anot\
+her \214le.)2.89 F .796(Classes may be gi)117 312.6 R -.15(ve)-.25 G 3.296(nn)
+.15 G .796(ames from the set of upper case letters.)213.664 312.6 R(Lo)5.796 E
+.797(wer case letters and special)-.25 F(characters are reserv)117 324.6 Q
+(ed for system use.)-.15 E(The syntax is:)142 340.8 Q F0(C)157 357 Q F2 1.666
+(cp)C(hr)-1.666 E(ase1 phr)-.15 E(ase2...)-.15 E F0(F)157 369 Q F2 1.666<638c>C
+(le)-1.666 E F1 1.115(The \214rst form de\214nes the class)117 385.2 R F2(c)
+3.615 E F1 1.115(to match an)3.615 F 3.614(yo)-.15 G 3.614(ft)319.638 385.2 S
+1.114(he named w)329.362 385.2 R 3.614(ords. It)-.1 F 1.114
+(is permissible to split)3.614 F(them among multiple lines; for e)117 397.2 Q
+(xample, the tw)-.15 E 2.5(of)-.1 G(orms:)317.57 397.2 Q(CHmonet ucbmonet)157
+413.4 Q(and)117 429.6 Q(CHmonet)157 445.8 Q(CHucbmonet)157 457.8 Q(are equi)117
+474 Q -.25(va)-.25 G 2.5(lent. The).25 F
+(second form reads the elements of the class)2.5 E F2(c)2.5 E F1
+(from the named)2.5 E F2(\214le)2.5 E F1(.)A(The)142 490.2 Q F0($~)3.112 E F1
+.613(\(match entries not in class\) only matches a single w)3.112 F .613
+(ord; multi-w)-.1 F .613(ord entries in the)-.1 F
+(class are ignored in this conte)117 502.2 Q(xt.)-.15 E .384(The class)142
+518.4 R F0($=w)2.884 E F1 .384
+(is set to be the set of all names this host is kno)2.884 F .384(wn by)-.25 F
+5.384(.T)-.65 G .383(his can be used to)431.368 518.4 R(match local hostnames.)
+117 530.4 Q(The class)142 546.6 Q F0($=k)2.5 E F1(is set to be the same as)2.5
+E F0($k)2.5 E F1 2.5(,t)C(hat is, the UUCP node name.)312.69 546.6 Q F0 2.5
+(5.1.4. M)102 570.6 R 2.5<8a64>2.5 G(e\214ne mailer)159.5 570.6 Q F1
+(Programs and interf)142 586.8 Q(aces to mailers are de\214ned in this line.)
+-.1 E(The format is:)5 E F0(M)157 603 Q F2(name)A F1 2.5(,{)C F2(\214eld)197.9
+603 Q F1(=)A F2(value)A F1(}*)1.666 E(where)117 619.2 Q F2(name)3.244 E F1 .744
+(is the name of the mailer \(used internally only\) and the \231\214eld=name\
+\232 pairs de\214ne)3.244 F(attrib)117 631.2 Q(utes of the mailer)-.2 E 5(.F)
+-.55 G(ields are:)220.13 631.2 Q EP
+%%Page: 29 26
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-29)452.9 60 Q/F1 10/Times-Roman@0 SF -.15(Pa)157 96 S 51.87(th The).15
+F(pathname of the mailer)2.5 E 47.83(Flags Special)157 108 R
+(\215ags for this mailer)2.5 E 41.73(Sender A)157 120 R(re)2.5 E
+(writing set for sender addresses)-.25 E 31.17(Recipient A)157 132 R(re)2.5 E
+(writing set for recipient addresses)-.25 E(Ar)157 144 Q 49.13(gv An)-.18 F(ar)
+2.5 E(gument v)-.18 E(ector to pass to this mailer)-.15 E 55.61(Eol The)157 156
+R(end-of-line string for this mailer)2.5 E 35.62(Maxsize The)157 168 R
+(maximum message length to this mailer)2.5 E 32.27(Linelimit The)157 180 R
+(maximum line length in the message body)2.5 E 31.18(Directory The)157 192 R
+-.1(wo)2.5 G(rking directory for the mailer).1 E
+(Only the \214rst character of the \214eld name is check)117 208.2 Q(ed.)-.1 E
+1.144(The follo)142 224.4 R 1.144
+(wing \215ags may be set in the mailer description.)-.25 F(An)6.144 E 3.644(yo)
+-.15 G 1.144(ther \215ags may be used)409.994 224.4 R(freely to conditionally \
+assign headers to messages destined for particular mailers.)117 236.4 Q 15.56
+(aR)117 252.6 S(un Extended SMTP \(ESMTP\) protocol \(de\214ned in RFCs 1425, \
+1426, and 1427\).)143.67 252.6 Q 15(bF)117 268.8 S .674
+(orce a blank line on the end of a message.)142.41 268.8 R .674
+(This is intended to w)5.674 F .675(ork around some stupid)-.1 F -.15(ve)137
+280.8 S .852(rsions of /bin/mail that require a blank line, b).15 F .851
+(ut do not pro)-.2 F .851(vide it themselv)-.15 F 3.351(es. It)-.15 F -.1(wo)
+3.351 G(uld).1 E(not normally be used on netw)137 292.8 Q(ork mail.)-.1 E 15.56
+(cD)117 309 S 4.165(on)144.22 309 S 1.665(ot include comments in addresses.)
+158.385 309 R 1.665(This should only be used if you ha)6.665 F 1.966 -.15(ve t)
+-.2 H 4.166(ow).15 G(ork)490.67 309 Q
+(around a remote mailer that gets confused by comments.)137 321 Q 13.33(CI)117
+337.2 S 3.06(fm)140.33 337.2 S .56(ail is)154.5 337.2 R/F2 10/Times-Italic@0 SF
+-.37(re)3.06 G(ceived).37 E F1 .56(from a mailer with this \215ag set, an)3.06
+F 3.06(ya)-.15 G .56(ddresses in the header that do not)367.33 337.2 R(ha)137
+349.2 Q .33 -.15(ve a)-.2 H 2.53(na).15 G 2.53(ts)174.47 349.2 S .03
+(ign \(\231@\232\) after being re)183.67 349.2 R .031
+(written by ruleset three will ha)-.25 F .331 -.15(ve t)-.2 H .031
+(he \231@domain\232 clause).15 F(from the sender tack)137 361.2 Q(ed on.)-.1 E
+(This allo)5 E(ws mail with headers of the form:)-.25 E(From: usera@hosta)177
+377.4 Q -.8(To)177 389.4 S 2.5(:u).8 G(serb@hostb, userc)197.59 389.4 Q
+(to be re)137 405.6 Q(written as:)-.25 E(From: usera@hosta)177 421.8 Q -.8(To)
+177 433.8 S 2.5(:u).8 G(serb@hostb, userc@hosta)197.59 433.8 Q(automatically)
+137 450 Q(.)-.65 E 12.78(DT)117 466.2 S(his mailer w)143.11 466.2 Q
+(ants a \231Date:\232 header line.)-.1 E 15.56(eT)117 482.4 S .563
+(his mailer is e)143.11 482.4 R(xpensi)-.15 E .862 -.15(ve t)-.25 H 3.062(oc)
+.15 G .562(onnect to, so try to a)253.972 482.4 R -.2(vo)-.2 G .562
+(id connecting normally; an).2 F 3.062(yn)-.15 G(ecessary)470.13 482.4 Q
+(connection will occur during a queue run.)137 494.4 Q 13.89(EE)117 510.6 S
+(scape lines be)143.11 510.6 Q
+(ginning with \231From\232 in the message with a `>' sign.)-.15 E 16.67(fT)117
+526.8 S .968(he mailer w)143.11 526.8 R .968(ants a)-.1 F F0<ad66>3.469 E F2
+(fr)3.469 E(om)-.45 E F1 .969(\215ag, b)3.469 F .969(ut only if this is a netw)
+-.2 F .969(ork forw)-.1 F .969(ard operation \(i.e., the)-.1 F(mailer will gi)
+137 538.8 Q .3 -.15(ve a)-.25 H 2.5(ne).15 G(rror if the e)218.81 538.8 Q -.15
+(xe)-.15 G(cuting user does not ha).15 E .3 -.15(ve s)-.2 H
+(pecial permissions\).).15 E 14.44(FT)117 555 S(his mailer w)143.11 555 Q
+(ants a \231From:\232 header line.)-.1 E 15(gN)117 571.2 S(ormally)144.22 571.2
+Q(,)-.65 E F2(sendmail)3.53 E F1 1.029
+(sends internally generated email \(e.g., error messages\) using the null)3.529
+F .005(return address)137 585.2 R/F3 7/Times-Roman@0 SF(9)193.375 581.2 Q F1
+.005(as required by RFC 1123.)199.38 585.2 R(Ho)5.006 E(we)-.25 E -.15(ve)-.25
+G .806 -.4(r, s).15 H .006(ome mailers don').4 F 2.506(ta)-.18 G .006
+(ccept a null return)431.502 585.2 R 3.718(address. If)137 597.2 R(necessary)
+3.718 E 3.718(,y)-.65 G 1.218(ou can set the)235.524 597.2 R F0(g)3.718 E F1
+1.218(\215ag to pre)3.718 F -.15(ve)-.25 G(nt).15 E F2(sendmail)3.718 E F1
+1.218(from obe)3.718 F 1.218(ying the stan-)-.15 F .601
+(dards; error messages will be sent as from the MAILER-D)137 609.2 R .602
+(AEMON \(actually)-.4 F 3.102(,t)-.65 G .602(he v)458.616 609.2 R .602(alue of)
+-.25 F(the)137 621.2 Q F0($n)2.5 E F1(macro\).)2.5 E 15(hU)117 637.4 S
+(pper case should be preserv)144.22 637.4 Q(ed in host names for this mailer)
+-.15 E(.)-.55 E 16.67(IT)117 653.6 S .093
+(his mailer will be speaking SMTP to another)143.11 653.6 R F2(sendmail)2.593 E
+F1 2.592<8a61>2.592 G 2.592(ss)381.248 653.6 S .092
+(uch it can use special proto-)391.62 653.6 R .318(col features.)137 665.6 R
+.319(This option is not required \(i.e., if this option is omitted the transmi\
+ssion will)5.318 F(still operate successfully)137 677.6 Q 2.5(,a)-.65 G
+(lthough perhaps not as ef)244.11 677.6 Q(\214ciently as possible\).)-.25 E .32
+LW 76 687.2 72 687.2 DL 80 687.2 76 687.2 DL 84 687.2 80 687.2 DL 88 687.2 84
+687.2 DL 92 687.2 88 687.2 DL 96 687.2 92 687.2 DL 100 687.2 96 687.2 DL 104
+687.2 100 687.2 DL 108 687.2 104 687.2 DL 112 687.2 108 687.2 DL 116 687.2 112
+687.2 DL 120 687.2 116 687.2 DL 124 687.2 120 687.2 DL 128 687.2 124 687.2 DL
+132 687.2 128 687.2 DL 136 687.2 132 687.2 DL 140 687.2 136 687.2 DL 144 687.2
+140 687.2 DL 148 687.2 144 687.2 DL 152 687.2 148 687.2 DL 156 687.2 152 687.2
+DL 160 687.2 156 687.2 DL 164 687.2 160 687.2 DL 168 687.2 164 687.2 DL 172
+687.2 168 687.2 DL 176 687.2 172 687.2 DL 180 687.2 176 687.2 DL 184 687.2 180
+687.2 DL 188 687.2 184 687.2 DL 192 687.2 188 687.2 DL 196 687.2 192 687.2 DL
+200 687.2 196 687.2 DL 204 687.2 200 687.2 DL 208 687.2 204 687.2 DL 212 687.2
+208 687.2 DL 216 687.2 212 687.2 DL/F4 5/Times-Roman@0 SF(9)93.6 697.6 Q/F5 8
+/Times-Roman@0 SF(Actually)3.2 I 2(,t)-.52 G(his only applies to SMTP)129.356
+700.8 Q 2(,w)-.888 G(hich uses the `)219.588 700.8 Q(`MAIL FR)-.592 E(OM:<>')
+-.32 E 2('c)-.592 G(ommand.)333.98 700.8 Q EP
+%%Page: 30 27
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-30 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 17.22(lT)117 96
+S(his mailer is local \(i.e., \214nal deli)143.11 96 Q -.15(ve)-.25 G
+(ry will be performed\).).15 E 13.89(LL)117 112.2 S .69
+(imit the line lengths as speci\214ed in RFC821.)143.11 112.2 R .69
+(This deprecated option should be replaced)5.69 F(by the)137 124.2 Q F0(L=)2.5
+E F1(mail declaration.)2.5 E -.15(Fo)5 G 2.5(rh).15 G(istoric reasons, the)
+272.54 124.2 Q F0(L)2.5 E F1(\215ag also sets the)2.5 E F0(7)2.5 E F1(\215ag.)
+2.5 E 12.22(mT)117 140.4 S 1.273
+(his mailer can send to multiple users on the same host in one transaction.)
+143.11 140.4 R 1.274(When a)6.273 F F0($u)3.774 E F1 .622(macro occurs in the)
+137 152.4 R/F2 10/Times-Italic@0 SF(ar)3.122 E(gv)-.37 E F1 .621
+(part of the mailer de\214nition, that \214eld will be repeated as neces-)3.121
+F(sary for all qualifying users.)137 164.4 Q 11.11(MT)117 180.6 S(his mailer w)
+143.11 180.6 Q(ants a \231Message-Id:\232 header line.)-.1 E 15(nD)117 196.8 S
+2.5(on)144.22 196.8 S
+(ot insert a UNIX-style \231From\232 line on the front of the message.)156.72
+196.8 Q 15(pU)117 213 S .701(se the route-addr style re)144.22 213 R -.15(ve)
+-.25 G .702(rse-path in the SMTP \231MAIL FR).15 F .702
+(OM:\232 command rather than)-.4 F .421
+(just the return address; although this is required in RFC821 section 3.1, man)
+137 225 R 2.921(yh)-.15 G .421(osts do not)459.818 225 R(process re)137 237 Q
+-.15(ve)-.25 G(rse-paths properly).15 E 5(.R)-.65 G -2.15 -.25(ev e)272.3 237 T
+(rse-paths are of).25 E(\214cially discouraged by RFC 1123.)-.25 E 14.44(PT)117
+253.2 S(his mailer w)143.11 253.2 Q(ants a \231Return-P)-.1 E(ath:\232 line.)
+-.15 E 16.67(rS)117 269.4 S(ame as)142.56 269.4 Q F0(f)2.5 E F1 2.5(,b)C
+(ut sends a)185.68 269.4 Q F0<ad72>2.5 E F1(\215ag.)2.5 E 16.11(sS)117 285.6 S
+(trip quote characters of)142.56 285.6 Q 2.5(fo)-.25 G 2.5(ft)245.61 285.6 S
+(he address before calling the mailer)254.22 285.6 Q(.)-.55 E 14.44(SD)117
+301.8 S(on')144.22 301.8 Q 3.442(tr)-.18 G .942
+(eset the userid before calling the mailer)166.922 301.8 R 5.943(.T)-.55 G .943
+(his w)344.319 301.8 R .943(ould be used in a secure en)-.1 F(viron-)-.4 E .491
+(ment where)137 313.8 R F2(sendmail)2.991 E F1 .491(ran as root.)2.991 F .491
+(This could be used to a)5.491 F -.2(vo)-.2 G .49(id for).2 F .49
+(ged addresses.)-.18 F .49(This \215ag)5.49 F(is suppressed if gi)137 325.8 Q
+-.15(ve)-.25 G 2.5(nf).15 G(rom an \231unsafe\232 en)228.81 325.8 Q
+(vironment \(e.g, a user')-.4 E 2.5(sm)-.55 G(ail.cf \214le\).)410.31 325.8 Q
+15(uU)117 342 S(pper case should be preserv)144.22 342 Q
+(ed in user names for this mailer)-.15 E(.)-.55 E 12.78(UT)117 358.2 S 2.996
+(his mailer w)143.11 358.2 R 2.996
+(ants Unix-style \231From\232 lines with the ugly UUCP-style \231remote from)
+-.1 F(<host>\232 on the end.)137 370.2 Q 15(xT)117 386.4 S(his mailer w)143.11
+386.4 Q(ants a \231Full-Name:\232 header line.)-.1 E 12.78(XT)117 402.6 S 1.22
+(his mailer w)143.11 402.6 R 1.22
+(ant to use the hidden dot algorithm as speci\214ed in RFC821; basically)-.1 F
+3.72(,a)-.65 G -.15(ny)494.15 402.6 S .224(line be)137 414.6 R .224
+(ginning with a dot will ha)-.15 F .525 -.15(ve a)-.2 H 2.725(ne).15 G .225
+(xtra dot prepended \(to be stripped at the other end\).)296.465 414.6 R .525(\
+This insures that lines in the message containing a dot will not terminate the\
+ message pre-)137 426.6 R(maturely)137 438.6 Q(.)-.65 E 15(7S)117 454.8 S .152
+(trip all output to se)142.56 454.8 R -.15(ve)-.25 G 2.652(nb).15 G 2.652
+(its. This)240.42 454.8 R .152(is the def)2.652 F .152(ault if the)-.1 F F0(L)
+2.652 E F1 .152(\215ag is set.)2.652 F .152(Note that setting this is)5.152 F
+.079(not suf)137 466.8 R .079
+(\214cient to get full eight bit data passed through)-.25 F F2(sendmail)2.579 E
+F1 5.079(.I)C 2.579(ft)398.439 466.8 S(he)407.128 466.8 Q F0(7)2.579 E F1 .079
+(option is set, this is)2.579 F(essentially al)137 478.8 Q -.1(wa)-.1 G
+(ys set, since the eighth bit w).1 E(as stripped on input.)-.1 E 2.122(The mai\
+ler with the special name \231error\232 can be used to generate a user error)
+142 495 R 7.122(.T)-.55 G(he)494.56 495 Q .247
+(\(optional\) host \214eld is an e)117 507 R .247
+(xit status to be returned, and the user \214eld is a message to be printed.)
+-.15 F .336(The e)117 519 R .336(xit status may be numeric or one of the v)-.15
+F .337(alues USA)-.25 F .337(GE, NOUSER, NOHOST)-.4 F 2.837(,U)-.74 G -.35(NA)
+465.4 519 S -1.35(VA)-1 G(IL-)1.35 E .828(ABLE, SOFTW)117 531 R .828
+(ARE, TEMPF)-1.2 F .828(AIL, PR)-.74 F -1.88 -.4(OT O)-.4 H .828
+(COL, or CONFIG to return the corresponding EX_).4 F -.15(ex)117 543 S
+(it code.).15 E -.15(Fo)5 G 2.5(re).15 G(xample, the entry:)181.26 543 Q
+($#error $@ NOHOST $: Host unkno)157 559.2 Q(wn in this domain)-.25 E .261(on \
+the RHS of a rule will cause the speci\214ed error to be generated and the \
+\231Host unkno)117 575.4 R .262(wn\232 e)-.25 F(xit)-.15 E
+(status to be returned if the LHS matches.)117 587.4 Q
+(This mailer is only functional in ruleset zero.)5 E 1.564
+(The mailer named \231local\232)142 603.6 R F2(must)4.064 E F1 1.564
+(be de\214ned in e)4.064 F -.15(ve)-.25 G 1.563(ry con\214guration \214le.).15
+F 1.563(This is used to)6.563 F(deli)117 615.6 Q -.15(ve)-.25 G 4.038(rl).15 G
+1.538(ocal mail, and is treated specially in se)151.188 615.6 R -.15(ve)-.25 G
+1.539(ral w).15 F 4.039(ays. Additionally)-.1 F 4.039(,t)-.65 G 1.539
+(hree other mailers)428.722 615.6 R 1.367(named \231prog\232, \231*\214le*\232\
+, and \231*include*\232 may be de\214ned to tune the deli)117 627.6 R -.15(ve)
+-.25 G 1.367(ry of messages to).15 F
+(programs, \214les, and :include: lists respecti)117 639.6 Q -.15(ve)-.25 G(ly)
+.15 E 5(.T)-.65 G(he)315.38 639.6 Q 2.5(yd)-.15 G(ef)337.17 639.6 Q(ault to:)
+-.1 E(Mprog, P=/bin/sh, F=lsD, A=sh \255c $u)157 655.8 Q(M*\214le*, P=/de)157
+667.8 Q(v/null, F=lsDFMPEu, A=FILE)-.25 E(M*include*, P=/de)157 679.8 Q
+(v/null, F=su, A=INCLUDE)-.25 E 1.263(The Sender and Recipient re)142 700.2 R
+1.263(writing sets may either be a simple inte)-.25 F 1.264(ger or may be tw)
+-.15 F(o)-.1 E(inte)117 712.2 Q .047
+(gers separated by a slash; if so, the \214rst re)-.15 F .046
+(writing set is applied to en)-.25 F -.15(ve)-.4 G .046(lope addresses and the)
+.15 F(second is applied to headers.)117 724.2 Q EP
+%%Page: 31 28
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-31)452.9 60 Q/F1 10/Times-Roman@0 SF 1.258
+(The Directory is actually a colon-separated path of directories to try)142 96
+R 6.259(.F)-.65 G 1.259(or e)439.702 96 R 1.259(xample, the)-.15 F .144
+(de\214nition \231D=$z:/\232 \214rst tries to e)117 108 R -.15(xe)-.15 G .143
+(cute in the recipient').15 F 2.643(sh)-.55 G .143
+(ome directory; if that is not a)353.332 108 R -.25(va)-.2 G(ilable,).25 E .78
+(it tries to e)117 120 R -.15(xe)-.15 G .78
+(cute in the root of the \214lesystem.).15 F .781
+(This is intended to be used only on the \231prog\232)5.781 F(mailer)117 132 Q
+2.899(,s)-.4 G .398(ince some shells \(such as)151.439 132 R/F2 10
+/Times-Italic@0 SF(csh)2.898 E F1 2.898(\)r)C .398(efuse to e)279.358 132 R
+-.15(xe)-.15 G .398(cute if the).15 F 2.898(yc)-.15 G .398
+(annot read the home directory)380.588 132 R(.)-.65 E .416
+(Since the queue directory is not normally readable by normal users)117 144 R
+F2(csh)2.916 E F1 .416(scripts as recipients can)2.916 F -.1(fa)117 156 S(il.)
+.1 E F0 2.5(5.1.5. H)102 180 R 2.5<8a64>2.5 G(e\214ne header)157.84 180 Q F1
+.198(The format of the header lines that sendmail inserts into the message are\
+ de\214ned by the)142 196.2 R F0(H)2.698 E F1 2.5(line. The)117 208.2 R
+(syntax of this line is:)2.5 E F0(H)157 224.4 Q F1([)A F0(?)A F2(m\215a)A(gs)
+-.1 E F0(?)A F1(])A F2(hname)A F0(:)A F2(htemplate)2.5 E F1 .691(Continuation \
+lines in this spec are re\215ected directly into the outgoing message.)117
+240.6 R(The)5.691 E F2(htemplate)3.191 E F1 1.567(is macro e)117 252.6 R 1.567
+(xpanded before insertion into the message.)-.15 F 1.567(If the)6.567 F F2
+(m\215a)4.067 E(gs)-.1 E F1 1.567(\(surrounded by question)4.067 F .219(marks\
+\) are speci\214ed, at least one of the speci\214ed \215ags must be stated in \
+the mailer de\214nition for)117 264.6 R .094
+(this header to be automatically output.)117 276.6 R .093
+(If one of these headers is in the input it is re\215ected to the)5.093 F
+(output re)117 288.6 Q -.05(ga)-.15 G(rdless of these \215ags.).05 E
+(Some headers ha)142 304.8 Q .3 -.15(ve s)-.2 H
+(pecial semantics that will be described belo).15 E -.65(w.)-.25 G F0 2.5
+(5.1.6. O)102 328.8 R 2.5<8a73>2.5 G(et option)156.17 328.8 Q F1 .045(There ar\
+e a number of \231random\232 options that can be set from a con\214guration \
+\214le.)142 345 R(Options)5.046 E(are represented by single characters.)117 357
+Q(The syntax of this line is:)5 E F0(O)157 373.2 Q F2 1.666(ov)C(alue)-1.666 E
+F1 1.055(This sets option)117 389.4 R F2(o)3.555 E F1 1.055(to be)3.555 F F2
+(value)3.555 E F1 6.055(.D)C 1.054(epending on the option,)256.325 389.4 R F2
+(value)3.554 E F1 1.054(may be a string, an inte)3.554 F(ger)-.15 E 3.554(,a)
+-.4 G(boolean \(with le)117 401.4 Q -.05(ga)-.15 G 2.5(lv).05 G
+(alues \231t\232, \231T\232, \231f\232, or \231F\232; the def)201.26 401.4 Q
+(ault is TR)-.1 E(UE\), or a time interv)-.4 E(al.)-.25 E
+(The options supported are:)142 417.6 Q(a)117 433.8 Q F2(N)A F1 .655(If set, w)
+189 433.8 R .655(ait up to)-.1 F F2(N)3.155 E F1 .655
+(minutes for an \231@:@\232 entry to e)3.155 F .655(xist in the alias database)
+-.15 F .475(before starting up.)189 445.8 R .474(If it does not appear in)5.475
+F F2(N)2.974 E F1 .474(minutes, reb)2.974 F .474(uild the database \(if)-.2 F
+(the)189 457.8 Q F0(D)2.5 E F1(option is also set\) or issue a w)2.5 E(arning.)
+-.1 E(A)117 474 Q F2 .506(spec, spec, ...)B F1 .506
+(Specify possible alias \214le\(s\).)190.012 474 R(Each)5.506 E F2(spec)3.006 E
+F1 .507(should be in the format `)3.006 F(`)-.74 E F2(class)A F0(:)A F2(\214le)
+3.007 E F1 -.74('')C(where)189 486 Q F2(class)2.948 E F0(:)A F1 .447
+(is optional and def)2.948 F .447(aults to `)-.1 F(`implicit')-.74 E 2.947
+('. Depending)-.74 F .447(on ho)2.947 F(w)-.25 E F0(send-)2.947 E(mail)189 498
+Q F1 1.224(is compiled, v)3.724 F 1.224
+(alid classes are \231implicit\232 \(search through a compiled-in)-.25 F .193
+(list of alias \214le types, for back compatibility\), \231hash\232 \(if)189
+510 R/F3 9/Times-Roman@0 SF(NEWDB)2.693 E F1 .193(is speci\214ed\),)2.693 F
+.881(\231dbm\232 \(if)189 522 R F3(NDBM)3.381 E F1 .882
+(is speci\214ed\), \231stab\232 \(internal symbol table \212 not normally)3.382
+F .476(used unless you ha)189 534 R .776 -.15(ve n)-.2 H 2.976(oo).15 G .475
+(ther database lookup\), or \231nis\232 \(if)295.74 534 R F3(NIS)2.975 E F1
+.475(is speci\214ed\).)2.975 F(If a list of)189 546 Q F2(spec)2.5 E F1 2.5(sa)C
+(re pro)259.26 546 Q(vided,)-.15 E F2(sendmail)2.5 E F1(searches them in order)
+2.5 E(.)-.55 E(b)117 562.2 Q F2(N)A F1(/)A F2(M)A F1 1.588(Insist on at least)
+189 562.2 R F2(N)4.088 E F1 1.589
+(blocks free on the \214lesystem that holds the queue \214les)4.088 F .19
+(before accepting email via SMTP)189 574.2 R 5.19(.I)-1.11 G 2.69(ft)334.09
+574.2 S .19(here is insuf)342.89 574.2 R .19(\214cient space)-.25 F F2
+(sendmail)2.69 E F1(gi)2.69 E -.15(ve)-.25 G(s).15 E 3.67(a4)189 586.2 S 1.17
+(52 response to the MAIL command.)202.11 586.2 R 1.17(This in)6.17 F 1.17
+(vites the sender to try ag)-.4 F(ain)-.05 E(later)189 598.2 Q 5.987(.T)-.55 G
+.987(he optional)220.817 598.2 R F2(M)3.487 E F1 .987
+(is a maximum message size adv)3.487 F .986(ertised in the ESMTP)-.15 F
+(EHLO response.)189 610.2 Q(It is currently otherwise unused.)5 E(B)117 626.4 Q
+F2(c)A F1 1.444(Set the blank substitution character to)189 626.4 R F2(c)3.945
+E F1 6.445(.U)C 1.445(nquoted spaces in addresses are)371.59 626.4 R
+(replaced by this character)189 638.4 Q 5(.D)-.55 G(ef)305.63 638.4 Q
+(aults to space \(i.e., no change is made\).)-.1 E 67.56(cI)117 654.6 S 3.893
+(fa)192.33 654.6 S 3.893(no)203.993 654.6 S 1.393(utgoing mailer is mark)
+217.886 654.6 R 1.393(ed as being e)-.1 F(xpensi)-.15 E -.15(ve)-.25 G 3.892
+(,d).15 G(on')415.296 654.6 Q 3.892(tc)-.18 G 1.392(onnect immedi-)439.558
+654.6 R(ately)189 666.6 Q 6.163(.T)-.65 G 1.164
+(his requires that queueing be compiled in, since it will depend on a)222.563
+666.6 R(queue run process to actually send the mail.)189 678.6 Q(C)117 694.8 Q
+F2(N)A F1 1.49(Checkpoints the queue e)189 694.8 R -.15(ve)-.25 G(ry).15 E F2
+(N)3.99 E F1(\(def)3.99 E 1.49(ault 10\) addresses sent.)-.1 F 1.49
+(If your system)6.49 F .785(crashes during deli)189 706.8 R -.15(ve)-.25 G .785
+(ry to a lar).15 F .785(ge list, this pre)-.18 F -.15(ve)-.25 G .785
+(nts retransmission to an).15 F 3.285(yb)-.15 G(ut)496.22 706.8 Q
+(the last recipients.)189 718.8 Q EP
+%%Page: 32 29
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-32 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(d)117 96 Q/F2 10
+/Times-Italic@0 SF(x)A F1(Deli)189 96 Q -.15(ve)-.25 G 2.5(ri).15 G 2.5(nm)
+223.87 96 S(ode)239.15 96 Q F2(x)2.5 E F1 5(.L)C -2.25 -.15(eg a)274.14 96 T
+2.5(lm).15 G(odes are:)300.88 96 Q 17.22(iD)229 112.2 S(eli)256.22 112.2 Q -.15
+(ve)-.25 G 2.5(ri).15 G(nteracti)283.87 112.2 Q -.15(ve)-.25 G
+(ly \(synchronously\)).15 E 15(bD)229 124.2 S(eli)256.22 124.2 Q -.15(ve)-.25 G
+2.5(ri).15 G 2.5(nb)283.87 124.2 S(ackground \(asynchronously\))296.37 124.2 Q
+15(qJ)229 136.2 S(ust queue the message \(deli)252.89 136.2 Q -.15(ve)-.25 G
+2.5(rd).15 G(uring queue run\))382.74 136.2 Q(Def)189 152.4 Q 1.32(aults to `)
+-.1 F(`b')-.74 E 3.82('i)-.74 G 3.82(fn)261.64 152.4 S 3.82(oo)273.79 152.4 S
+1.32(ption is speci\214ed, `)287.61 152.4 R(`i')-.74 E 3.82('i)-.74 G 3.82(fi)
+385.57 152.4 S 3.82(ti)395.5 152.4 S 3.82(ss)404.88 152.4 S 1.32(peci\214ed b)
+416.48 152.4 R 1.32(ut gi)-.2 F -.15(ve)-.25 G 3.82(nn).15 G(o)499 152.4 Q(ar)
+189 164.4 Q(gument \(i.e., `)-.18 E(`Od')-.74 E 2.5('i)-.74 G 2.5(se)278.98
+164.4 S(qui)289.81 164.4 Q -.25(va)-.25 G(lent to `).25 E(`Odi')-.74 E('\).)
+-.74 E 64.78(DI)117 180.6 S 2.735(fs)192.33 180.6 S .235(et, reb)202.285 180.6
+R .236(uild the alias database if necessary and possible.)-.2 F .236
+(If this option is not)5.236 F(set,)189 192.6 Q F2(sendmail)3.385 E F1 .885
+(will ne)3.385 F -.15(ve)-.25 G 3.385(rr).15 G(eb)292.96 192.6 Q .885
+(uild the alias database unless e)-.2 F .885(xplicitly requested)-.15 F(using)
+189 204.6 Q F0(\255bi)2.5 E F1(.)A(e)117 220.8 Q F2(x)A F1
+(Dispose of errors using mode)189 220.8 Q F2(x)2.5 E F1 5(.T)C(he v)327.31
+220.8 Q(alues for)-.25 E F2(x)2.5 E F1(are:)2.5 E 15(pP)229 237 S
+(rint error messages \(def)254.56 237 Q(ault\))-.1 E 15(qN)229 249 S 2.5(om)
+256.22 249 S(essages, just gi)271.5 249 Q .3 -.15(ve ex)-.25 H(it status).15 E
+12.22(mM)229 261 S(ail back errors)257.89 261 Q 12.78(wW)229 273 S
+(rite back errors \(mail if user not logged in\))258.44 273 Q 15.56(eM)229 285
+S(ail back errors and gi)257.89 285 Q .3 -.15(ve z)-.25 H(ero e).15 E
+(xit stat al)-.15 E -.1(wa)-.1 G(ys).1 E(E)117 305.4 Q F2(\214le/messa)A -.1
+(ge)-.1 G F1 .549(Prepend error messages with the indicated message.)189 305.4
+R .549(If it be)5.549 F .55(gins with a slash,)-.15 F .107(it is assumed to be\
+ the pathname of a \214le containing a message \(this is the rec-)189 317.4 R
+1.316(ommended setting\).)189 329.4 R 1.316
+(Otherwise, it is a literal message.)6.316 F 1.317(The error \214le might)6.317
+F .99
+(contain the name, email address, and/or phone number of a local postmaster)189
+341.4 R .428(who could pro)189 353.4 R .428(vide assistance in to end users.)
+-.15 F .429(If the option is missing or null,)5.429 F .342
+(or if it names a \214le which does not e)189 365.4 R .342
+(xist or which is not readable, no message)-.15 F(is printed.)189 377.4 Q 68.67
+(fS)117 393.6 S -2.25 -.2(av e)194.56 393.6 T 2.399
+(Unix-style \231From\232 lines at the front of headers.)5.099 F 2.399
+(Normally the)7.399 F 4.9(ya)-.15 G(re)496.23 393.6 Q
+(assumed redundant and discarded.)189 405.6 Q(F)117 421.8 Q F2(mode)A F1
+(The \214le mode for queue \214les.)189 421.8 Q(g)117 438 Q F2(n)A F1
+(Set the def)189 438 Q(ault group id for mailers to run in to)-.1 E F2(n)2.5 E
+F1 5(.D)C(ef)397.77 438 Q(aults to 1.)-.1 E 64.78(GA)117 454.2 S(llo)196.22
+454.2 Q 3.492(wf)-.25 G .992(uzzy matching on the GECOS \214eld.)220.572 454.2
+R .991(If this \215ag is set, and the usual)5.991 F .793(user name lookups f)
+189 466.2 R .793(ail \(that is, there is no alias with this name and a)-.1 F F2
+-.1(ge)3.294 G(tpw-).1 E(nam)189 478.2 Q F1 -.1(fa)3.702 G 1.202
+(ils\), sequentially search the passw).1 F 1.201
+(ord \214le for a matching entry in the)-.1 F 1.446(GECOS \214eld.)189 490.2 R
+1.446(This also requires that MA)6.446 F 1.446(TCHGECOS be turned on during)
+-1.11 F 2.5(compilation. This)189 502.2 R(option is not recommended.)2.5 E(h)
+117 518.4 Q F2(N)A F1 1.274(The maximum hop count.)189 518.4 R 1.274
+(Messages that ha)6.274 F 1.574 -.15(ve b)-.2 H 1.273(een processed more than)
+.15 F F2(N)3.773 E F1(times are assumed to be in a loop and are rejected.)189
+530.4 Q(Def)5 E(aults to 25.)-.1 E(H)117 546.6 Q F2(\214le)A F1
+(Specify the help \214le for SMTP)189 546.6 Q(.)-1.11 E 69.22(iI)117 562.8 S
+1.014(gnore dots in incoming messages.)192.33 562.8 R 1.014(This is al)6.014 F
+-.1(wa)-.1 G 1.014(ys disabled \(that is, dots are).1 F(al)189 574.8 Q -.1(wa)
+-.1 G(ys accepted\) when reading SMTP mail.).1 E 68.67(II)117 591 S .62
+(nsist that the BIND name serv)192.33 591 R .619(er be running to resolv)-.15 F
+3.119(eh)-.15 G .619(ost names.)421.524 591 R .619(If this is)5.619 F .945
+(not set and the name serv)189 603 R .945(er is not running, the)-.15 F F2
+(/etc/hosts)3.445 E F1 .945(\214le will be consid-)3.445 F .188(ered complete.)
+189 615 R .188(In general, you do w)5.188 F .188
+(ant to set this option if your)-.1 F F2(/etc/hosts)2.687 E F1(\214le)2.687 E
+.412(does not include all hosts kno)189 627 R .412
+(wn to you or if you are using the MX \(mail for)-.25 F(-)-.2 E -.1(wa)189 639
+S .315(rding\) feature of the BIND name serv).1 F(er)-.15 E 5.315(.T)-.55 G
+.315(he name serv)373.955 639 R .314(er will still be con-)-.15 F 1.522
+(sulted e)189 651 R -.15(ve)-.25 G 4.022(ni).15 G 4.022(ft)242.194 651 S 1.523
+(his option is not set, b)252.326 651 R(ut)-.2 E F2(sendmail)4.023 E F1 1.523
+(will feel free to resort to)4.023 F(reading)189 663 Q F2(/etc/hosts)3.053 E F1
+.553(if the name serv)3.053 F .552(er is not a)-.15 F -.25(va)-.2 G 3.052
+(ilable. Thus,).25 F .552(you should)3.052 F F2(ne)3.052 E(ver)-.15 E F1
+(set this option if you do not run the name serv)189 675 Q(er)-.15 E(.)-.55 E
+69.22(jI)117 691.2 S 3.128(fs)192.33 691.2 S .628
+(et, send error messages in MIME format \(see RFC1341 and RFC1344 for)202.678
+691.2 R(details\).)189 703.2 Q EP
+%%Page: 33 30
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-33)452.9 60 Q/F1 10/Times-Roman@0 SF(J)117 96 Q/F2 10/Times-Italic@0 SF
+(path)A F1 4.923(Set the path for searching for users' .forw)189 96 R 4.923
+(ard \214les.)-.1 F 4.922(The def)9.922 F 4.922(ault is)-.1 F(\231$z/.forw)189
+108 Q 2.868(ard\232. Some)-.1 F .368
+(sites that use the automounter may prefer to change this)2.868 F .676
+(to \231/v)189 120 R(ar/forw)-.25 E .676
+(ard/$u\232 to search a \214le with the same name as the user in a sys-)-.1 F
+.924(tem directory)189 132 R 5.924(.I)-.65 G 3.424(tc)254.628 132 S .924
+(an also be set to a sequence of paths separated by colons;)265.272 132 R F2
+(sendmail)189 144 Q F1 .645
+(stops at the \214rst \214le it can successfully and safely open.)3.146 F -.15
+(Fo)5.645 G 3.145(re).15 G(xam-)483.45 144 Q 1.535(ple, \231/v)189 156 R
+(ar/forw)-.25 E(ard/$u:$z/.forw)-.1 E 1.535(ard\232 will search \214rst in /v)
+-.1 F(ar/forw)-.25 E(ard/)-.1 E F2(username)A F1(and then in)189 168 Q F2
+(~username)2.5 E F1(/.forw)A(ard \(b)-.1 E
+(ut only if the \214rst \214le does not e)-.2 E(xist\).)-.15 E(k)117 184.2 Q F2
+(N)A F1 .196
+(The maximum number of open connections that will be cached at a time.)189
+184.2 R(The)5.196 E(def)189 196.2 Q .566(ault is one.)-.1 F .567
+(This delays closing the the current connection until either this)5.566 F(in)
+189 208.2 Q -.2(vo)-.4 G .516
+(cation of sendmail needs to connect to another host or it terminates.).2 F
+(Set-)5.515 E 1.958(ting it to zero def)189 220.2 R 1.958
+(aults to the old beha)-.1 F(vior)-.2 E 4.459(,t)-.4 G 1.959
+(hat is, connections are closed)379.244 220.2 R(immediately)189 232.2 Q(.)-.65
+E(K)117 248.4 Q F2(timeout)A F1 .883
+(The maximum amount of time a cached connection will be permitted to idle)189
+248.4 R 2.746(without acti)189 260.4 R(vity)-.25 E 7.746(.I)-.65 G 5.246(ft)
+267.482 260.4 S 2.746(his time is e)278.838 260.4 R 2.746
+(xceeded, the connection is immediately)-.15 F 4.423(closed. This)189 272.4 R
+-.25(va)4.423 G 1.922(lue should be small \(on the order of ten minutes\).).25
+F(Before)6.922 E F0(sendmail)189 284.4 Q F1 1.083
+(uses a cached connection, it al)3.583 F -.1(wa)-.1 G 1.084
+(ys sends a NOOP \(no operation\)).1 F 2.058
+(command to check the connection; if this f)189 296.4 R 2.058
+(ails, it reopens the connection.)-.1 F .478(This k)189 308.4 R .478
+(eeps your end from f)-.1 F .478(ailing if the other end times out.)-.1 F .478
+(The point of this)5.478 F 3.099(option is to be a good netw)189 320.4 R 3.099
+(ork neighbor and a)-.1 F -.2(vo)-.2 G 3.099(id using up e).2 F(xcessi)-.15 E
+-.15(ve)-.25 G(resources on the other end.)189 332.4 Q(The def)5 E
+(ault is \214v)-.1 E 2.5(em)-.15 G(inutes.)383.99 332.4 Q 69.22(lI)117 348.6 S
+3.14(ft)192.33 348.6 S .64(here is an \231Errors-T)201.58 348.6 R .64
+(o:\232 header)-.8 F 3.14(,s)-.4 G .64
+(end error messages to the addresses listed)333.53 348.6 R 3.951(there. The)189
+360.6 R 3.951(yn)-.15 G 1.451(ormally go to the en)247.292 360.6 R -.15(ve)-.4
+G 1.451(lope sender).15 F 6.451(.U)-.55 G 1.451(se of this option causes)
+405.428 360.6 R(sendmail to violate RFC 1123.)189 372.6 Q(L)117 388.8 Q F2(n)A
+F1(Set the def)189 388.8 Q(ault log le)-.1 E -.15(ve)-.25 G 2.5(lt).15 G(o)
+288.77 388.8 Q F2(n)2.5 E F1 5(.D)C(ef)315.99 388.8 Q(aults to 9.)-.1 E 64.22
+(mS)117 405 S(end to me too, e)194.56 405 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5
+(fIa)278.04 405 S 2.5(mi)294.14 405 S 2.5(na)307.2 405 S 2.5(na)319.14 405 S
+(lias e)331.08 405 Q(xpansion.)-.15 E(M)117 421.2 Q F2 1.666(xv)C(alue)-1.666 E
+F1 1.312(Set the macro)189 421.2 R F2(x)3.812 E F1(to)3.812 E F2(value)3.812 E
+F1 6.312(.T)C 1.312(his is intended only for use from the command)306.852 421.2
+R(line.)189 433.2 Q 67(nV)117 449.4 S(alidate the RHS of aliases when reb)
+195.11 449.4 Q(uilding the alias database.)-.2 E 67(oA)117 465.6 S 1.786
+(ssume that the headers may be in old format, i.e., spaces delimit names.)
+196.22 465.6 R .432(This actually turns on an adapti)189 477.6 R .733 -.15
+(ve a)-.25 H .433(lgorithm: if an).15 F 2.933(yr)-.15 G .433
+(ecipient address contains)403.154 477.6 R 5.09(ac)189 489.6 S 2.589
+(omma, parenthesis, or angle brack)202.97 489.6 R 2.589
+(et, it will be assumed that commas)-.1 F .484(already e)189 501.6 R 2.984
+(xist. If)-.15 F .485(this \215ag is not on, only commas delimit names.)2.984 F
+.485(Headers are)5.485 F(al)189 513.6 Q -.1(wa)-.1 G
+(ys output with commas between the names.).1 E(O)117 529.8 Q F2(options)A F1
+(Set serv)189 529.8 Q(er SMTP options.)-.15 E(The options are)5 E F2 -.1(ke)2.5
+G(y=value)-.2 E F1 2.5(pairs. Kno)2.5 F(wn k)-.25 E -.15(ey)-.1 G 2.5(sa).15 G
+(re:)488.82 529.8 Q 52.83(Port Name/number)229 546 R(of listening port \(def)
+2.5 E(aults to "smtp"\))-.1 E 48.95(Addr Address)229 558 R(mask \(def)2.5 E
+(aults IN)-.1 E(ADDR_ANY\))-.35 E -.15(Fa)229 570 S 41.31(mily Address).15 F
+-.1(fa)2.5 G(mily \(def).1 E(aults to INET\))-.1 E 44.5(Listen Size)229 582 R
+(of listen queue \(def)2.5 E(aults to 10\))-.1 E(The)189 598.2 Q F2(Addr)4.114
+E F1 1.614(ess mask may be a numeric address in dot notation or a netw)B(ork)
+-.1 E(name.)189 610.2 Q(p)117 626.4 Q F2(opt,opt,...)1.666 E F1 1.22
+(Set the pri)189 626.4 R -.25(va)-.25 G -.15(cy).25 G F2(opt)3.871 E F1 3.721
+(ions. `)B(`Pri)-.74 E -.25(va)-.25 G -.15(cy).25 G 2.701 -.74('' i).15 H 3.721
+(sr).74 G 1.221(eally a misnomer; man)351.854 626.4 R 3.721(yo)-.15 G 3.721(ft)
+460.468 626.4 S 1.221(hese are)470.299 626.4 R 2.419(just a w)189 638.4 R 2.418
+(ay of insisting on stricter adherence to the SMTP protocol.)-.1 F(The)7.418 E
+F2(opt)189 650.4 Q F1(ions can be selected from:)A EP
+%%Page: 34 31
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-34 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 40.26
+(public Allo)229 96 R 2.5(wo)-.25 G(pen access)329.01 96 Q 11.38
+(needmailhelo Insist)229 108 R(on HELO or EHLO command before MAIL)2.5 E(neede)
+229 120 Q 9.87(xpnhelo Insist)-.15 F(on HELO or EHLO command before EXPN)2.5 E
+(noe)229 132 Q 35.97(xpn Disallo)-.15 F 2.5(wE)-.25 G(XPN entirely)341.23 132 Q
+12.5(needvrfyhelo Insist)229 144 R(on HELO or EHLO command before VRFY)2.5 E
+(no)229 156 Q 38.75(vrfy Disallo)-.15 F 2.5(wV)-.25 G(RFY entirely)342.34 156 Q
+14.71(restrictmailq Restrict)229 168 R(mailq command)2.5 E(goa)229 180 Q -.1
+(wa)-.15 G 36.91(yD).1 G(isallo)303.98 180 Q 2.5(we)-.25 G
+(ssentially all SMTP status queries)339.56 180 Q 1.768(The \231goa)189 196.2 R
+-.1(wa)-.15 G 1.768(y\232 pseudo-\215ag sets all \215ags e).1 F 1.768
+(xcept \231restrictmailq\232.)-.15 F 1.768(If mailq is)6.768 F .688(restricted\
+, only people in the same group as the queue directory can print the)189 208.2
+R(queue.)189 220.2 Q(P)117 236.4 Q/F2 10/Times-Italic@0 SF(postmaster)A F1
+1.115(If set, copies of error messages will be sent to the named)189 236.4 R F2
+(postmaster)3.615 E F1 6.115(.O)C(nly)491.22 236.4 Q .398(the header of the f)
+189 248.4 R .398(ailed message is sent.)-.1 F .397
+(Since most errors are user problems,)5.398 F .563
+(this is probably not a good idea on lar)189 260.4 R .564(ge sites, and ar)-.18
+F .564(guably contains all sorts)-.18 F .05(of pri)189 272.4 R -.25(va)-.25 G
+.35 -.15(cy v).25 H .05(iolations, b).15 F .05
+(ut it seems to be popular with certain operating systems)-.2 F -.15(ve)189
+284.4 S(ndors.).15 E(q)117 300.6 Q F2(factor)A F1(Use)189 300.6 Q F2(factor)
+3.097 E F1 .597
+(as the multiplier in the map function to decide when to just queue)3.097 F
+.426(up jobs rather than run them.)189 312.6 R .425(This v)5.425 F .425
+(alue is di)-.25 F .425(vided by the dif)-.25 F .425(ference between)-.25 F
+1.063(the current load a)189 324.6 R -.15(ve)-.2 G 1.064(rage and the load a)
+.15 F -.15(ve)-.2 G 1.064(rage limit \().15 F F0(x)A F1 1.064
+(\215ag\) to determine the)3.564 F(maximum message priority that will be sent.)
+189 336.6 Q(Def)5 E(aults to 600000.)-.1 E(Q)117 352.8 Q F2(dir)A F1
+(Use the named)189 352.8 Q F2(dir)2.5 E F1(as the queue directory)2.5 E(.)-.65
+E(r)117 369 Q F2(timeouts)1.666 E F1 -.35(Ti)189 369 S 3.939(meout reads after)
+.35 F F2(time)6.438 E F1(interv)6.438 E 6.438(al. The)-.25 F F2(timeouts)6.438
+E F1(ar)6.438 E 3.938(gument is a list of)-.18 F F2 -.1(ke)189 381 S(ywor)-.2 E
+(d=value)-.37 E F1 3.61(pairs. The)3.61 F 1.11
+(recognized timeouts and their def)3.61 F 1.11(ault v)-.1 F 1.11(alues, and)
+-.25 F(their minimum v)189 393 Q
+(alues speci\214ed in RFC 1123 section 5.3.2 are:)-.25 E 23.6(initial w)229
+409.2 R(ait for initial greeting message [5m, 5m])-.1 E 29.72(helo reply)229
+421.2 R(to HELO or EHLO command [5m, none])2.5 E 29.16(mail reply)229 433.2 R
+(to MAIL command [10m, 5m])2.5 E 31.39(rcpt reply)229 445.2 R
+(to RCPT command [1h, 5m])2.5 E 16.94(datainit reply)229 457.2 R(to D)2.5 E
+-1.21 -1.11(AT A)-.4 H(command [5m, 2m])3.61 E 8.06(datablock data)229 469.2 R
+(block read [1h, 3m])2.5 E 12.5(data\214nal reply)229 481.2 R(to \214nal `)2.5
+E(`.)-.74 E 1.48 -.74('' i)-.7 H 2.5(nd).74 G(ata [1h, 10m])363.47 481.2 Q 32.5
+(rset reply)229 493.2 R(to RSET command [5m, none])2.5 E 31.38(quit reply)229
+505.2 R(to Q)2.5 E(UIT command [2m, none])-.1 E 28.05(misc reply)229 517.2 R
+(to NOOP and VERB commands [2m, none])2.5 E 7.5(command command)229 529.2 R
+(read [1h, 5m])2.5 E .799(All b)189 545.4 R .798
+(ut \231command\232 apply to client SMTP)-.2 F 5.798(.F)-1.11 G .798
+(or back compatibility)373.408 545.4 R 3.298(,at)-.65 G(imeout)476.22 545.4 Q
+(with no `)189 557.4 Q(`k)-.74 E -.15(ey)-.1 G -.1(wo).15 G(rd=').1 E 2.5('p)
+-.74 G(art will set all of the longer v)281.4 557.4 Q(alues.)-.25 E 68.11(sB)
+117 573.6 S 2.729(es)195.67 573.6 S(uper)206.729 573.6 Q .229
+(-safe when running things, i.e., al)-.2 F -.1(wa)-.1 G .229
+(ys instantiate the queue \214le, e).1 F -.15(ve)-.25 G(n).15 E .739
+(if you are going to attempt immediate deli)189 585.6 R -.15(ve)-.25 G(ry).15 E
+(.)-.65 E F2(Sendmail)5.739 E F1(al)3.239 E -.1(wa)-.1 G .739(ys instantiates)
+.1 F(the queue \214le before returning control the the client under an)189
+597.6 Q 2.5(yc)-.15 G(ircumstances.)444.07 597.6 Q(S)117 613.8 Q F2(\214le)A F1
+(Log statistics in the named)189 613.8 Q F2(\214le)2.5 E F1(.)A(t)117 630 Q F2
+(S,D)A F1 .798(Set the local time zone name to)189 630 R F2(S)3.299 E F1 .799
+(for standard time and)3.299 F F2(D)3.299 E F1 .799(for daylight time;)3.299 F
+(this is only used under v)189 642 Q(ersion six.)-.15 E(T)117 658.2 Q F2
+(rtime/wtime)A F1 1.604(Set the queue timeout to)189 658.2 R F2(rtime)4.103 E
+F1 6.603(.A)C 1.603(fter this interv)334.172 658.2 R 1.603
+(al, messages that ha)-.25 F 1.903 -.15(ve n)-.2 H(ot).15 E 1.251
+(been successfully sent will be returned to the sender)189 670.2 R 6.252(.D)
+-.55 G(ef)422.724 670.2 Q 1.252(aults to \214v)-.1 F 3.752(ed)-.15 G(ays.)
+488.17 670.2 Q .546(The optional)189 682.2 R F2(wtime)3.046 E F1 .546
+(is the time after which a w)3.046 F .546(arning message is sent.)-.1 F .546
+(If it is)5.546 F(missing or zero then no w)189 694.2 Q
+(arning messages are sent.)-.1 E(u)117 710.4 Q F2(n)A F1 .175(Set the def)189
+710.4 R .175(ault userid for mailers to)-.1 F F2(n)2.675 E F1 5.175(.M)C .175
+(ailers without the)355.28 710.4 R F2(S)2.676 E F1 .176(\215ag in the mailer)
+2.676 F(de\214nition will run as this user)189 722.4 Q 5(.D)-.55 G(ef)322.34
+722.4 Q(aults to 1.)-.1 E EP
+%%Page: 35 32
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-35)452.9 60 Q/F1 10/Times-Roman@0 SF(U)117 96 Q/F2 10/Times-Italic@0 SF
+(udbspec)A F1(The user database speci\214cation.)189 96 Q 67(vR)117 112.2 S
+.412(un in v)195.67 112.2 R .412(erbose mode.)-.15 F .412(If this is set,)5.412
+F F2(sendmail)2.911 E F1 .411(adjusts options)2.911 F F0(c)2.911 E F1(\(don')
+2.911 E 2.911(tc)-.18 G(onnect)477.34 112.2 Q .427(to e)189 124.2 R(xpensi)-.15
+E .727 -.15(ve m)-.25 H .427(ailers\) and).15 F F0(d)2.927 E F1(\(deli)2.928 E
+-.15(ve)-.25 G .428(ry mode\) so that all mail is deli).15 F -.15(ve)-.25 G
+.428(red com-).15 F .048
+(pletely in a single job so that you can see the entire deli)189 136.2 R -.15
+(ve)-.25 G .048(ry process.).15 F(Option)5.048 E F0(v)2.548 E F1(should)189
+148.2 Q F2(ne)3.389 E(ver)-.15 E F1 .889
+(be set in the con\214guration \214le; it is intended for command line)3.389 F
+(use only)189 160.2 Q(.)-.65 E(V)117 176.4 Q F2(fallbac)A(khost)-.2 E F1 .964
+(If speci\214ed, the)189 176.4 R F2(fallbac)3.464 E(khost)-.2 E F1 .964
+(acts lik)3.464 F 3.464(eav)-.1 G .964(ery lo)358.608 176.4 R 3.464(wp)-.25 G
+.964(riority MX on e)398.056 176.4 R -.15(ve)-.25 G .963(ry host.).15 F
+(This is intended to be used by sites with poor netw)189 188.4 Q(ork connecti)
+-.1 E(vity)-.25 E(.)-.65 E(x)117 204.6 Q F2(LA)A F1 .108
+(When the system load a)189 204.6 R -.15(ve)-.2 G .108(rage e).15 F(xceeds)-.15
+E F2(LA)2.608 E F1 2.608(,j)C .109(ust queue messages \(i.e., don')367.546
+204.6 R 2.609(tt)-.18 G(ry)495.67 204.6 Q(to send them\).)189 216.6 Q(Def)5 E
+(aults to 8.)-.1 E(X)117 232.8 Q F2(LA)A F1 1.251(When the system load a)189
+232.8 R -.15(ve)-.2 G 1.251(rage e).15 F(xceeds)-.15 E F2(LA)3.751 E F1 3.751
+(,r)C 1.251(efuse incoming SMTP connec-)376.097 232.8 R 2.5(tions. Def)189
+244.8 R(aults to 12.)-.1 E(y)117 261 Q F2(fact)A F1 .621(The indicated)189 261
+R F2(fact)3.121 E F1 .621(or is added to the priority \(thus)B F2(lowering)
+3.122 E F1 .622(the priority of the)3.122 F 1.384
+(job\) for each recipient, i.e., this v)189 273 R 1.383
+(alue penalizes jobs with lar)-.25 F 1.383(ge numbers of)-.18 F 2.5
+(recipients. Def)189 285 R(aults to 30000.)-.1 E 64.78(YI)117 301.2 S 3.346(fs)
+192.33 301.2 S .846(et, deli)202.896 301.2 R -.15(ve)-.25 G 3.346(re).15 G .847
+(ach job that is run from the queue in a separate process.)251.118 301.2 R(Use)
+5.847 E .037(this option if you are short of memory)189 313.2 R 2.536(,s)-.65 G
+.036(ince the def)350.024 313.2 R .036(ault tends to consume con-)-.1 F
+(siderable amounts of memory while the queue is being processed.)189 325.2 Q(z)
+117 341.4 Q F2(fact)A F1 1.644(The indicated)189 341.4 R F2(fact)4.144 E F1
+1.645(or is multiplied by the message class \(determined by the)B .923
+(Precedence: \214eld in the user header and the)189 353.4 R F0(P)3.423 E F1
+.923(lines in the con\214guration \214le\))3.423 F .819
+(and subtracted from the priority)189 365.4 R 5.819(.T)-.65 G .819
+(hus, messages with a higher Priority: will)333.255 365.4 R(be f)189 377.4 Q
+-.2(avo)-.1 G 2.5(red. Def).2 F(aults to 1800.)-.1 E(Z)117 393.6 Q F2(fact)A F1
+(The)189 393.6 Q F2(fact)3.346 E F1 .846(or is added to the priority e)B -.15
+(ve)-.25 G .846(ry time a job is processed.).15 F .845(Thus, each)5.845 F .942
+(time a job is processed, its priority will be decreased by the indicated v)189
+405.6 R(alue.)-.25 E .297(In most en)189 417.6 R .296
+(vironments this should be positi)-.4 F -.15(ve)-.25 G 2.796(,s).15 G .296
+(ince hosts that are do)378.614 417.6 R .296(wn are all)-.25 F(too often do)189
+429.6 Q(wn for a long time.)-.25 E(Def)5 E(aults to 90000.)-.1 E 67(7S)117
+445.8 S .278(trip input to se)194.56 445.8 R -.15(ve)-.25 G 2.778(nb).15 G .278
+(its for compatibility with old systems.)275.272 445.8 R .279(This shouldn')
+5.279 F 2.779(tb)-.18 G(e)499.56 445.8 Q(necessary)189 457.8 Q(.)-.65 E .78
+(All options can be speci\214ed on the command line using the \255o \215ag, b)
+117 474 R .779(ut most will cause)-.2 F F2(send-)3.279 E(mail)117 486 Q F1 .324
+(to relinquish its setuid permissions.)2.824 F .325
+(The options that will not cause this are b, d, e, E, i, L,)5.325 F .217
+(m, o, p, r)117 498 R 2.717(,s)-.4 G 2.717(,v)162.468 498 S 2.717(,C)172.035
+498 S 2.717(,a)183.922 498 S .217(nd 7.)193.579 498 R .216
+(Also, M \(de\214ne macro\) when de\214ning the r or s macros is also consid-)
+5.216 F(ered \231safe\232.)117 510 Q F0 2.5(5.1.7. P)102 534 R 2.5<8a70>2.5 G
+-.18(re)156.17 534 S(cedence de\214nitions).18 E F1 -1.11(Va)142 550.2 S .304
+(lues for the \231Precedence:\232 \214eld may be de\214ned using the)1.11 F F0
+(P)2.805 E F1 .305(control line.)2.805 F .305(The syntax of)5.305 F
+(this \214eld is:)117 562.2 Q F0(P)157 578.4 Q F2(name)A F0(=)A F2(num)A F1
+.286(When the)117 594.6 R F2(name)2.786 E F1 .285
+(is found in a \231Precedence:\232 \214eld, the message class is set to)2.786 F
+F2(num)2.785 E F1 5.285(.H)C .285(igher num-)459.555 594.6 R .479
+(bers mean higher precedence.)117 606.6 R .479(Numbers less than zero ha)5.479
+F .779 -.15(ve t)-.2 H .48(he special property that if an error).15 F 1.11(occ\
+urs during processing the body of the message will not be returned; this is e)
+117 618.6 R 1.11(xpected to be)-.15 F .678(used for \231b)117 630.6 R .678
+(ulk\232 mail such as through mailing lists.)-.2 F .678(The def)5.678 F .678
+(ault precedence is zero.)-.1 F -.15(Fo)5.678 G 3.178(re).15 G(xam-)483.45
+630.6 Q(ple, our list of precedences is:)117 642.6 Q(P\214rst-class=0)157 658.8
+Q(Pspecial-deli)157 670.8 Q -.15(ve)-.25 G(ry=100).15 E(Plist=\25530)157 682.8
+Q(Pb)157 694.8 Q(ulk=\25560)-.2 E(Pjunk=\255100)157 706.8 Q .8
+(People writing mailing list e)117 723 R .799
+(xploders are encouraged to use \231Precedence: list\232.)-.15 F .799(Older v)
+5.799 F(ersions)-.15 E EP
+%%Page: 36 33
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-36 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(of)117 96 Q/F2
+10/Times-Italic@0 SF(sendmail)3.759 E F1 1.259
+(\(which discarded all error returns for ne)3.759 F -.05(ga)-.15 G(ti).05 E
+1.559 -.15(ve p)-.25 H 1.259(recedences\) didn').15 F 3.76(tr)-.18 G 1.26
+(ecognize this)450.25 96 R .255(name, gi)117 108 R .255(ving it a def)-.25 F
+.255(ault precedence of zero.)-.1 F .254(This allo)5.254 F .254
+(ws list maintainers to see error returns on)-.25 F(both old and ne)117 120 Q
+2.5(wv)-.25 G(ersions of)193.26 120 Q F2(sendmail)2.5 E F1(.)A F0 2.5(5.1.8. V)
+102 144 R 2.5<8a63>2.5 G(on\214guration v)156.16 144 Q(ersion le)-.1 E -.1(ve)
+-.15 G(l).1 E F1 2.11 -.8(To p)142 160.2 T(ro).8 E .51
+(vide compatibility with old con\214guration \214les, the)-.15 F F0(V)3.01 E F1
+.51(line has been added to de\214ne)3.01 F .173(some v)117 172.2 R .173
+(ery basic semantics of the con\214guration \214le.)-.15 F .172
+(These are not intended to be long term sup-)5.173 F 1.84(ports; rather)117
+184.2 R 4.34(,t)-.4 G(he)176.66 184.2 Q 4.34(yd)-.15 G 1.84
+(escribe compatibility features which will probably be remo)200.29 184.2 R -.15
+(ve)-.15 G 4.34(di).15 G 4.34(nf)470.78 184.2 S(uture)483.45 184.2 Q(releases.)
+117 196.2 Q .031(\231Old\232 con\214guration \214les are de\214ned as v)142
+212.4 R .031(ersion le)-.15 F -.15(ve)-.25 G 2.531(lo).15 G 2.531(ne. V)359.438
+212.4 R .031(ersion le)-1.11 F -.15(ve)-.25 G 2.53(lt).15 G .23 -.1(wo \214)
+433.84 212.4 T .03(les mak).1 F 2.53(et)-.1 G(he)494.56 212.4 Q(follo)117 224.4
+Q(wing changes:)-.25 E 12.5(\(1\) Host)122 240.6 R .757(name canoni\214cation \
+\($[ ... $]\) appends a dot if the name is recognized; this gi)3.256 F -.15(ve)
+-.25 G(s).15 E .903(the con\214g \214le a w)148.66 252.6 R .903
+(ay of \214nding out if an)-.1 F .903(ything matched.)-.15 F(\(Actually)5.903 E
+3.403(,t)-.65 G .902(his just initializes)432.186 252.6 R .424
+(the \231host\232 map with the \231\255a.)148.66 264.6 R 5.424<9a8d>-.7 G .424
+(ag \212 you can reset it to an)280.014 264.6 R .424
+(ything you prefer by declar)-.15 F(-)-.2 E(ing the map e)148.66 276.6 Q
+(xplicitly)-.15 E(.\))-.65 E 12.5(\(2\) Def)122 292.8 R .436(ault host name e)
+-.1 F .435(xtension is consistent throughout processing; v)-.15 F .435
+(ersion le)-.15 F -.15(ve)-.25 G 2.935(lo).15 G .435(ne con-)473.855 292.8 R
+.828(\214gurations turned of)148.66 304.8 R 3.328(fd)-.25 G .828(omain e)
+243.384 304.8 R .828(xtension \(that is, adding the local domain name\) during)
+-.15 F .597(certain points in processing.)148.66 316.8 R -1.11(Ve)5.597 G .597
+(rsion le)1.11 F -.15(ve)-.25 G 3.097(lt).15 G .797 -.1(wo c)326.822 316.8 T
+.597(on\214gurations are e).1 F .596(xpected to include a)-.15 F
+(trailing dot to indicate that the name is already canonical.)148.66 328.8 Q
+12.5(\(3\) Local)122 345 R .176
+(names that are not aliases are passed through a ne)2.675 F 2.676(wd)-.25 G
+.176(istinguished ruleset \214v)388.892 345 R .176(e; this)-.15 F .797
+(can be used to append a local relay)148.66 357 R 5.797(.T)-.65 G .797
+(his beha)307.676 357 R .796(viour can be pre)-.2 F -.15(ve)-.25 G .796
+(nted by resolving the).15 F .62(local name with an initial `@'.)148.66 369 R
+.621(That is, something that resolv)5.62 F .621(es to a local mailer and a)-.15
+F .844(user name of \231vikki\232 will be passed through ruleset \214v)148.66
+381 R .843(e, b)-.15 F .843(ut a user name of \231@vikki\232)-.2 F .328
+(will ha)148.66 393 R .628 -.15(ve t)-.2 H .328
+(he `@' stripped, will not be passed through ruleset \214v).15 F .328(e, b)-.15
+F .328(ut will otherwise be)-.2 F 1.509(treated the same as the prior e)148.66
+405 R 4.009(xample. The)-.15 F -.15(ex)4.009 G 1.508
+(pectation is that this might be used to).15 F .907(implement a polic)148.66
+417 R 3.407(yw)-.15 G .907(here mail sent to \231vikki\232 w)238.171 417 R .908
+(as handled by a central hub, b)-.1 F .908(ut mail)-.2 F
+(sent to \231vikki@localhost\232 w)148.66 429 Q(as deli)-.1 E -.15(ve)-.25 G
+(red directly).15 E(.)-.65 E -1.11(Ve)142 445.2 S .229(rsion le)1.11 F -.15(ve)
+-.25 G 2.729(lt).15 G .229(hree \214les allo)199.828 445.2 R 2.729(w#i)-.25 G
+.228(nitiated comments on all lines.)274.374 445.2 R .228
+(Exceptions are backslash)5.228 F(escaped # marks and the $# syntax.)117 457.2
+Q F0 2.5(5.1.9. K)102 481.2 R 2.5<8a6b>2.5 G(ey \214le declaration)157.74 481.2
+Q F1(Special maps can be de\214ned using the line:)142 497.4 Q
+(Kmapname mapclass ar)157 513.6 Q(guments)-.18 E(The)117 529.8 Q F2(mapname)
+3.443 E F1 .944(is the handle by which this map is referenced in the re)3.443 F
+.944(writing rules.)-.25 F(The)5.944 E F2(map-)3.444 E(class)117 541.8 Q F1
+.301(is the name of a type of map; these are compiled in to sendmail.)2.801 F
+(The)5.3 E F2(ar)2.8 E(guments)-.37 E F1 .3(are inter)2.8 F(-)-.2 E .569
+(preted depending on the class; typically)117 553.8 R 3.069(,t)-.65 G .569
+(here w)286.134 553.8 R .569(ould be a single ar)-.1 F .57
+(gument naming the \214le con-)-.18 F(taining the map.)117 565.8 Q
+(Maps are referenced using the syntax:)142 582 Q($\()157 598.2 Q F2(map k)2.5 E
+-.3(ey)-.1 G F1($@)2.8 E F2(ar)2.5 E(guments)-.37 E F1($:)2.5 E F2(default)2.5
+E F1($\))2.5 E .797(where either or both of the)117 614.4 R F2(ar)3.297 E
+(guments)-.37 E F1(or)3.297 E F2(default)3.297 E F1 .796
+(portion may be omitted.)3.297 F(The)5.796 E F2(ar)3.296 E(guments)-.37 E F1
+(may)3.296 E .205(appear more than once.)117 626.4 R .205(The indicated)5.205 F
+F2 -.1(ke)2.705 G(y)-.2 E F1(and)2.705 E F2(ar)2.705 E(guments)-.37 E F1 .205
+(are passed to the appropriate mapping)2.705 F 2.503(function. If)117 638.4 R
+.003(it returns a v)2.503 F .003(alue, it replaces the input.)-.25 F .003
+(If it does not return a v)5.003 F .003(alue and the)-.25 F F2(default)2.503 E
+F1(is)2.503 E(speci\214ed, the)117 650.4 Q F2(default)2.5 E F1
+(replaces the input.)2.5 E(Otherwise, the input is unchanged.)5 E .159
+(During replacement of either a map v)142 666.6 R .159(alue or def)-.25 F .159
+(ault the string \231%)-.1 F F2(n)A F1 2.66<9a28>C(where)421.82 666.6 Q F2(n)
+2.66 E F1 .16(is a digit\) is)2.66 F .204(replaced by the corresponding)117
+678.6 R F2(ar)2.704 E(gument)-.37 E F1 5.204(.A)C -.18(rg)294 678.6 S .204
+(ument zero is al).18 F -.1(wa)-.1 G .204(ys the database k).1 F -.15(ey)-.1 G
+5.203(.F)-.5 G .203(or e)468.127 678.6 R(xam-)-.15 E(ple, the rule)117 690.6 Q
+(R$- ! $+)157 706.8 Q($: $\(uucp $1 $@ $2 $: %1 @ %0 . UUCP $\))265 706.8 Q
+.436(Looks up the UUCP name in a \(user de\214ned\) UUCP map; if not found it \
+turns it into \231.UUCP\232)117 723 R EP
+%%Page: 37 34
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-37)452.9 60 Q/F1 10/Times-Roman@0 SF 2.5(form. The)117 96 R
+(database might contain records lik)2.5 E(e:)-.1 E(decv)157 112.2 Q 77.43
+(ax %1@%0.DEC.COM)-.25 F 72.19(research %1@%0.A)157 124.2 R(TT)-1.11 E(.COM)
+-.74 E 2.065(The b)142 144.6 R 2.064(uilt in map with both name and class \231\
+host\232 is the host name canonicalization)-.2 F 2.5(lookup. Thus,)117 156.6 R
+(the syntax:)2.5 E($\(host)157 172.8 Q/F2 10/Times-Italic@0 SF(hostname)2.5 E
+F1($\))A(is equi)117 189 Q -.25(va)-.25 G(lent to:).25 E($[)157 205.2 Q F2
+(hostname)A F1($])A 1.783(There are four prede\214ned database lookup classes:\
+ \231dbm\232, \231btree\232, \231hash\232, and \231nis\232.)142 225.6 R .569
+(The \214rst requires that sendmail be compiled with the)117 237.6 R F0(ndbm)
+3.069 E F1 .568(library; the second tw)3.069 F 3.068(or)-.1 G .568(equire the)
+463.722 237.6 R F0(db)117 249.6 Q F1(library)3.198 E 3.198(,a)-.65 G .698
+(nd the third requires that sendmail be compiled with NIS support.)167.466
+249.6 R .698(All four accept)5.698 F(as ar)117 261.6 Q
+(guments the some optional \215ags and a \214lename \(or a mapname for NIS\).)
+-.18 E(Kno)5 E(wn \215ags are:)-.25 E 58.86(\255o Indicates)117 277.8 R .21
+(that this map is optional \212 that is, if it cannot be opened, no error is)
+2.71 F(produced, and sendmail will beha)189 289.8 Q .3 -.15(ve a)-.2 H 2.5(si)
+.15 G 2.5(ft)348.9 289.8 S(he map e)357.51 289.8 Q(xisted b)-.15 E(ut w)-.2 E
+(as empty)-.1 E(.)-.65 E 56.64(\255N Normally)117 306 R .121
+(sendmail does not include the trailing null byte on a string as part of)2.62 F
+.561(the k)189 318 R -.15(ey)-.1 G 5.561(.I)-.5 G 3.061(ft)229.212 318 S .561
+(his \215ag is indicated, it will be included.)238.383 318 R .56
+(This is for compatibility)5.56 F(with some methods of b)189 330 Q
+(uilding the maps.)-.2 E<ad61>117 346.2 Q F2(x)A F1 .649(Append the character)
+189 346.2 R F2(x)3.149 E F1 .649(on successful matches.)3.149 F -.15(Fo)5.649 G
+3.149(re).15 G .649(xample, the def)406.052 346.2 R(ault)-.1 E F2(host)3.15 E
+F1(map appends a dot on successful matches.)189 358.2 Q 60.53(\255f F)117 374.4
+R(old upper to lo)-.15 E(wer case before looking up the k)-.25 E -.15(ey)-.1 G
+(.)-.5 E 56.08(\255m Match)117 390.6 R .085(only \(without replacing the v)
+2.585 F 2.585(alue\). If)-.25 F .085(you only care about the e)2.585 F
+(xistence)-.15 E 2.618(of a k)189 402.6 R 2.918 -.15(ey a)-.1 H 2.618
+(nd not the v).15 F 2.619(alue \(as you might when searching the NIS map)-.25 F
+.447(\231hosts.byname\232 for e)189 414.6 R .447(xample\), this \215ag pre)-.15
+F -.15(ve)-.25 G .447(nts the map from substituting the).15 F -.25(va)189 426.6
+S 4.935(lue. Ho).25 F(we)-.25 E -.15(ve)-.25 G 3.235 -.4(r, T).15 H 2.436
+(he \255a ar).4 F 2.436(gument is still appended on a match, and the)-.18 F
+(def)189 438.6 Q(ault is still tak)-.1 E(en if the match f)-.1 E(ails.)-.1 E
+(The)142 454.8 Q F2(dbm)3.874 E F1 1.374
+(map appends the strings \231.pag\232 and \231.dir\232 to the gi)3.874 F -.15
+(ve)-.25 G 3.874<6e8c>.15 G 1.374(lename; the tw)420.268 454.8 R(o)-.1 E F2(db)
+3.874 E F1(-)A(based maps append \231.db\232.)117 466.8 Q .022(The program)142
+483 R F2(mak)2.522 E(emap)-.1 E F1 .023(\(8\) can be used to b)B .023(uild an)
+-.2 F 2.523(yo)-.15 G 2.523(ft)353.095 483 S .023
+(he three database-oriented maps.)361.728 483 R(It)5.023 E(tak)117 495 Q
+(es the follo)-.1 E(wing \215ags:)-.25 E 60.53(\255f Do)117 511.2 R
+(not fold upper to lo)2.5 E(wer case in the map.)-.25 E 56.64(\255N Include)117
+527.4 R(null bytes in k)2.5 E -.15(ey)-.1 G(s.).15 E 58.86(\255o Append)117
+543.6 R(to an e)2.5 E(xisting \(old\) \214le.)-.15 E 60.53(\255r Allo)117 559.8
+R 3.479(wr)-.25 G .979(eplacement of e)220.559 559.8 R .979(xisting k)-.15 F
+-.15(ey)-.1 G .979(s; normally).15 F 3.479(,r)-.65 G .979(e-inserting an e)
+385.494 559.8 R .979(xisting k)-.15 F 1.279 -.15(ey i)-.1 H(s).15 E(an error)
+189 571.8 Q(.)-.55 E 58.86(\255v Print)117 588 R(what is happening.)2.5 E
+(There are also tw)142 604.2 Q 2.5(ob)-.1 G
+(uiltin maps that are, strictly speaking, not database lookups.)223.34 604.2 Q
+1.563(The \231host\232 map does host domain canoni\214cation; gi)142 620.4 R
+-.15(ve)-.25 G 4.063(nah).15 G 1.563(ost name it calls the name)392.585 620.4 R
+(serv)117 632.4 Q(er to \214nd the canonical name for that host.)-.15 E .106
+(The \231dequote\232 map strips double quotes \("\) from a name.)142 648.6 R
+.106(It does not strip backslashes.)5.106 F(It)5.106 E 1.838
+(will not strip quotes if the resulting string w)117 660.6 R 1.838
+(ould contain unscannable syntax \(that is, basic)-.1 F .601(errors lik)117
+672.6 R 3.101(eu)-.1 G .601(nbalanced angle brack)166.422 672.6 R .601
+(ets; more sophisticated errors such as unkno)-.1 F .6(wn hosts are not)-.25 F
+(check)117 684.6 Q 3.398(ed\). The)-.1 F .899
+(intent is for use when trying to accept mail from systems such as DECnet that)
+3.398 F(routinely quote odd syntax such as)117 696.6 Q("49ers::ubell")157 712.8
+Q EP
+%%Page: 38 35
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-38 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 2.5(At)117 96 S
+(ypical usage is probably something lik)129.5 96 Q(e:)-.1 E(Kdequote dequote)
+157 112.2 Q(...)157 136.2 Q 88.19(R$\255 $:)157 160.2 R($\(dequote $1 $\))2.5 E
+(R$\255 $+)157 172.2 Q($: $>3 $1 $2)265 172.2 Q(Care must be tak)117 188.4 Q
+(en to pre)-.1 E -.15(ve)-.25 G(nt une).15 E(xpected results; for e)-.15 E
+(xample,)-.15 E("|someprogram < input > output")157 204.6 Q .084(will ha)117
+220.8 R .384 -.15(ve q)-.2 H .083(uotes stripped, b).15 F .083
+(ut the result is probably not what you had in mind.)-.2 F -.15(Fo)5.083 G .083
+(rtunately these).15 F(cases are rare.)117 232.8 Q(Ne)142 249 Q 2.5(wc)-.25 G
+(lasses can be added in the routine)167.57 249 Q F0(setupmaps)2.5 E F1
+(in \214le)2.5 E F0(conf)2.5 E(.c)-.15 E F1(.)A F0 2.5(5.2. Building)87 273 R
+2.5(aC)2.5 G(on\214guration File Fr)160.91 273 Q(om Scratch)-.18 E F1 1.517
+(Building a con\214guration table from scratch is an e)127 289.2 R 1.518
+(xtremely dif)-.15 F 1.518(\214cult job)-.25 F 6.518(.F)-.4 G(ortunately)
+441.334 289.2 Q 4.018(,i)-.65 G 4.018(ti)490.532 289.2 S(s)500.11 289.2 Q 1.855
+(almost ne)102 301.2 R -.15(ve)-.25 G 4.355(rn).15 G 1.855
+(ecessary to do so; nearly e)164.19 301.2 R -.15(ve)-.25 G 1.855
+(ry situation that may come up may be resolv).15 F 1.855(ed by)-.15 F .416
+(changing an e)102 313.2 R .416(xisting table.)-.15 F .416(In an)5.416 F 2.916
+(yc)-.15 G .416
+(ase, it is critical that you understand what it is that you are try-)248.616
+313.2 R 1.151(ing to do and come up with a philosoph)102 325.2 R 3.651(yf)-.05
+G 1.151(or the con\214guration table.)281.472 325.2 R 1.151
+(This section is intended to)6.151 F -.15(ex)102 337.2 S .67
+(plain what the real purpose of a con\214guration table is and to gi).15 F .97
+-.15(ve y)-.25 H .67(ou some ideas for what your).15 F(philosoph)102 349.2 Q
+2.5(ym)-.05 G(ight be.)156.68 349.2 Q F0 1.32(Do not e)127 365.4 R -.1(ve)-.15
+G 3.82(nc).1 G(onsider)188.2 365.4 Q F1 1.32(writing your o)3.82 F 1.32
+(wn con\214guration \214le without carefully studying RFC)-.25 F
+(821, 822, and 1123.)102 377.4 Q -1.1(Yo)5 G 2.5(us)1.1 G
+(hould also read RFC 976 if you are doing UUCP e)208.95 377.4 Q(xchange.)-.15 E
+F0 2.5(5.2.1. What)102 401.4 R -.25(yo)2.5 G 2.5(ua).25 G .36 -.18(re t)178.7
+401.4 T(rying to do).18 E F1 .82
+(The con\214guration table has three major purposes.)142 417.6 R .821
+(The \214rst and simplest is to set up the)5.821 F(en)117 429.6 Q .35
+(vironment for)-.4 F/F2 10/Times-Italic@0 SF(sendmail)2.85 E F1 5.35(.T)C .35
+(his in)234.58 429.6 R -.2(vo)-.4 G(lv).2 E .35
+(es setting the options, de\214ning a fe)-.15 F 2.85(wc)-.25 G .35
+(ritical macros, etc.)429.43 429.6 R(Since these are described in other places\
+, we will not go into more detail here.)117 441.6 Q .283
+(The second purpose is to re)142 457.8 R .284(write addresses in the message.)
+-.25 F .284(This should typically be done)5.284 F .214(in tw)117 469.8 R 2.714
+(op)-.1 G 2.713(hases. The)150.108 469.8 R .213
+(\214rst phase maps addresses in an)2.713 F 2.713(yf)-.15 G .213
+(ormat into a canonical form.)337.182 469.8 R .213(This should)5.213 F .156
+(be done in ruleset three.)117 481.8 R .157
+(The second phase maps this canonical form into the syntax appropriate)5.156 F
+1.998(for the recei)117 493.8 R 1.997(ving mailer)-.25 F(.)-.55 E F2(Sendmail)
+6.997 E F1 1.997(does this in three subphases.)4.497 F 1.997
+(Rulesets one and tw)6.997 F 4.497(oa)-.1 G(re)496.23 493.8 Q .043
+(applied to all sender and recipient addresses respecti)117 505.8 R -.15(ve)
+-.25 G(ly).15 E 5.043(.A)-.65 G .043(fter this, you may specify per)357.904
+505.8 R(-mailer)-.2 E 2.723
+(rulesets for both sender and recipient addresses; this allo)117 517.8 R 2.723
+(ws mailer)-.25 F 2.723(-speci\214c customization.)-.2 F(Finally)117 529.8 Q
+2.5(,r)-.65 G(uleset four is applied to do an)153.02 529.8 Q 2.5(yd)-.15 G(ef)
+283.69 529.8 Q(ault con)-.1 E -.15(ve)-.4 G(rsion to e).15 E(xternal form.)-.15
+E .785(The third purpose is to map addresses into the actual set of instructio\
+ns necessary to get)142 546 R .154(the message deli)117 558 R -.15(ve)-.25 G
+2.654(red. Ruleset).15 F .154(zero must resolv)2.654 F 2.654(et)-.15 G 2.654
+(ot)321.658 558 S .153(he internal form, which is in turn used as a)332.092 558
+R .446(pointer to a mailer descriptor)117 570 R 5.446(.T)-.55 G .446
+(he mailer descriptor describes the interf)248.38 570 R .447
+(ace requirements of the)-.1 F(mailer)117 582 Q(.)-.55 E F0 2.5
+(5.2.2. Philosoph)102 606 R(y)-.15 E F1 1.481(The particular philosoph)142
+622.2 R 3.981(yy)-.05 G 1.481(ou choose will depend hea)257.213 622.2 R 1.481
+(vily on the size and structure of)-.2 F .55(your or)117 634.2 R -.05(ga)-.18 G
+3.05(nization. I).05 F .55(will present a fe)3.05 F 3.05(wp)-.25 G .55
+(ossible philosophies here.)283.39 634.2 R .55(There are as man)5.55 F 3.05(yp)
+-.15 G(hiloso-)476.22 634.2 Q
+(phies as there are con\214g designers; feel free to de)117 646.2 Q -.15(ve)
+-.25 G(lop your o).15 E(wn.)-.25 E .388
+(One general point applies to all of these philosophies: it is almost al)142
+662.4 R -.1(wa)-.1 G .388(ys a mistak).1 F 2.888(et)-.1 G 2.888(ot)485.002
+662.4 S(ry)495.67 662.4 Q .176(to do full host route resolution.)117 674.4 R
+-.15(Fo)5.176 G 2.676(re).15 G .176
+(xample, if you are on a UUCP-only site and you are trying)267.652 674.4 R
+1.223(to get names of the form \231user@host\232 to the Internet, it does not \
+pay to route them to \231xyz-)117 686.4 R -.25(va)117 698.4 S(x!decv).25 E
+(ax!ucb)-.25 E -.25(va)-.15 G .304
+(x!c70!user@host\232 since you then depend on se).25 F -.15(ve)-.25 G .305
+(ral links not under your con-).15 F .996(trol, some of which are lik)117 710.4
+R .996(ely to misparse it an)-.1 F(yw)-.15 E(ay)-.1 E 5.996(.T)-.65 G .996
+(he best approach to this problem is to)347.32 710.4 R 1.048(simply forw)117
+722.4 R 1.048(ard the message for \231user@host\232 to \231xyzv)-.1 F 1.049
+(ax\232 and let xyzv)-.25 F 1.049(ax w)-.25 F 1.049(orry about it from)-.1 F EP
+%%Page: 39 36
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-39)452.9 60 Q/F1 10/Times-Roman@0 SF 3.606(there. In)117 96 R(summary)
+3.606 E 3.606(,j)-.65 G 1.106
+(ust get the message closer to the destination, rather than determining the)
+202.988 96 R(full path.)117 108 Q F0 2.5(5.2.2.1. Lar)117 132 R
+(ge site, many hosts \212 minimum inf)-.1 E(ormation)-.25 E F1(Berk)157 148.2 Q
+(ele)-.1 E 3.018(yi)-.15 G 3.018(sa)198.648 148.2 S 3.018(ne)209.996 148.2 S
+.518(xample of a lar)222.304 148.2 R .518(ge site, i.e., more than tw)-.18 F
+3.018(oo)-.1 G 3.018(rt)400.266 148.2 S .519(hree hosts and multiple)409.394
+148.2 R .444(mail connections.)132 160.2 R 2.044 -.8(We h)5.444 H -2.25 -.2
+(av e).8 H .443(decided that the only reasonable philosoph)3.144 F 2.943(yi)
+-.05 G 2.943(no)429.634 160.2 S .443(ur en)442.577 160.2 R(vironment)-.4 E .312
+(is to designate one host as the guru for our site.)132 172.2 R .312
+(It must be able to resolv)5.312 F 2.812(ea)-.15 G .612 -.15(ny p)438.504 172.2
+T .312(iece of mail).15 F 1.083(it recei)132 184.2 R -.15(ve)-.25 G 3.583
+(s. The).15 F 1.083(other sites should ha)3.583 F 1.383 -.15(ve t)-.2 H 1.083
+(he minimum amount of information the).15 F 3.582(yc)-.15 G 1.082(an get)
+478.758 184.2 R -2.3 -.15(aw a)132 196.2 T 2.635(yw).15 G 2.635(ith. In)162.705
+196.2 R .135(addition, an)2.635 F 2.635(yi)-.15 G .135(nformation the)249.485
+196.2 R 2.635(yd)-.15 G 2.635(oh)321.265 196.2 S -2.25 -.2(av e)333.9 196.2 T
+.136(should be hints rather than solid infor)2.835 F(-)-.2 E(mation.)132 208.2
+Q -.15(Fo)157 224.4 S 6.71(re).15 G 4.209
+(xample, a typical site on our local ether netw)181.74 224.4 R 4.209
+(ork is \231monet\232 \(actually)-.1 F(\231monet.CS.Berk)132 236.4 Q(ele)-.1 E
+-.65(y.)-.15 G 3.887(EDU\232\). When).65 F 1.387(monet recei)3.887 F -.15(ve)
+-.25 G 3.887(sm).15 G 1.387(ail for deli)354.258 236.4 R -.15(ve)-.25 G(ry).15
+E 3.887(,i)-.65 G 3.887(tc)424.579 236.4 S 1.387(hecks whether it)435.686 236.4
+R(kno)132 248.4 Q 1.342(ws that the destination host is directly reachable; if\
+ so, mail is sent to that host.)-.25 F 1.342(If it)6.342 F(recei)132 260.4 Q
+-.15(ve)-.25 G 2.915(sm).15 G .415(ail for an)175.055 260.4 R 2.915(yu)-.15 G
+(nkno)224.75 260.4 Q .415(wn host, it just passes it directly to \231ucb)-.25 F
+-.25(va)-.15 G(x.CS.Berk).25 E(ele)-.1 E -.65(y.)-.15 G(EDU\232,).65 E .178
+(our master host.)132 272.4 R(Ucb)5.178 E -.25(va)-.15 G 2.678(xm).25 G .177
+(ay determine that the host name is ille)242.852 272.4 R -.05(ga)-.15 G 2.677
+(la).05 G .177(nd reject the message,)415.159 272.4 R .754
+(or may be able to do deli)132 284.4 R -.15(ve)-.25 G(ry).15 E 5.754(.H)-.65 G
+-.25(ow)268.146 284.4 S -2.15 -.25(ev e).25 H 1.554 -.4(r, i).25 H 3.254(ti).4
+G 3.254(si)313.874 284.4 S .754(mportant to note that when a ne)323.798 284.4 R
+3.254(wm)-.25 G .754(ail con-)472.976 284.4 R .164
+(nection is added, the only host that)132 296.4 R/F2 10/Times-Italic@0 SF(must)
+2.664 E F1(ha)2.664 E .464 -.15(ve i)-.2 H .164(ts tables updated is ucb).15 F
+-.25(va)-.15 G .164(x; the others).25 F F2(may)2.664 E F1(be)2.664 E
+(updated if con)132 308.4 Q -.15(ve)-.4 G(nient, b).15 E
+(ut this is not critical.)-.2 E 2.121
+(This picture is slightly muddied due to netw)157 324.6 R 2.122
+(ork connections that are not actually)-.1 F 2.362(located on ucb)132 336.6 R
+-.25(va)-.15 G 4.862(x. F).25 F 2.362(or e)-.15 F 2.362
+(xample, some UUCP connections are currently on \231ucbarpa.)-.15 F<9a>-.7 E
+(Ho)132 348.6 Q(we)-.25 E -.15(ve)-.25 G 1.044 -.4(r, m).15 H(onet).4 E F2 .244
+(does not)2.744 F F1(kno)2.744 E 2.744(wa)-.25 G .245
+(bout this; the information is hidden totally between ucb)266.34 348.6 R -.25
+(va)-.15 G(x).25 E 1.045(and ucbarpa.)132 360.6 R 1.045
+(Mail going from monet to a UUCP host is transferred via the ethernet from)
+6.045 F 1.43(monet to ucb)132 372.6 R -.25(va)-.15 G 1.43
+(x, then via the ethernet from ucb).25 F -.25(va)-.15 G 3.931(xt).25 G 3.931
+(ou)355.704 372.6 S 1.431(cbarpa, and then is submitted to)369.635 372.6 R
+(UUCP)132 384.6 Q 5(.A)-1.11 G(lthough this in)172.28 384.6 Q -.2(vo)-.4 G(lv)
+.2 E(es some e)-.15 E(xtra hops, we feel this is an acceptable tradeof)-.15 E
+(f.)-.25 E .826(An interesting point is that it w)157 400.8 R .826
+(ould be possible to update monet to send appropriate)-.1 F .127
+(UUCP mail directly to ucbarpa if the load got too high; if monet f)132 412.8 R
+.127(ailed to note a host as con-)-.1 F .353(nected to ucbarpa it w)132 424.8 R
+.353(ould go via ucb)-.1 F -.25(va)-.15 G 2.853(xa).25 G 2.852(sb)305.954 424.8
+S .352(efore, and if monet incorrectly sent a message)317.696 424.8 R .395
+(to ucbarpa it w)132 436.8 R .396(ould still be sent by ucbarpa to ucb)-.1 F
+-.25(va)-.15 G 2.896(xa).25 G 2.896(sb)356.654 436.8 S 2.896(efore. The)368.44
+436.8 R .396(only problem that can)2.896 F .901(occur is loops, for e)132 448.8
+R .901(xample, if ucbarpa thought that ucb)-.15 F -.25(va)-.15 G 3.401(xh).25 G
+.9(ad the UUCP connection and)383.75 448.8 R(vice v)132 460.8 Q 2.5(ersa. F)
+-.15 F(or this reason, updates should)-.15 E F2(always)2.5 E F1
+(happen to the master host \214rst.)2.5 E .144(This philosoph)157 477 R 2.644
+(yr)-.05 G .145(esults as much from the need to ha)227.798 477 R .445 -.15
+(ve a s)-.2 H .145(ingle source for the con\214gu-).15 F .289
+(ration \214les \(typically b)132 489 R .289(uilt using)-.2 F F2(m4)2.789 E F1
+.289(\(1\) or some similar tool\) as an)1.666 F 2.789(yl)-.15 G .288
+(ogical need.)410.664 489 R(Maintain-)5.288 E
+(ing more than three separate tables by hand is essentially an impossible job)
+132 501 Q(.)-.4 E F0 2.5(5.2.2.2. Small)117 525 R(site \212 complete inf)2.5 E
+(ormation)-.25 E F1 3.356(As)157 541.2 S .856(mall site \(tw)171.466 541.2 R
+3.356(oo)-.1 G 3.356(rt)236.434 541.2 S .856(hree hosts and fe)245.9 541.2 R
+3.356(we)-.25 G .856(xternal connections\) may \214nd it more rea-)330.564
+541.2 R .435(sonable to ha)132 553.2 R .735 -.15(ve c)-.2 H .435
+(omplete information at each host.).15 F .435(This w)5.435 F .435
+(ould require that each host kno)-.1 F(w)-.25 E -.15(ex)132 565.2 S .185
+(actly where each netw).15 F .185
+(ork connection is, possibly including the names of each host on that)-.1 F
+(netw)132 577.2 Q 4.341(ork. As)-.1 F 1.841
+(long as the site remains small and the the con\214guration remains relati)
+4.341 F -.15(ve)-.25 G(ly).15 E
+(static, the update problem will probably not be too great.)132 589.2 Q F0 2.5
+(5.2.2.3. Single)117 613.2 R(host)2.5 E F1 .117(This is in some sense the tri)
+157 629.4 R .117(vial case.)-.25 F .117
+(The only major issue is trying to insure that you)5.117 F(don')132 641.4 Q
+3.425(th)-.18 G -2.25 -.2(av e)161.355 641.4 T .925(to kno)3.625 F 3.425(wt)
+-.25 G .925(oo much about your en)217.69 641.4 R 3.425(vironment. F)-.4 F .925
+(or e)-.15 F .924(xample, if you ha)-.15 F 1.224 -.15(ve a U)-.2 H(UCP).15 E
+.614(connection you might \214nd it useful to kno)132 653.4 R 3.115(wa)-.25 G
+.615(bout the names of hosts connected directly to)318.885 653.4 R(you, b)132
+665.4 Q
+(ut this is really not necessary since this may be determined from the syntax.)
+-.2 E F0 2.5(5.2.2.4. A)117 689.4 R(completely differ)2.5 E(ent philosoph)-.18
+E(y)-.15 E F1(This is adapted from Bruce Lilly)157 705.6 Q 5(.A)-.65 G .3 -.15
+(ny e)301.89 705.6 T(rrors in interpretation are mine.).15 E EP
+%%Page: 40 37
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-40 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF .065
+(Do minimal changes in ruleset 3: \214x some common b)157 96 R .064
+(ut unambiguous errors \(e.g. trail-)-.2 F 2.758
+(ing dot on domains\) and hide bang paths foo!bar into bar@foo.UUCP)132 108 R
+7.759(.T)-1.11 G 2.759(he resulting)454.301 108 R("canonical" form is an)132
+120 Q 2.5(yv)-.15 G(alid RFC822/RFC1123/RFC976 address.)233.63 120 Q 1.388
+(Ruleset 0 does the b)157 136.2 R 1.387(ulk of the w)-.2 F 3.887(ork. It)-.1 F
+(remo)3.887 E -.15(ve)-.15 G 3.887(st).15 G 1.387
+(he trailing "@.UUCP" that hides)367.472 136.2 R .66(bang paths, strips an)132
+148.2 R .661(ything not needed to resolv)-.15 F .661
+(e, e.g. the phrase from phrase <route-addr>)-.15 F .497
+(and from named groups, rejects unparseable addresses using $#error)132 160.2 R
+2.996(,a)-.4 G .496(nd \214nally resolv)419.052 160.2 R .496(es to)-.15 F 4.324
+(am)132 172.2 S 1.824(ailer/host/user triple.)148.544 172.2 R 1.824
+(Ruleset 0 is rather length)6.824 F 4.325(ya)-.05 G 4.325(si)360.965 172.2 S
+4.325(th)371.96 172.2 S 1.825(as to handle 3 basic address)384.065 172.2 R
+5.373(forms: RFC976 bang paths, RFC1123 %-hacks \(including v)132 184.2 R 5.373
+(anilla RFC822 local-)-.25 F .136(part@domain\), and RFC822 source routes.)132
+196.2 R(It')5.137 E 2.637(sa)-.55 G .137(lso complicated by ha)329.508 196.2 R
+.137(ving to handle named)-.2 F(lists.)132 208.2 Q .617(The header re)157 224.4
+R .616(writing rulesets 1 and 2 remo)-.25 F .916 -.15(ve t)-.15 H .616
+(he trailing "@.UUCP" that hides bang).15 F 2.5(paths. Ruleset)132 236.4 R 2.5
+(2a)2.5 G(lso strips the $# mailer $@ host \(for test mode\).)205.05 236.4 Q
+(Ruleset 4 does absolutely nothing.)157 252.6 Q 1.316(The per)157 268.8 R 1.316
+(-mailer re)-.2 F 1.316(writing rulesets conform the en)-.25 F -.15(ve)-.4 G
+1.317(lope and header addresses to the).15 F
+(requirements of the speci\214c mailer)132 280.8 Q(.)-.55 E
+(Lots of rulesets-as-subroutines are used.)157 297 Q .35(As a result, header a\
+ddresses are subject to minimal munging \(per RFC1123\), and the)157 313.2 R
+(general plan is per RFC822 sect. 3.4.10.)132 325.2 Q F0 2.5(5.2.3. Rele)102
+349.2 R -.1(va)-.15 G(nt issues).1 E F1 .584(The canonical form you use should\
+ almost certainly be as speci\214ed in the Internet proto-)142 365.4 R 2.604
+(cols RFC819 and RFC822.)117 377.4 R 2.604(Copies of these RFC')7.604 F 5.104
+(sa)-.55 G 2.603(re included on the)347.852 377.4 R/F2 10/Times-Italic@0 SF
+(sendmail)5.103 E F1 2.603(tape as)5.103 F F2(doc/rfc819.lpr)117 389.4 Q F1
+(and)2.5 E F2(doc/rfc822.lpr)2.5 E F1(.)A 2.04
+(RFC822 describes the format of the mail message itself.)142 405.6 R F2
+(Sendmail)7.04 E F1(follo)4.54 E 2.04(ws this RFC)-.25 F(closely)117 417.6 Q
+2.984(,t)-.65 G 2.984(ot)152.944 417.6 S .483(he e)163.708 417.6 R .483
+(xtent that man)-.15 F 2.983(yo)-.15 G 2.983(ft)251.44 417.6 S .483
+(he standards described in this document can not be changed)260.533 417.6 R
+(without changing the code.)117 429.6 Q(In particular)5 E 2.5(,t)-.4 G
+(he follo)286.85 429.6 Q(wing characters ha)-.25 E .3 -.15(ve s)-.2 H
+(pecial interpretations:).15 E 2.5(<>\(\)"\\)157 445.8 S(An)117 462 Q 3.036(ya)
+-.15 G .537(ttempt to use these characters for other than their RFC822 purpose\
+ in addresses is proba-)141.546 462 R(bly doomed to disaster)117 474 Q(.)-.55 E
+1.327(RFC819 describes the speci\214cs of the domain-based addressing.)142
+490.2 R 1.326(This is touched on in)6.327 F 1.439(RFC822 as well.)117 502.2 R
+1.439(Essentially each host is gi)6.439 F -.15(ve)-.25 G 3.939(nan).15 G 1.44
+(ame which is a right-to-left dot quali\214ed)333.711 502.2 R .232
+(pseudo-path from a distinguished root.)117 514.2 R .232
+(The elements of the path need not be ph)5.232 F .232(ysical hosts; the)-.05 F
+2.365(domain is logical rather than ph)117 526.2 R 4.866(ysical. F)-.05 F 2.366
+(or e)-.15 F 2.366(xample, at Berk)-.15 F(ele)-.1 E 4.866(yo)-.15 G 2.366
+(ne le)406.406 526.2 R -.05(ga)-.15 G 4.866(lh).05 G 2.366(ost might be)449.818
+526.2 R(\231a.CC.Berk)117 538.2 Q(ele)-.1 E -.65(y.)-.15 G .366
+(EDU\232; reading from right to left, \231EDU\232 is a top le).65 F -.15(ve)
+-.25 G 2.865(ld).15 G .365(omain comprising edu-)410.5 538.2 R .561
+(cational institutions, \231Berk)117 550.2 R(ele)-.1 E .562
+(y\232 is a logical domain name, \231CC\232 represents the Computer Cen-)-.15 F
+(ter)117 562.2 Q 2.5(,\()-.4 G(in this case a strictly logical entity\), and \
+\231a\232 is a host in the Computer Center)135.48 562.2 Q(.)-.55 E(Be)142 578.4
+Q -.1(wa)-.25 G
+(re when reading RFC819 that there are a number of errors in it.).1 E F0 2.5
+(5.2.4. Ho)102 602.4 R 2.5(wt)-.1 G 2.5(op)155.23 602.4 S -.18(ro)168.29 602.4
+S(ceed).18 E F1 .335(Once you ha)142 618.6 R .635 -.15(ve d)-.2 H .335
+(ecided on a philosoph).15 F 1.635 -.65(y, i)-.05 H 2.835(ti).65 G 2.834(sw)
+319.44 618.6 S .334(orth e)333.284 618.6 R .334(xamining the a)-.15 F -.25(va)
+-.2 G .334(ilable con\214guration).25 F .174(tables to decide if an)117 630.6 R
+2.674(yo)-.15 G 2.674(ft)212.98 630.6 S .174
+(hem are close enough to steal major parts of.)221.764 630.6 R(Ev)5.174 E .175
+(en under the w)-.15 F .175(orst of)-.1 F(conditions, there is a f)117 642.6 Q
+(air amount of boiler plate that can be collected safely)-.1 E(.)-.65 E .33
+(The ne)142 658.8 R .33(xt step is to b)-.15 F .33(uild ruleset three.)-.2 F
+.329(This will be the hardest part of the job)5.33 F 5.329(.B)-.4 G -2.1 -.25
+(ew a)469.321 658.8 T .329(re of).25 F .781
+(doing too much to the address in this ruleset, since an)117 670.8 R .781
+(ything you do will re\215ect through to the)-.15 F 2.744(message. In)117 682.8
+R(particular)2.744 E 2.744(,s)-.4 G .243
+(tripping of local domains is best deferred, since this can lea)216.752 682.8 R
+.543 -.15(ve y)-.2 H .243(ou with).15 F 1.234
+(addresses with no domain spec at all.)117 694.8 R(Since)6.235 E F2(sendmail)
+3.735 E F1(lik)3.735 E 1.235(es to append the sending domain to)-.1 F .83
+(addresses with no domain, this can change the semantics of addresses.)117
+706.8 R .83(Also try to a)5.83 F -.2(vo)-.2 G .83(id fully).2 F .342
+(qualifying domains in this ruleset.)117 718.8 R .342(Although technically le)
+5.342 F -.05(ga)-.15 G .343(l, this can lead to unpleasantly and).05 F EP
+%%Page: 41 38
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-41)452.9 60 Q/F1 10/Times-Roman@0 SF 1.287
+(unnecessarily long addresses re\215ected into messages.)117 96 R 1.287
+(The Berk)6.287 F(ele)-.1 E 3.787(yc)-.15 G 1.287
+(on\214guration \214les de\214ne)406.426 96 R .093
+(ruleset nine to qualify domain names and strip local domains.)117 108 R .093
+(This is called from ruleset zero to)5.093 F
+(get all addresses into a cleaner form.)117 120 Q .318(Once you ha)142 136.2 R
+.618 -.15(ve r)-.2 H .318
+(uleset three \214nished, the other rulesets should be relati).15 F -.15(ve)
+-.25 G .318(ly tri).15 F 2.817(vial. If)-.25 F(you)2.817 E(need hints, e)117
+148.2 Q(xamine the supplied con\214guration tables.)-.15 E F0 2.5(5.2.5. T)102
+172.2 R(esting the r)-.92 E(ewriting rules \212 the \255bt \215ag)-.18 E F1
+1.075(When you b)142 188.4 R 1.075(uild a con\214guration table, you can do a \
+certain amount of testing using the)-.2 F(\231test mode\232 of)117 200.4 Q/F2
+10/Times-Italic@0 SF(sendmail)2.5 E F1 5(.F)C(or e)226.84 200.4 Q
+(xample, you could in)-.15 E -.2(vo)-.4 G -.1(ke).2 G F2(sendmail)2.6 E F1(as:)
+2.5 E(sendmail \255bt \255Ctest.cf)157 216.6 Q .904(which w)117 232.8 R .903
+(ould read the con\214guration \214le \231test.cf\232 and enter test mode.)-.1
+F .903(In this mode, you enter)5.903 F(lines of the form:)117 244.8 Q
+(rwset address)157 261 Q(where)117 277.2 Q F2(rwset)3.376 E F1 .876(is the re)
+3.376 F .876(writing set you w)-.25 F .876(ant to use and)-.1 F F2(addr)3.376 E
+(ess)-.37 E F1 .877(is an address to apply the set to.)3.376 F -.7(Te)117 289.2
+S .17(st mode sho).7 F .17(ws you the steps it tak)-.25 F .169
+(es as it proceeds, \214nally sho)-.1 F .169(wing you the address it ends up)
+-.25 F 3.635(with. Y)117 301.2 R 1.135(ou may use a comma separated list of rw\
+sets for sequential application of rules to an)-1.1 F 2.5(input. F)117 313.2 R
+(or e)-.15 E(xample:)-.15 E(3,1,21,4 monet:bollard)157 329.4 Q .386
+(\214rst applies ruleset three to the input \231monet:bollard.)117 345.6 R
+5.385<9a52>-.7 G .385(uleset one is then applied to the output)347.145 345.6 R
+(of ruleset three, follo)117 357.6 Q
+(wed similarly by rulesets twenty-one and four)-.25 E(.)-.55 E .202(If you nee\
+d more detail, you can also use the \231\255d21\232 \215ag to turn on more deb)
+142 373.8 R 2.702(ugging. F)-.2 F(or)-.15 E -.15(ex)117 385.8 S(ample,).15 E
+(sendmail \255bt \255d21.99)157 402 Q .754
+(turns on an incredible amount of information; a single w)117 418.2 R .753
+(ord address is probably going to print)-.1 F(out se)117 430.2 Q -.15(ve)-.25 G
+(ral pages w).15 E(orth of information.)-.1 E -1.1(Yo)142 446.4 S 3.075(us)1.1
+G .575(hould be w)165.085 446.4 R .575(arned that internally)-.1 F(,)-.65 E F0
+(sendmail)3.075 E F1 .575(applies ruleset 3 to all addresses.)3.075 F .575
+(In this)5.575 F -.15(ve)117 458.4 S 1.23(rsion of sendmail, you will ha).15 F
+1.53 -.15(ve t)-.2 H 3.73(od).15 G 3.73(ot)281.21 458.4 S 1.23(hat manually)
+292.72 458.4 R 6.23(.F)-.65 G 1.23(or e)359.38 458.4 R 1.23(xample, older v)
+-.15 F 1.23(ersions allo)-.15 F(wed)-.25 E(you to use)117 470.4 Q 2.5(0b)157
+486.6 S(ruce@broadcast.son)169.5 486.6 Q -.65(y.)-.15 G(com).65 E(This v)117
+502.8 Q(ersion requires that you use:)-.15 E(3,0 bruce@broadcast.son)157 519 Q
+-.65(y.)-.15 G(com).65 E F0 2.5(5.2.6. Building)102 547.2 R
+(mailer descriptions)2.5 E F1 1.886 -.8(To a)142 563.4 T .287
+(dd an outgoing mailer to your mail system, you will ha).8 F .587 -.15(ve t)-.2
+H 2.787(od).15 G .287(e\214ne the characteristics)409.566 563.4 R
+(of the mailer)117 575.4 Q(.)-.55 E 1.481(Each mailer must ha)142 591.6 R 1.781
+-.15(ve a)-.2 H 3.981(ni).15 G 1.481(nternal name.)257.645 591.6 R 1.481
+(This can be arbitrary)6.481 F 3.98(,e)-.65 G 1.48(xcept that the names)417.63
+591.6 R(\231local\232 and \231prog\232 must be de\214ned.)117 603.6 Q .127
+(The pathname of the mailer must be gi)142 619.8 R -.15(ve)-.25 G 2.628(ni).15
+G 2.628(nt)317.038 619.8 S .128(he P \214eld.)327.446 619.8 R .128
+(If this mailer should be accessed)5.128 F
+(via an IPC connection, use the string \231[IPC]\232 instead.)117 631.8 Q .021
+(The F \214eld de\214nes the mailer \215ags.)142 648 R -1.1(Yo)5.021 G 2.521
+(us)1.1 G .021(hould specify an \231f\232 or \231r\232 \215ag to pass the name)
+311.06 648 R .465(of the sender as a)117 660 R F0<ad66>2.965 E F1(or)2.965 E F0
+<ad72>2.965 E F1 .465(\215ag respecti)2.965 F -.15(ve)-.25 G(ly).15 E 5.465(.T)
+-.65 G .465(hese \215ags are only passed if the)306.95 660 R 2.966(yw)-.15 G
+.466(ere passed to)451.418 660 R F2(sendmail,)117 672 Q F1 1.705
+(so that mailers that gi)4.205 F 2.005 -.15(ve e)-.25 H 1.705
+(rrors under some circumstances can be placated.).15 F 1.705(If the)6.705 F
+1.362(mailer is not pick)117 684 R 3.862(yy)-.15 G 1.362
+(ou can just specify \231\255f $g\232 in the ar)204.518 684 R 1.362
+(gv template.)-.18 F 1.363(If the mailer must be)6.362 F 1.708(called as)117
+696 R F0 -.18(ro)4.207 G(ot).18 E F1 1.707(the \231S\232 \215ag should be gi)
+4.207 F -.15(ve)-.25 G 1.707
+(n; this will not reset the userid before calling the).15 F EP
+%%Page: 42 39
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-42 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(mailer)117 98 Q
+/F2 7/Times-Roman@0 SF(10)142.55 94 Q F1 5.112(.I)149.55 98 S 2.612(ft)160.492
+98 S .112(his mailer is local \(i.e., will perform \214nal deli)169.214 98 R
+-.15(ve)-.25 G .112(ry rather than another netw).15 F .112(ork hop\))-.1 F .728
+(the \231l\232 \215ag should be gi)117 110 R -.15(ve)-.25 G 3.227(n. Quote).15
+F .727(characters \(backslashes and " marks\) can be stripped from)3.227 F .268
+(addresses if the \231s\232 \215ag is speci\214ed; if this is not gi)117 122 R
+-.15(ve)-.25 G 2.769(nt).15 G(he)344.247 122 Q 2.769(ya)-.15 G .269
+(re passed through.)365.746 122 R .269(If the mailer is)5.269 F .67(capable of\
+ sending to more than one user on the same host in a single transaction the \
+\231m\232 \215ag)117 134 R 1.176(should be stated.)117 146 R 1.176
+(If this \215ag is on, then the ar)6.176 F 1.177(gv template containing)-.18 F
+F0($u)3.677 E F1 1.177(will be repeated for)3.677 F .089
+(each unique user on a gi)117 158 R -.15(ve)-.25 G 2.589(nh).15 G 2.589
+(ost. The)235.994 158 R .089
+(\231e\232 \215ag will mark the mailer as being \231e)2.589 F(xpensi)-.15 E
+-.15(ve)-.25 G 1.488 -.7(,\232 w).15 H(hich).7 E(will cause)117 172 Q/F3 10
+/Times-Italic@0 SF(sendmail)2.5 E F1(to defer connection until a queue run)2.5
+E F2(11)345.57 168 Q F1(.)352.57 172 Q 2.037
+(An unusual case is the \231C\232 \215ag.)142 188.2 R 2.037
+(This \215ag applies to the mailer that the message is)7.037 F(recei)117 200.2
+Q -.15(ve)-.25 G 2.654(df).15 G .153(rom, rather than the mailer being sent to\
+; if set, the domain spec of the sender \(i.e., the)156.454 200.2 R 1.519
+(\231@host.domain\232 part\) is sa)117 212.2 R -.15(ve)-.2 G 4.019(da).15 G
+1.519(nd is appended to an)252.746 212.2 R 4.019(ya)-.15 G 1.52
+(ddresses in the message that do not)354.341 212.2 R
+(already contain a domain spec.)117 224.2 Q -.15(Fo)5 G 2.5(re).15 G
+(xample, a message of the form:)266.11 224.2 Q(From: eric@v)157 240.4 Q
+(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU).65 E -.8(To)157 252.4 S
+2.5(:w).8 G(nj@monet.CS.Berk)179.81 252.4 Q(ele)-.1 E -.65(y.)-.15 G
+(EDU, mckusick).65 E(will be modi\214ed to:)117 268.6 Q(From: eric@v)157 284.8
+Q(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU).65 E -.8(To)157 296.8 S
+2.5(:w).8 G(nj@monet.CS.Berk)179.81 296.8 Q(ele)-.1 E -.65(y.)-.15 G
+(EDU, mckusick@v).65 E(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU).65 E
+F3 9.365(if and only if)117 313 R F1 9.364
+(the \231C\232 \215ag is de\214ned in the mailer corresponding to)207.8 313 R
+(\231eric@v)117 325 Q(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU.).65 E
+<9a>-.7 E(Other \215ags are described in Appendix C.)142 341.2 Q .538
+(The S and R \214elds in the mailer description are per)142 357.4 R .538
+(-mailer re)-.2 F .538(writing sets to be applied to)-.25 F 2.253
+(sender and recipient addresses respecti)117 369.4 R -.15(ve)-.25 G(ly).15 E
+7.253(.T)-.65 G 2.252(hese are applied after the sending domain is)312.995
+369.4 R .546(appended and the general re)117 381.4 R .547
+(writing sets \(numbers one and tw)-.25 F .547(o\) are applied, b)-.1 F .547
+(ut before the out-)-.2 F .458(put re)117 393.4 R .458
+(write \(ruleset four\) is applied.)-.25 F 2.958(At)5.458 G .457
+(ypical use is to append the current domain to addresses)279.646 393.4 R
+(that do not already ha)117 405.4 Q .3 -.15(ve a d)-.2 H 2.5(omain. F).15 F
+(or e)-.15 E(xample, a header of the form:)-.15 E(From: eric)157 421.6 Q
+(might be changed to be:)117 437.8 Q(From: eric@v)157 454 Q(angogh.CS.Berk)-.25
+E(ele)-.1 E -.65(y.)-.15 G(EDU).65 E(or)117 470.2 Q(From: ucb)157 486.4 Q -.25
+(va)-.15 G(x!eric).25 E .186(depending on the domain it is being shipped into.)
+117 502.6 R .186(These sets can also be used to do special pur)5.186 F(-)-.2 E
+(pose output re)117 514.6 Q(writing in cooperation with ruleset four)-.25 E(.)
+-.55 E .228
+(The E \214eld de\214nes the string to use as an end-of-line indication.)142
+530.8 R 2.728(As)5.228 G .228(tring containing only)419.654 530.8 R(ne)117
+542.8 Q(wline is the def)-.25 E 2.5(ault. The)-.1 F
+(usual backslash escapes \(\\r)2.5 E 2.5(,\\)-.4 G(n, \\f, \\b\) may be used.)
+342.87 542.8 Q(Finally)142 559 Q 2.648(,a)-.65 G 2.648(na)179.278 559 S -.18
+(rg)191.366 559 S 2.648(vt).18 G .149(emplate is gi)209.944 559 R -.15(ve)-.25
+G 2.649(na).15 G 2.649(st)282.481 559 S .149(he E \214eld.)291.8 559 R .149
+(It may ha)5.149 F .449 -.15(ve e)-.2 H .149(mbedded spaces.).15 F .149
+(If there is)5.149 F .204(no ar)117 571 R .204(gv with a)-.18 F F0($u)2.704 E
+F1 .204(macro in it,)2.704 F F3(sendmail)2.704 E F1 .204
+(will speak SMTP to the mailer)2.704 F 5.203(.I)-.55 G 2.703(ft)412.648 571 S
+.203(he pathname for this)421.461 571 R(mailer is \231[IPC],)117 583 Q 2.5
+<9a74>-.7 G(he ar)192.4 583 Q(gv should be)-.18 E(IPC $h [)157 599.2 Q F3(port)
+2.5 E F1(])2.5 E(where)117 615.4 Q F3(port)2.5 E F1
+(is the optional port number to connect to.)2.5 E -.15(Fo)142 631.6 S 2.5(re)
+.15 G(xample, the speci\214cations:)162.53 631.6 Q(Mlocal, P=/bin/mail, F=rlsm)
+157 647.8 Q(S=10, R=20, A=mail \255d $u)5 E(Mether)157 659.8 Q 2.35(,P)-.4 G
+13.9(=[IPC], F=meC,)195.89 659.8 R(S=11, R=21, A=IPC $h, M=100000)1.39 E 1.643
+(speci\214es a mailer to do local deli)117 676 R -.15(ve)-.25 G 1.644
+(ry and a mailer for ethernet deli).15 F -.15(ve)-.25 G(ry).15 E 6.644(.T)-.65
+G 1.644(he \214rst is called)436.018 676 R .32 LW 76 685.6 72 685.6 DL 80 685.6
+76 685.6 DL 84 685.6 80 685.6 DL 88 685.6 84 685.6 DL 92 685.6 88 685.6 DL 96
+685.6 92 685.6 DL 100 685.6 96 685.6 DL 104 685.6 100 685.6 DL 108 685.6 104
+685.6 DL 112 685.6 108 685.6 DL 116 685.6 112 685.6 DL 120 685.6 116 685.6 DL
+124 685.6 120 685.6 DL 128 685.6 124 685.6 DL 132 685.6 128 685.6 DL 136 685.6
+132 685.6 DL 140 685.6 136 685.6 DL 144 685.6 140 685.6 DL 148 685.6 144 685.6
+DL 152 685.6 148 685.6 DL 156 685.6 152 685.6 DL 160 685.6 156 685.6 DL 164
+685.6 160 685.6 DL 168 685.6 164 685.6 DL 172 685.6 168 685.6 DL 176 685.6 172
+685.6 DL 180 685.6 176 685.6 DL 184 685.6 180 685.6 DL 188 685.6 184 685.6 DL
+192 685.6 188 685.6 DL 196 685.6 192 685.6 DL 200 685.6 196 685.6 DL 204 685.6
+200 685.6 DL 208 685.6 204 685.6 DL 212 685.6 208 685.6 DL 216 685.6 212 685.6
+DL/F4 5/Times-Roman@0 SF(10)93.6 696 Q/F5 8/Times-Italic@0 SF(Sendmail)3.2 I/F6
+8/Times-Roman@0 SF(must be running setuid to root for this to w)2 E(ork.)-.08 E
+F4(11)93.6 709.6 Q F6(The \231c\232 con\214guration option must be gi)3.2 I
+-.12(ve)-.2 G 2(nf).12 G(or this to be ef)242.04 712.8 Q(fecti)-.2 E -.12(ve)
+-.2 G(.).12 E EP
+%%Page: 43 40
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-43)452.9 60 Q/F1 10/Times-Roman@0 SF(\231local,)117 96 Q 2.649<9a69>-.7
+G 2.649(sl)152.549 96 S .149(ocated in the \214le \231/bin/mail,)161.868 96 R
+2.649<9a74>-.7 G(ak)283.573 96 Q .149(es a pick)-.1 F(y)-.15 E F0<ad72>2.649 E
+F1 .148(\215ag, does local deli)2.649 F -.15(ve)-.25 G(ry).15 E 2.648(,q)-.65 G
+.148(uotes should)453.572 96 R 1.016
+(be stripped from addresses, and multiple users can be deli)117 108 R -.15(ve)
+-.25 G 1.017(red at once; ruleset ten should be).15 F 1.417(applied to sender \
+addresses in the message and ruleset twenty should be applied to recipient)117
+120 R .122(addresses; the ar)117 132 R .123
+(gv to send to a message will be the w)-.18 F .123(ord \231mail,)-.1 F 2.623
+<9a74>-.7 G .123(he w)383.125 132 R .123(ord \231\255d,)-.1 F 2.623<9a61>-.7 G
+.123(nd w)446.644 132 R .123(ords con-)-.1 F 1.484
+(taining the name of the recei)117 144 R 1.484(ving user)-.25 F 6.484(.I)-.55 G
+3.984(fa)288.498 144 S F0<ad72>A F1 1.484
+(\215ag is inserted it will be between the w)3.984 F(ords)-.1 E .288
+(\231mail\232 and \231\255d.)117 156 R 5.288<9a54>-.7 G .289
+(he second mailer is called \231ether)196.394 156 R 1.689 -.7(,\232 i)-.4 H
+2.789(ts).7 G .289(hould be connected to via an IPC con-)348.947 156 R .932(ne\
+ction, it can handle multiple users at once, connections should be deferred, a\
+nd an)117 168 R 3.432(yd)-.15 G(omain)479 168 Q 1.458
+(from the sender address should be appended to an)117 180 R 3.958(yr)-.15 G
+(ecei)340.2 180 Q -.15(ve)-.25 G 3.958(rn).15 G 1.458
+(ame without a domain; sender)377.628 180 R .74
+(addresses should be processed by ruleset ele)117 192 R -.15(ve)-.25 G 3.24(na)
+.15 G .74(nd recipient addresses by ruleset twenty-one.)320.34 192 R
+(There is a 100,000 byte limit on messages passed through this mailer)117 204 Q
+(.)-.55 E F0 2.5(5.3. The)87 228 R(User Database)2.5 E F1 .108(If you ha)127
+244.2 R .408 -.15(ve a ve)-.2 H .109
+(rsion of sendmail with the user database package compiled in, the handling of)
+.15 F(sender and recipient addresses is modi\214ed.)102 256.2 Q
+(The location of this database is controlled with the)127 272.4 Q F0(U)2.5 E F1
+(option.)2.5 E F0 2.5(5.3.1. Structur)102 296.4 R 2.5(eo)-.18 G 2.5(ft)177.92
+296.4 S(he user database)187.08 296.4 Q F1(The database is a sorted \(BT)142
+312.6 Q(ree-based\) structure.)-.35 E(User records are stored with the k)5 E
+-.15(ey)-.1 G(:).15 E/F2 10/Times-Italic@0 SF(user)157 328.8 Q(-name)-.2 E F0
+(:)A F2(\214eld-name)A F1 .128
+(The sorted database format ensures that user records are clustered together)
+117 345 R 5.128(.M)-.55 G .128(eta-information is)432.492 345 R(al)117 357 Q
+-.1(wa)-.1 G(ys stored with a leading colon.).1 E
+(Field names de\214ne both the syntax and semantics of the v)142 373.2 Q 2.5
+(alue. De\214ned)-.25 F(\214elds include:)2.5 E 33.39(maildrop The)117 389.4 R
+(deli)4.872 E -.15(ve)-.25 G 2.372(ry address for this user).15 F 7.372(.T)-.55
+G 2.373(here may be multiple v)349.472 389.4 R 2.373(alues of this)-.25 F 2.675
+(record. In)189 401.4 R(particular)2.675 E 2.675(,m)-.4 G .175
+(ailing lists will ha)284.095 401.4 R .475 -.15(ve o)-.2 H(ne).15 E F2(maildr)
+2.675 E(op)-.45 E F1 .175(record for each user)2.675 F(on the list.)189 413.4 Q
+30.06(mailname The)117 429.6 R 1.026(outgoing mailname for this user)3.526 F
+6.026(.F)-.55 G 1.027(or each outgoing name, there should)353.336 429.6 R .08
+(be an appropriate)189 441.6 R F2(maildr)2.58 E(op)-.45 E F1 .08
+(record for that name to allo)2.58 F 2.58(wr)-.25 G .08(eturn mail.)422.38
+441.6 R .08(See also)5.08 F F2(:default:mailname)189 453.6 Q F1(.)A 25.62
+(mailsender Changes)117 469.8 R(an)3.447 E 3.447(ym)-.15 G .947
+(ail sent to this address to ha)252.404 469.8 R 1.248 -.15(ve t)-.2 H .948
+(he indicated en).15 F -.15(ve)-.4 G .948(lope sender).15 F(.)-.55 E .498(This\
+ is intended for mailing lists, and will normally be the name of an appro-)189
+481.8 R .754(priate -request address.)189 493.8 R .754(It is v)5.754 F .755
+(ery similar to the o)-.15 F(wner)-.25 E(-)-.2 E F2(list)A F1 .755
+(syntax in the alias)3.255 F(\214le.)189 505.8 Q 33.95(fullname The)117 522 R
+(full name of the user)2.5 E(.)-.55 E(of)117 538.2 Q 13.66(\214ce-address The)
+-.25 F(of)2.5 E(\214ce address for this user)-.25 E(.)-.55 E(of)117 554.4 Q
+19.21(\214ce-phone The)-.25 F(of)2.5 E(\214ce phone number for this user)-.25 E
+(.)-.55 E(of)117 570.6 Q(\214ce-f)-.25 E 30.98(ax The)-.1 F(of)2.5 E(\214ce F)
+-.25 E(AX number for this user)-.74 E(.)-.55 E 13.96(home-address The)117 586.8
+R(home address for this user)2.5 E(.)-.55 E 19.51(home-phone The)117 603 R
+(home phone number for this user)2.5 E(.)-.55 E(home-f)117 619.2 Q 31.28
+(ax The)-.1 F(home F)2.5 E(AX number for this user)-.74 E(.)-.55 E 41.73
+(project A)117 635.4 R .856
+(\(short\) description of the project this person is af)3.356 F .855
+(\214liated with.)-.25 F .855(In the Uni-)5.855 F -.15(ve)189 647.4 S
+(rsity this is often just the name of their graduate advisor).15 E(.)-.55 E
+52.28(plan A)117 663.6 R
+(pointer to a \214le from which plan information can be g)2.5 E(athered.)-.05 E
+.924(As of this writing, only a fe)142 679.8 R 3.424(wo)-.25 G 3.424(ft)273.208
+679.8 S .925(hese \214elds are actually being used by sendmail:)282.742 679.8 R
+F2(mail-)3.425 E(dr)117 691.8 Q(op)-.45 E F1(and)2.5 E F2(mailname)2.5 E F1 5
+(.A)C F2(\214ng)211.54 691.8 Q(er)-.1 E F1
+(program that uses the other \214elds is planned.)2.5 E EP
+%%Page: 44 41
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-44 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E 2.5(5.3.2. User)102 96 R
+(database semantics)2.5 E/F1 10/Times-Roman@0 SF .996(When the re)142 112.2 R
+.995(writing rules submit an address to the local mailer)-.25 F 3.495(,t)-.4 G
+.995(he user name is passed)408.93 112.2 R .78(through the alias \214le.)117
+124.2 R .781
+(If no alias is found \(or if the alias points back to the same address\), the)
+5.78 F 1.778(name \(with \231:maildrop\232 appended\) is then used as a k)117
+136.2 R 2.077 -.15(ey i)-.1 H 4.277(nt).15 G 1.777(he user database.)375.985
+136.2 R 1.777(If no match)6.777 F
+(occurs \(or if the maildrop points at the same address\), forw)117 148.2 Q
+(arding is tried.)-.1 E .55(If the \214rst tok)142 164.4 R .551(en of the user\
+ name returned by ruleset 0 is an \231@\232 sign, the user database)-.1 F .626
+(lookup is skipped.)117 176.4 R .625
+(The intent is that the user database will act as a set of def)5.626 F .625
+(aults for a cluster)-.1 F 1.533(\(in our case, the Computer Science Di)117
+188.4 R 1.533(vision\); mail sent to a speci\214c machine should ignore)-.25 F
+(these def)117 200.4 Q(aults.)-.1 E .351
+(When mail is sent, the name of the sending user is look)142 216.6 R .351
+(ed up in the database.)-.1 F .351(If that user)5.351 F .04
+(has a \231mailname\232 record, the v)117 228.6 R .041
+(alue of that record is used as their outgoing name.)-.25 F -.15(Fo)5.041 G
+2.541(re).15 G .041(xample, I)466.189 228.6 R(might ha)117 240.6 Q .3 -.15
+(ve a r)-.2 H(ecord:).15 E 25.94(eric:mailname Eric.Allman@CS.Berk)157 256.8 R
+(ele)-.1 E -.65(y.)-.15 G(EDU).65 E(This w)117 273 Q
+(ould cause my outgoing mail to be sent as Eric.Allman.)-.1 E .757
+(If a \231maildrop\232 is found for the user)142 289.2 R 3.257(,b)-.4 G .757
+(ut no corresponding \231maildrop\232 record e)301.588 289.2 R .757(xists, the)
+-.15 F 1.127(record \231:def)117 301.2 R 1.127(ault:mailname\232 is consulted.)
+-.1 F 1.127(If present, this is the name of a host to o)6.127 F -.15(ve)-.15 G
+1.128(rride the).15 F .625(local host.)117 313.2 R -.15(Fo)5.625 G 3.125(re).15
+G .625(xample, in our case we w)185.515 313.2 R .625
+(ould set it to \231CS.Berk)-.1 F(ele)-.1 E -.65(y.)-.15 G 3.125(EDU\232. The)
+.65 F(ef)3.125 E .625(fect is that)-.25 F(an)117 325.2 Q .881(yone kno)-.15 F
+.882(wn in the database gets their outgoing mail stamped as \231user@CS.Berk)
+-.25 F(ele)-.1 E -.65(y.)-.15 G(EDU\232,).65 E -.2(bu)117 337.2 S 2.5(tp).2 G
+(eople not listed in the database use the local hostname.)137.08 337.2 Q F0 2.5
+(6. O)72 361.2 R(THER CONFIGURA)-.4 E(TION)-.95 E F1 .907
+(There are some con\214guration changes that can be made by recompiling)112
+377.4 R/F2 10/Times-Italic@0 SF(sendmail)3.407 E F1 5.907(.T)C .906
+(his section)460.594 377.4 R
+(describes what changes can be made and what has to be modi\214ed to mak)87
+389.4 Q 2.5(et)-.1 G(hem.)387.95 389.4 Q F0 2.5(6.1. P)87 413.4 R
+(arameters in sr)-.1 E(c/Mak)-.18 E(e\214le)-.1 E F1 .92
+(These parameters are intended to describe the compilation en)127 429.6 R .92
+(vironment, not site polic)-.4 F 2.22 -.65(y, a)-.15 H(nd).65 E
+(should normally be de\214ned in src/Mak)102 441.6 Q(e\214le.)-.1 E 39.5
+(NDBM If)102 457.8 R .665(set, the ne)3.165 F 3.165(wv)-.25 G .664
+(ersion of the DBM library that allo)240.41 457.8 R .664
+(ws multiple databases will be)-.25 F 2.542(used. If)174 469.8 R .042
+(neither NDBM nor NEWDB are set, a much less ef)2.542 F .043
+(\214cient method of alias)-.25 F(lookup is used.)174 481.8 Q 32.84(NEWDB If)
+102 498 R .142(set, use the ne)2.642 F 2.642(wd)-.25 G .142
+(atabase package from Berk)254.44 498 R(ele)-.1 E 2.641(y\()-.15 G .141
+(from 4.4BSD\).)385.817 498 R .141(This package)5.141 F .266
+(is substantially f)174 510 R .267(aster than DBM or NDBM.)-.1 F .267
+(If NEWDB and NDBM are both set,)5.267 F(sendmail will read DBM \214les, b)174
+522 Q(ut will create and use NEWDB \214les.)-.2 E(YPCOMP)102 538.2 Q 19.3 -1.11
+(AT I)-.92 H 3.684(fs)1.11 G 1.184(et together with)188.234 538.2 R F2(both)
+3.684 E F1 1.183(NEWDB and NDBM,)3.683 F F2(sendmail)3.683 E F1 1.183
+(will create both DBM)3.683 F 1.067
+(and NEWDB \214les if and only if the \214le /v)174 550.2 R(ar/yp/Mak)-.25 E
+1.067(e\214le e)-.1 F 1.067(xists and is readable.)-.15 F .501
+(This is intended for compatibility with Sun Microsystems')174 562.2 R F2
+(mkalias)3.001 E F1 .501(program used)3.001 F(on YP masters.)174 574.2 Q 41.73
+(_AIX3 Compile)102 590.4 R(for IBM AIX 3.x.)2.5 E
+(This has only been tested on 3.2.3.)5 E 25.05(SYSTEM5 Set)102 606.6 R
+(all of the compilation parameters appropriate for System V)2.5 E(.)-1.29 E
+36.72(LOCKF Use)102 622.8 R .299(System V)2.799 F F0(lockf)2.799 E F1 .299
+(instead of Berk)2.799 F(ele)-.1 E(y)-.15 E F0(\215ock)2.799 E F1 5.299(.D)C .3
+(ue to the highly unusual seman-)375.012 622.8 R .052
+(tics of locks across forks in)174 634.8 R F0(lockf)2.552 E F1 2.551(,t)C .051
+(his should ne)314.903 634.8 R -.15(ve)-.25 G 2.551(rb).15 G 2.551(eu)387.706
+634.8 S .051(sed unless absolutely nec-)399.697 634.8 R(essary)174 646.8 Q 5
+(.S)-.65 G(et by def)211.4 646.8 Q(ault if SYSTEM5 is set.)-.1 E 33.94
+(SYS5TZ Use)102 663 R(System V time zone semantics.)2.5 E(HASINITGR)102 679.2 Q
+(OUPS)-.4 E .812(Set this if your system has the)174 691.2 R F2(initgr)3.312 E
+(oups\(\))-.45 E F1 .812(call \(if you ha)3.312 F 1.112 -.15(ve m)-.2 H .813
+(ultiple group sup-).15 F 2.5(port\). This)174 703.2 R(is the def)2.5 E
+(ault if SYSTEM5 is)-.1 E F2(not)2.5 E F1(de\214ned or if you are on HPUX.)2.5
+E EP
+%%Page: 45 42
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-45)452.9 60 Q/F1 10/Times-Roman@0 SF(HASUN)102 96 Q 13.19(AME Set)-.35
+F .89(this if you ha)3.39 F 1.19 -.15(ve t)-.2 H(he).15 E/F2 10/Times-Italic@0
+SF(uname)3.39 E F1 .89(\(2\) system call \(or corresponding library routine\).)
+B(Set by def)174 108 Q(ault if SYSTEM5 is set.)-.1 E(HASST)102 124.2 Q -1.11
+(AT)-.93 G 15.42(FS Set)1.11 F .202(this if you ha)2.701 F .502 -.15(ve t)-.2 H
+(he).15 E F2(statfs)2.702 E F1 .202(\(2\) system call.)B .202(This will allo)
+5.202 F 2.702(wy)-.25 G .202(ou to gi)425.822 124.2 R .502 -.15(ve a t)-.25 H
+(empo-).15 E .108(rary f)174 136.2 R .108
+(ailure message to incoming SMTP email when you are lo)-.1 F 2.608(wo)-.25 G
+2.608(nd)441.188 136.2 S .107(isk space.)453.796 136.2 R(It)5.107 E
+(is set by def)174 148.2 Q(ault on 4.4 BSD and OSF/1 systems.)-.1 E(HASUST)102
+164.4 Q 21.54 -1.11(AT S)-.93 H .593(et if you ha)1.11 F .894 -.15(ve t)-.2 H
+(he).15 E F2(ustat)3.094 E F1 .594(\(2\) system call.)B .594
+(This is an alternati)5.594 F .894 -.15(ve i)-.25 H .594(mplementation of).15 F
+.525(disk space control.)174 176.4 R -1.1(Yo)5.525 G 3.025(us)1.1 G .525
+(hould only set one of HASST)278.32 176.4 R -1.11(AT)-.93 G .525(FS or HASUST)
+1.11 F -.83 -1.11(AT ;)-.93 H(the)4.135 E(\214rst is preferred.)174 188.4 Q(_P)
+102 204.6 Q -1.11(AT)-.92 G(H_SENDMAILCF)1.11 E
+(The pathname of the sendmail.cf \214le.)174 216.6 Q(_P)102 232.8 Q -1.11(AT)
+-.92 G(H_SENDMAILFC)1.11 E(The pathname of the sendmail.fc \214le.)174 244.8 Q
+(_P)102 261 Q -1.11(AT)-.92 G(H_SENDMAILPID)1.11 E
+(The pathname of the sendmail.pid \214le.)174 273 Q 26.17(LA_TYPE The)102 289.2
+R(load a)2.5 E -.15(ve)-.2 G(rage type.).15 E(Details are described belo)5 E
+-.65(w.)-.25 G 1.146(The are four b)102 305.4 R 1.146(uilt-in w)-.2 F 1.146
+(ays of computing the load a)-.1 F -.15(ve)-.2 G(rage.).15 E F2(Sendmail)6.147
+E F1 1.147(tries to auto-con\214gure them)3.647 F .267
+(based on imperfect guesses; you can select one using the)102 317.4 R F2(cc)
+2.766 E F1(option)2.766 E F0(\255DLA_TYPE=)2.766 E F2(type)A F1 2.766(,w)C
+(here)467.364 317.4 Q F2(type)2.766 E F1(is:)102 329.4 Q 34.51(LA_INT The)102
+345.6 R -.1(ke)2.978 G .478(rnel stores the load a).1 F -.15(ve)-.2 G .479
+(rage in the k).15 F .479(ernel as an array of long inte)-.1 F 2.979(gers. The)
+-.15 F(actual v)174 357.6 Q(alues are scaled by a f)-.25 E(actor FSCALE \(def)
+-.1 E(ault 256\).)-.1 E(LA_FLO)102 373.8 Q 22.63 -1.11(AT T)-.35 H 1.118(he k)
+1.11 F 1.117(ernel stores the load a)-.1 F -.15(ve)-.2 G 1.117(rage in the k)
+.15 F 1.117(ernel as an array of double precision)-.1 F(\215oats.)174 385.8 Q
+25.05(LA_SUBR Call)102 402 R(the)2.5 E F2 -.1(ge)2.5 G(tloadavg).1 E F1
+(routine to get the load a)2.5 E -.15(ve)-.2 G(rage as an array of doubles.).15
+E(LA_ZER)102 418.2 Q 27.96(OA)-.4 G -.1(lwa)181.22 418.2 S
+(ys return zero as the load a).1 E -.15(ve)-.2 G 2.5(rage. This).15 F(is the f)
+2.5 E(allback case.)-.1 E .738(If type)102 434.4 R/F3 9/Times-Roman@0 SF
+(LA_INT)3.238 E F1(or)3.238 E F3(LA_FLO)3.238 E -.999(AT)-.315 G F1 .738
+(is speci\214ed, you may also need to specify)4.237 F F3(_P)3.239 E -.999(AT)
+-.828 G(H_UNIX).999 E F1 .739(\(the path to)3.239 F .269
+(your system binary\) and)102 446.4 R F3(LA_A)2.769 E(VENR)-1.215 E(UN)-.36 E
+F1 .269(\(the name of the v)2.769 F .269(ariable containing the load a)-.25 F
+-.15(ve)-.2 G .269(rage in the).15 F -.1(ke)102 458.4 S(rnel; usually \231_a).1
+E -.15(ve)-.2 G(nrun\232 or \231a).15 E -.15(ve)-.2 G(nrun\232\).).15 E F0 2.5
+(6.2. P)87 482.4 R(arameters in sr)-.1 E(c/conf)-.18 E(.h)-.15 E F1 -.15(Pa)127
+498.6 S .895(rameters and compilation options are de\214ned in conf.h.).15 F
+.896(Most of these need not normally)5.895 F .193(be tweak)102 510.6 R .192
+(ed; common parameters are all in sendmail.cf.)-.1 F(Ho)5.192 E(we)-.25 E -.15
+(ve)-.25 G .992 -.4(r, t).15 H .192(he sizes of certain primiti).4 F .492 -.15
+(ve ve)-.25 H(c-).15 E(tors, etc., are included in this \214le.)102 522.6 Q
+(The numbers follo)5 E(wing the parameters are their def)-.25 E(ault v)-.1 E
+(alue.)-.25 E 1.909(MAXLINE [1024])102 538.8 R 1.909
+(The maximum line length of an)190.309 538.8 R 4.409(yi)-.15 G 1.909
+(nput line.)338.273 538.8 R 1.91(If message lines e)6.909 F 1.91(xceed this)
+-.15 F .575(length the)188.4 550.8 R 3.075(yw)-.15 G .575
+(ill still be processed correctly; ho)243.84 550.8 R(we)-.25 E -.15(ve)-.25 G
+1.375 -.4(r, h).15 H .575(eader lines, con\214gura-).4 F
+(tion \214le lines, alias lines, etc., must \214t within this limit.)188.4
+562.8 Q(MAXN)102 579 Q(AME [256])-.35 E(The maximum length of an)9.82 E 2.5(yn)
+-.15 G(ame, such as a host or a user name.)309.63 579 Q .23(MAXPV [40])102
+595.2 R .231(The maximum number of parameters to an)188.63 595.2 R 2.731(ym)
+-.15 G(ailer)376.455 595.2 Q 5.231(.T)-.55 G .231(his limits the number of)
+407.516 595.2 R .376(recipients that may be passed in one transaction.)188.4
+607.2 R .375(It can be set to an)5.376 F 2.875(ya)-.15 G(rbitrary)474.01 607.2
+Q .875(number abo)188.4 619.2 R 1.175 -.15(ve a)-.15 H .876(bout 10, since).15
+F F2(sendmail)3.376 E F1 .876(will break up a deli)3.376 F -.15(ve)-.25 G .876
+(ry into smaller).15 F .887(batches as needed.)188.4 631.2 R 3.387(Ah)5.887 G
+.887(igher number may reduce load on your system, ho)285.808 631.2 R(w-)-.25 E
+-2.15 -.25(ev e)188.4 643.2 T -.55(r.).25 G(MAXA)102 659.4 Q -.18(TO)-1.11 G
+2.558(M[).18 G 8.26(100] The)159.368 659.4 R .058
+(maximum number of atoms \(tok)2.558 F .059(ens\) in a single address.)-.1 F
+-.15(Fo)5.059 G 2.559(re).15 G .059(xample, the)457.281 659.4 R
+(address \231eric@CS.Berk)188.4 671.4 Q(ele)-.1 E -.65(y.)-.15 G(EDU\232 is se)
+.65 E -.15(ve)-.25 G 2.5(na).15 G(toms.)367.93 671.4 Q .113(MAXMAILERS [25])102
+687.6 R .112(The maximum number of mailers that may be de\214ned in the con\
+\214guration \214le.).02 F(MAXR)102 703.8 Q(WSETS [100])-.55 E
+(The maximum number of re).01 E(writing sets that may be de\214ned.)-.25 E EP
+%%Page: 46 43
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-46 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF
+(MAXPRIORITIES [25])102 96 Q 2.481(The maximum number of v)188.4 108 R 2.482
+(alues for the \231Precedence:\232 \214eld that may be)-.25 F
+(de\214ned \(using the)188.4 120 Q F0(P)2.5 E F1(line in sendmail.cf\).)2.5 E
+(MAXUSERENVIR)102 136.2 Q(ON [40])-.4 E .399
+(The maximum number of items in the user en)188.4 148.2 R .399
+(vironment that will be passed to)-.4 F(subordinate mailers.)188.4 160.2 Q -.1
+(QU)102 176.4 S(EUESIZE [1000]).1 E
+(The maximum number of entries that will be processed in a single queue run.)
+2.35 E(MAXMXHOSTS [20])102 192.6 Q
+(The maximum number of MX records we will accept for an)188.4 204.6 Q 2.5(ys)
+-.15 G(ingle host.)439.03 204.6 Q(MAXIP)102 220.8 Q .968(ADDR [16])-.92 F .968
+(The maximum number of numeric IP addresses we will accept for this host.)7.61
+F(This does not limit the number the number of addresses for other hosts.)188.4
+232.8 Q 2.851(An)102 249 S .351(umber of other compilation options e)117.071
+249 R 2.851(xist. These)-.15 F .35
+(specify whether or not speci\214c code should be)2.851 F(compiled in.)102 261
+Q(DEB)102 277.2 Q 49.56(UG If)-.1 F 1.226(set, deb)3.726 F 1.226
+(ugging information is compiled in.)-.2 F 2.827 -.8(To a)6.226 H 1.227
+(ctually get the deb).8 F(ugging)-.2 E .4(output, the)188.4 289.2 R F0<ad64>2.9
+E F1 .4(\215ag must be used.)2.9 F F0 .4(WE STR)5.4 F(ONGL)-.3 E 2.9(YR)-.92 G
+.4(ECOMMEND THA)412.05 289.2 R(T)-.95 E .97(THIS BE LEFT ON.)188.4 301.2 R F1
+.97(Some people, belie)5.97 F .97(ving that it w)-.25 F .97
+(as a security hole \(it)-.1 F -.1(wa)188.4 313.2 S(s, once\) ha).1 E .3 -.15
+(ve t)-.2 H(urned it of).15 E 2.5(fa)-.25 G(nd thus crippled deb)309.05 313.2 Q
+(uggers.)-.2 E 41.69(NETINET If)102 329.4 R .829
+(set, support for Internet protocol netw)3.33 F .829(orking is compiled in.)-.1
+F(Pre)5.829 E .829(vious v)-.25 F(er)-.15 E(-)-.2 E .006(sions of)188.4 341.4 R
+F0(sendmail)2.506 E F1 .006(referred to this as)2.506 F/F2 9/Times-Roman@0 SF
+-.36(DA)2.506 G(EMON).36 E F1 2.506(;t)C .006(his old usage is no)382.57 341.4
+R 2.506(wi)-.25 G(ncorrect.)468.74 341.4 Q 48.35(NETISO If)102 357.6 R .143
+(set, support for ISO protocol netw)2.643 F .142
+(orking is compiled in \(it may be appropri-)-.1 F
+(ate to #de\214ne this in the Mak)188.4 369.6 Q(e\214le instead of conf.h\).)
+-.1 E 63.35(LOG If)102 385.8 R .5(set, the)3 F/F3 10/Times-Italic@0 SF(syslo)3
+E(g)-.1 E F1 .5(routine in use at some sites is used.)3 F .5(This mak)5.5 F .5
+(es an informa-)-.1 F .504
+(tional log record for each message processed, and mak)188.4 397.8 R .504
+(es a higher priority log)-.1 F(record for internal system errors.)188.4 409.8
+Q(MA)102 426 Q 16.12(TCHGECOS Compile)-1.11 F 3.555(in the code to do `)6.055 F
+3.555(`fuzzy matching')-.74 F 6.055('o)-.74 G 6.055(nt)404.22 426 S 3.555
+(he GECOS \214eld in)418.055 426 R 2.5(/etc/passwd. This)188.4 438 R
+(also requires that option G be turned on.)2.5 E -.35(NA)102 454.2 S 18.15
+(MED_BIND Compile).35 F .413(in code to use the Berk)2.913 F(ele)-.1 E 2.912
+(yI)-.15 G .412(nternet Name Domain \(BIND\) serv)342.41 454.2 R .412(er to)
+-.15 F(resolv)188.4 466.2 Q 2.5(eT)-.15 G(CP/IP host names.)225.74 466.2 Q(NO)
+102 482.4 Q 38.76(TUNIX If)-.4 F .247
+(you are using a non-UNIX mail format, you can set this \215ag to turn of)2.747
+F 2.748(fs)-.25 G(pe-)491.23 482.4 Q
+(cial processing of UNIX-style \231From \232 lines.)188.4 494.4 Q -.1(QU)102
+510.6 S 50.12(EUE This).1 F 1.559
+(\215ag should be set to compile in the queueing code.)4.06 F 1.559
+(If this is not set,)6.559 F
+(mailers must accept the mail immediately or it will be returned to the sender)
+188.4 522.6 Q(.)-.55 E(SETPR)102 538.8 Q 12.63(OCTITLE If)-.4 F(de\214ned,)3.88
+E F3(sendmail)3.88 E F1 1.381(will change its)3.881 F F3(ar)3.881 E(gv)-.37 E
+F1 1.381(array to indicate its current status.)3.881 F .207
+(This can be used in conjunction with the)188.4 550.8 R F3(ps)2.707 E F1 .206
+(command to \214nd out just what it')2.707 F(s)-.55 E(up to.)188.4 562.8 Q
+57.78(SMTP If)102 579 R .756(set, the code to handle user and serv)3.256 F .756
+(er SMTP will be compiled in.)-.15 F .756(This is)5.756 F 2.507
+(only necessary if your machine has some mailer that speaks SMTP \(this)188.4
+591 R(means most machines e)188.4 603 Q -.15(ve)-.25 G(rywhere\).).15 E(UGL)102
+619.2 Q 30.46(YUUCP If)-1 F 1.023(you ha)3.523 F 1.323 -.15(ve a U)-.2 H 1.024
+(UCP host adjacent to you which is not running a reasonable).15 F -.15(ve)188.4
+631.2 S .112(rsion of).15 F F3(rmail)2.612 E F1 2.612(,y)C .112(ou will ha)
+263.026 631.2 R .412 -.15(ve t)-.2 H 2.612(os).15 G .112
+(et this \215ag to include the \231remote from sys-)329.234 631.2 R .031
+(name\232 info on the from line.)188.4 643.2 R .032
+(Otherwise, UUCP gets confused about where the)5.032 F(mail came from.)188.4
+655.2 Q 44.45(USERDB Include)102 671.4 R(the)3.449 E F0(experimental)3.449 E F1
+(Berk)3.449 E(ele)-.1 E 3.449(yu)-.15 G .949(ser information database package.)
+341.356 671.4 R(This)5.948 E .27(adds a ne)188.4 683.4 R 2.77(wl)-.25 G -2.15
+-.25(ev e)238.67 683.4 T 2.77(lo).25 G 2.77(fl)262.7 683.4 S .27(ocal name e)
+271.58 683.4 R .27(xpansion between aliasing and forw)-.15 F 2.77(arding. It)
+-.1 F(also uses the NEWDB package.)188.4 695.4 Q
+(This may change in future releases.)5 E(IDENTPR)102 711.6 Q -1.88 -.4(OT O)-.4
+H .376(Compile in the IDENT protocol as de\214ned in RFC 1413.)188.4 711.6 R
+.375(This def)5.375 F .375(aults on for)-.1 F 1.053(all systems e)188.4 723.6 R
+1.053(xcept Ultrix, which apparently has the interesting \231feature\232 that)
+-.15 F EP
+%%Page: 47 44
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-47)452.9 60 Q/F1 10/Times-Roman@0 SF .83(when it recei)188.4 96 R -.15
+(ve)-.25 G 3.33(sa\231).15 G .83
+(host unreachable\232 message it closes all open connections)270.18 96 R 1.921
+(to that host.)188.4 108 R 1.921(Since some \214re)6.921 F -.1(wa)-.25 G 1.922
+(ll g).1 F(ate)-.05 E -.1(wa)-.25 G 1.922(ys send this error code when you).1 F
+2.055
+(access an unauthorized port \(such as 113, used by IDENT\), Ultrix cannot)
+188.4 120 R(recei)188.4 132 Q .3 -.15(ve e)-.25 H(mail from such hosts.).15 E
+F0 2.5(6.3. Con\214guration)87 156 R(in sr)2.5 E(c/conf)-.18 E(.c)-.15 E F1
+(The follo)127 172.2 Q(wing changes can be made in conf.c.)-.25 E F0 2.5
+(6.3.1. Built-in)102 196.2 R(Header Semantics)2.5 E F1 1.248
+(Not all header semantics are de\214ned in the con\214guration \214le.)142
+212.4 R 1.248(Header lines that should)6.248 F .305(only be included by certai\
+n mailers \(as well as other more obscure semantics\) must be speci\214ed)117
+224.4 R .046(in the)117 236.4 R/F2 10/Times-Italic@0 SF(HdrInfo)2.546 E F1 .046
+(table in)2.546 F F2(conf)2.546 E(.c)-.15 E F1 5.046(.T)C .047
+(his table contains the header name \(which should be in all lo)246.836 236.4 R
+(wer)-.25 E(case\) and a set of header control \215ags \(described belo)117
+248.4 Q(w\), The \215ags are:)-.25 E(H_A)117 264.6 Q 30.97(CHECK Normally)-.4 F
+.007(when the check is made to see if a header line is compatible with)2.508 F
+2.94(am)203.4 276.6 S(ailer)218.56 276.6 Q(,)-.4 E F2(sendmail)2.94 E F1 .441
+(will not delete an e)2.94 F .441(xisting line.)-.15 F .441
+(If this \215ag is set,)5.441 F F2(send-)2.941 E(mail)203.4 288.6 Q F1 .152
+(will delete e)2.652 F -.15(ve)-.25 G 2.652(ne).15 G .152
+(xisting header lines.)293.998 288.6 R .152
+(That is, if this bit is set and the)5.152 F 1.425(mailer does not ha)203.4
+300.6 R 1.725 -.15(ve \215)-.2 H 1.425
+(ag bits set that intersect with the required mailer).15 F 2.204
+(\215ags in the header de\214nition in sendmail.cf, the header line is)203.4
+312.6 R F2(always)4.703 E F1(deleted.)203.4 324.6 Q 51.13(H_EOH If)117 340.8 R
+.206(this header \214eld is set, treat it lik)2.705 F 2.706(eab)-.1 G .206
+(lank line, i.e., it will signal the end)363.948 340.8 R
+(of the header and the be)203.4 352.8 Q(ginning of the message te)-.15 E(xt.)
+-.15 E 39.45(H_FORCE Add)117 369 R 2.039(this header entry e)4.539 F -.15(ve)
+-.25 G 4.539(ni).15 G 4.539(fo)326.225 369 S 2.038(ne e)339.094 369 R 2.038
+(xisted in the message before.)-.15 F 2.038(If a)7.038 F 2.188
+(header entry does not ha)203.4 381 R 2.488 -.15(ve t)-.2 H 2.188(his bit set,)
+.15 F F2(sendmail)4.688 E F1 2.189(will not add another)4.689 F .62
+(header line if a header line of this name already e)203.4 393 R 3.12
+(xisted. This)-.15 F -.1(wo)3.12 G .62(uld nor).1 F(-)-.2 E
+(mally be used to stamp the message by e)203.4 405 Q -.15(ve)-.25 G
+(ryone who handled it.).15 E(H_TRA)117 421.2 Q 39.3(CE If)-.4 F 1.043
+(set, this is a timestamp \(trace\) \214eld.)3.543 F 1.044
+(If the number of trace \214elds in a)6.043 F .706(message e)203.4 433.2 R .705
+(xceeds a preset amount the message is returned on the assump-)-.15 F
+(tion that it has an aliasing loop.)203.4 445.2 Q 46.67(H_RCPT If)117 461.4 R
+.332(set, this \214eld contains recipient addresses.)2.832 F .332
+(This is used by the)5.332 F F0<ad74>2.832 E F1 .333(\215ag to)2.833 F 1.349
+(determine who to send to when it is collecting recipients from the mes-)203.4
+473.4 R(sage.)203.4 485.4 Q(H_FR)117 501.6 Q 43.74(OM This)-.4 F 1.673
+(\215ag indicates that this \214eld speci\214es a sender)4.173 F 6.674(.T)-.55
+G 1.674(he order of these)432.058 501.6 R .883(\214elds in the)203.4 513.6 R F2
+(HdrInfo)3.383 E F1 .883(table speci\214es)3.383 F F2(sendmail')3.383 E(s)-.4 E
+F1 .883(preference for which \214eld)3.383 F(to return error messages to.)203.4
+525.6 Q(Let')117 541.8 Q 2.5(sl)-.55 G(ook at a sample)142.28 541.8 Q F2
+(HdrInfo)2.5 E F1(speci\214cation:)2.5 E EP
+%%Page: 48 45
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-48 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(struct hdrinfo)
+157 96 Q(HdrInfo[] =)258.19 96 Q({)157 108 Q
+(/* originator \214elds, most to least signi\214cant)189.5 120 Q(*/)5 E 14.72
+("resent-sender", H_FR)177 132 R(OM,)-.4 E 21.38("resent-from", H_FR)177 144 R
+(OM,)-.4 E 41.93("sender", H_FR)177 156 R(OM,)-.4 E 48.59("from", H_FR)177 168
+R(OM,)-.4 E 29.15("full-name", H_A)177 180 R(CHECK,)-.4 E
+(/* destination \214elds */)189.5 192 Q 60.25("to", H_RCPT)177 204 R(,)-.74 E
+33.04("resent-to", H_RCPT)177 216 R(,)-.74 E 59.15("cc", H_RCPT)177 228 R(,)
+-.74 E(/* message identi\214cation and control */)189.5 240 Q 34.15
+("message", H_EOH,)177 252 R("te)177 264 Q 53.18(xt", H_EOH,)-.15 F
+(/* trace \214elds */)189.5 276 Q("recei)177 288 Q -.15(ve)-.25 G 34.56
+(d", H_TRA).15 F(CE|H_FORCE,)-.4 E 49.53(NULL, 0,)177 312 R(};)157 324 Q 2.435
+(This structure indicates that the \231T)117 340.2 R 2.435
+(o:\232, \231Resent-T)-.8 F 2.435
+(o:\232, and \231Cc:\232 \214elds all specify recipient)-.8 F 3.162
+(addresses. An)117 352.2 R 3.162<7999>-.15 G .661(Full-Name:\232 \214eld will \
+be deleted unless the required mailer \215ag \(indicated in)188.154 352.2 R
+.245(the con\214guration \214le\) is speci\214ed.)117 364.2 R .245
+(The \231Message:\232 and \231T)5.245 F -.15(ex)-.7 G .246
+(t:\232 \214elds will terminate the header;).15 F 1.936
+(these are used by random dissenters around the netw)117 376.2 R 1.936(ork w)
+-.1 F 4.436(orld. The)-.1 F(\231Recei)4.436 E -.15(ve)-.25 G 1.936
+(d:\232 \214eld will).15 F(al)117 388.2 Q -.1(wa)-.1 G
+(ys be added, and can be used to trace messages.).1 E .445
+(There are a number of important points here.)142 404.4 R .446
+(First, header \214elds are not added automati-)5.446 F .657
+(cally just because the)117 416.4 R 3.157(ya)-.15 G .657(re in the)216.678
+416.4 R/F2 10/Times-Italic@0 SF(HdrInfo)3.157 E F1 .657(structure; the)3.157 F
+3.157(ym)-.15 G .656(ust be speci\214ed in the con\214guration)358.23 416.4 R
+.727(\214le in order to be added to the message.)117 428.4 R(An)5.728 E 3.228
+(yh)-.15 G .728(eader \214elds mentioned in the con\214guration \214le)312.982
+428.4 R -.2(bu)117 440.4 S 3.24(tn).2 G .74(ot mentioned in the)137.82 440.4 R
+F2(HdrInfo)3.24 E F1 .74(structure ha)3.24 F 1.04 -.15(ve d)-.2 H(ef).15 E .74
+(ault processing performed; that is, the)-.1 F 3.24(ya)-.15 G(re)496.23 440.4 Q
+1.374(added unless the)117 452.4 R 3.874(yw)-.15 G 1.374
+(ere in the message already)201.792 452.4 R 6.375(.S)-.65 G 1.375(econd, the)
+326.595 452.4 R F2(HdrInfo)3.875 E F1 1.375(structure only speci\214es)3.875 F
+.324
+(cliched processing; certain headers are processed specially by ad hoc code re)
+117 464.4 R -.05(ga)-.15 G .324(rdless of the sta-).05 F .48
+(tus speci\214ed in)117 476.4 R F2(HdrInfo)2.98 E F1 5.48(.F)C .481(or e)226.55
+476.4 R .481(xample, the \231Sender:\232 and \231From:\232 \214elds are al)-.15
+F -.1(wa)-.1 G .481(ys scanned on).1 F(ARP)117 490.4 Q .75
+(ANET mail to determine the sender)-.92 F/F3 7/Times-Roman@0 SF(12)282.31 486.4
+Q F1 3.251(;t)289.31 490.4 S .751
+(his is used to perform the \231return to sender\232 func-)298.121 490.4 R
+2.977(tion. The)117 502.4 R .476(\231From:\232 and \231Full-Name:\232 \214elds\
+ are used to determine the full name of the sender if)2.977 F
+(possible; this is stored in the macro)117 514.4 Q F0($x)2.5 E F1
+(and used in a number of w)2.5 E(ays.)-.1 E F0 2.5(6.3.2. Restricting)102 538.4
+R(Use of Email)2.5 E F1 .149
+(If it is necessary to restrict mail through a relay)142 554.6 R 2.649(,t)-.65
+G(he)339.75 554.6 Q F2 -.15(ch)2.65 G(ec).15 E(kcompat)-.2 E F1 .15
+(routine can be modi\214ed.)2.65 F .163(This routine is called for e)117 566.6
+R -.15(ve)-.25 G .163(ry recipient address.).15 F .163(It returns an e)5.163 F
+.163(xit status indicating the status of)-.15 F .895(the message.)117 578.6 R
+.895(The status)5.895 F/F4 9/Times-Roman@0 SF(EX_OK)3.395 E F1 .895
+(accepts the address,)3.395 F F4(EX_TEMPF)3.395 E(AIL)-.666 E F1 .895
+(queues the message for a)3.395 F .264(later try)117 590.6 R 2.764(,a)-.65 G
+.264(nd other v)157.698 590.6 R .264(alues \(commonly)-.25 F F4(EX_UN)2.764 E
+-1.215(AVA)-.315 G(ILABLE)1.215 E F1 2.764(\)r)C .264(eject the message.)
+358.375 590.6 R .263(It is up to)5.264 F F2 -.15(ch)2.763 G(ec).15 E(k-)-.2 E
+(compat)117 602.6 Q F1 .429(to print an error message \(using)2.929 F F2(usr)
+2.929 E(err)-.37 E F1 2.929(\)i)C 2.929(ft)315.032 602.6 S .43
+(he message is rejected.)324.071 602.6 R -.15(Fo)5.43 G 2.93(re).15 G(xample,)
+443.39 602.6 Q F2 -.15(ch)2.93 G(ec).15 E(k-)-.2 E(compat)117 614.6 Q F1
+(could read:)2.5 E .32 LW 76 669.2 72 669.2 DL 80 669.2 76 669.2 DL 84 669.2 80
+669.2 DL 88 669.2 84 669.2 DL 92 669.2 88 669.2 DL 96 669.2 92 669.2 DL 100
+669.2 96 669.2 DL 104 669.2 100 669.2 DL 108 669.2 104 669.2 DL 112 669.2 108
+669.2 DL 116 669.2 112 669.2 DL 120 669.2 116 669.2 DL 124 669.2 120 669.2 DL
+128 669.2 124 669.2 DL 132 669.2 128 669.2 DL 136 669.2 132 669.2 DL 140 669.2
+136 669.2 DL 144 669.2 140 669.2 DL 148 669.2 144 669.2 DL 152 669.2 148 669.2
+DL 156 669.2 152 669.2 DL 160 669.2 156 669.2 DL 164 669.2 160 669.2 DL 168
+669.2 164 669.2 DL 172 669.2 168 669.2 DL 176 669.2 172 669.2 DL 180 669.2 176
+669.2 DL 184 669.2 180 669.2 DL 188 669.2 184 669.2 DL 192 669.2 188 669.2 DL
+196 669.2 192 669.2 DL 200 669.2 196 669.2 DL 204 669.2 200 669.2 DL 208 669.2
+204 669.2 DL 212 669.2 208 669.2 DL 216 669.2 212 669.2 DL/F5 5/Times-Roman@0
+SF(12)93.6 679.6 Q/F6 8/Times-Roman@0 SF(Actually)3.2 I 2.632(,t)-.52 G .632
+(his is no longer true in SMTP; this information is contained in the en)132.488
+682.8 R -.12(ve)-.32 G 2.631(lope. The).12 F .631(older ARP)2.631 F .631
+(ANET protocols did)-.736 F(not completely distinguish en)72 692.4 Q -.12(ve)
+-.32 G(lope from header).12 E(.)-.44 E EP
+%%Page: 49 46
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-49)452.9 60 Q/F1 9/Times-Roman@0 SF(int)157 94.8 Q
+(checkcompat\(to, e\))157 105.6 Q(re)175 116.4 Q(gister ADDRESS *to;)-.135 E
+(re)175 127.2 Q(gister ENVELOPE *e;)-.135 E({)157 138 Q(re)175 148.8 Q
+(gister ST)-.135 E(AB *s;)-.837 E 2.25(s=s)175 170.4 S(tab\("pri)191.578 170.4
+Q -.225(va)-.225 G(te", ST_MAILER, ST_FIND\);).225 E
+(if \(s != NULL && e\255>e_from.q_mailer != LocalMailer &&)175 181.2 Q
+(to->q_mailer == s->s_mailer\))184 192 Q({)175 202.8 Q(usrerr\("No pri)193
+213.6 Q -.225(va)-.225 G(te net mail allo).225 E(wed through this machine"\);)
+-.225 E(return \(EX_UN)193 224.4 Q -1.215(AVA)-.315 G(ILABLE\);)1.215 E(})175
+235.2 Q(if \(MsgSize > 50000 && to\255>q_mailer != LocalMailer\))175 246 Q({)
+175 256.8 Q(usrerr\("Message too lar)193 267.6 Q(ge for non-local deli)-.162 E
+-.135(ve)-.225 G(ry"\);).135 E(NoReturn = TR)193 278.4 Q(UE;)-.36 E
+(return \(EX_UN)193 289.2 Q -1.215(AVA)-.315 G(ILABLE\);)1.215 E(})175 300 Q
+(return \(EX_OK\);)175 310.8 Q(})157 321.6 Q/F2 10/Times-Roman@0 SF .205
+(This w)117 337.8 R .205
+(ould reject messages greater than 50000 bytes unless the)-.1 F 2.705(yw)-.15 G
+.205(ere local.)387.09 337.8 R(The)5.205 E/F3 10/Times-Italic@0 SF(NoReturn)
+2.705 E F2(\215ag)2.705 E 1.196(can be sent to suppress the return of the actu\
+al body of the message in the error return.)117 349.8 R(The)6.197 E(actual use\
+ of this routine is highly dependent on the implementation, and use should be \
+limited.)117 361.8 Q F0 2.5(6.3.3. Load)102 385.8 R -.6 -1(Av e)2.5 H
+(rage Computation)1 E F2 .18(The routine)142 402 R F3 -.1(ge)2.68 G(tla).1 E F2
+.18(should return an approximation of the current system load a)2.68 F -.15(ve)
+-.2 G .18(rage as an).15 F(inte)117 414 Q(ger)-.15 E 5(.T)-.55 G
+(here are four v)157.68 414 Q
+(ersions included on compilation \215ags as described abo)-.15 E -.15(ve)-.15 G
+(.).15 E F0 2.5(6.3.4. New)102 438 R(Database Map Classes)2.5 E F2(Ne)142 454.2
+Q 2.875(wk)-.25 G .675 -.15(ey m)168.405 454.2 T .375(aps can be added by crea\
+ting a class initialization function and a lookup func-).15 F 2.5(tion. These)
+117 466.2 R(are then added to the routine)2.5 E F3(setupmaps.)2.5 E F2
+(The initialization function is called as)142 482.4 Q F3(xxx)157 498.6 Q F2
+(_map_init\(MAP *map, char *mapname, char *ar)A(gs\))-.18 E(The)117 514.8 Q F3
+(map)2.555 E F2 .055(is an internal data structure.)2.555 F(The)5.055 E F3
+(mapname)2.555 E F2 .054(is the name of the map \(used for error mes-)2.554 F
+2.819(sages\). The)117 526.8 R F3(ar)2.819 E(gs)-.37 E F2 .32(is a pointer to \
+the rest of the con\214guration \214le line; \215ags and \214lenames can be)
+2.819 F -.15(ex)117 538.8 S .675(tracted from this line.).15 F .675
+(The initialization function must return)5.675 F F1(TR)3.175 E(UE)-.36 E F2
+.674(if it successfully opened)3.174 F(the map,)117 550.8 Q F1 -.666(FA)2.5 G
+(LSE).666 E F2(otherwise.)2.5 E(The lookup function is called as)142 567 Q F3
+(xxx)157 583.2 Q F2(_map_lookup\(MAP *map, char b)A(uf[], int b)-.2 E
+(ufsize, char **a)-.2 E 1.3 -.65(v, i)-.2 H(nt *statp\)).65 E(The)117 599.4 Q
+F3(map)3.475 E F2 .975(de\214nes the map internally)3.475 F 5.975(.T)-.65 G
+.975(he parameters)277.18 599.4 R F3 -.2(bu)3.475 G(f).2 E F2(and)3.475 E F3
+-.2(bu)3.475 G(fsize).2 E F2(ha)3.476 E 1.276 -.15(ve t)-.2 H .976(he input k)
+.15 F -.15(ey)-.1 G 5.976(.T)-.5 G(his)492.33 599.4 Q .043
+(may be \(and often is\) used destructi)117 611.4 R -.15(ve)-.25 G(ly).15 E
+5.043(.T)-.65 G(he)289.831 611.4 Q F3(av)2.543 E F2 .043(is a list of ar)2.543
+F .042(guments passed in from the re)-.18 F(write)-.25 E 3.654(line. The)117
+623.4 R 1.154(lookup function should return a pointer to the ne)3.654 F 3.655
+(wv)-.25 G 3.655(alue. IF)378.335 623.4 R 1.155(the map lookup f)3.655 F(ails,)
+-.1 E F3(*statp)117 635.4 Q F2 1.272(should be set to an e)3.772 F 1.272
+(xit status code; in particular)-.15 F 3.772(,i)-.4 G 3.771(ts)357.652 635.4 S
+1.271(hould be set to)368.093 635.4 R F1(EX_TEMPF)3.771 E(AIL)-.666 E F2(if)
+3.771 E(reco)117 647.4 Q -.15(ve)-.15 G(ry is to be attempted by the higher le)
+.15 E -.15(ve)-.25 G 2.5(lc).15 G(ode.)308.76 647.4 Q F0 2.5(6.3.5. Queueing)
+102 671.4 R(Function)2.5 E F2 .782(The routine)142 687.6 R F3(shouldqueue)3.282
+E F2 .783(is called to decide if a message should be queued or processed)3.283
+F(immediately)117 699.6 Q 6.619(.T)-.65 G 1.618
+(ypically this compares the message priority to the current load a)180.779
+699.6 R -.15(ve)-.2 G 4.118(rage. The).15 F(def)117 711.6 Q
+(ault de\214nition is:)-.1 E EP
+%%Page: 50 47
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-50 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(bool)157 96 Q
+(shouldqueue\(pri, ctime\))157 108 Q(long pri;)175 120 Q(time_t ctime;)175 132
+Q({)157 144 Q(if \(CurrentLA < QueueLA\))175 156 Q(return \(F)193 168 Q
+(ALSE\);)-.74 E(if \(CurrentLA >= RefuseLA\))175 180 Q(return \(TR)193 192 Q
+(UE\);)-.4 E(return \(pri > \(QueueF)175 204 Q
+(actor / \(CurrentLA \255 QueueLA + 1\)\)\);)-.15 E(})157 216 Q 2.062
+(If the current load a)117 232.2 R -.15(ve)-.2 G 2.062(rage \(global v).15 F
+(ariable)-.25 E/F2 10/Times-Italic@0 SF(Curr)4.562 E(entLA)-.37 E F1 4.562(,w)C
+2.062(hich is set before this function is)361.636 232.2 R 1.058
+(called\) is less than the lo)117 244.2 R 3.558(wt)-.25 G 1.058
+(hreshold load a)234.198 244.2 R -.15(ve)-.2 G 1.058(rage \(option).15 F F0(x)
+3.557 E F1 3.557(,v)C(ariable)375.526 244.2 Q F2(QueueLA)3.557 E F1(\),)A F2
+(shouldqueue)3.557 E F1(returns)117 256.2 Q/F3 9/Times-Roman@0 SF -.666(FA)
+2.586 G(LSE).666 E F1 .086(immediately \(that is, it should)2.586 F F2(not)
+2.586 E F1 2.586(queue\). If)2.586 F .086(the current load a)2.586 F -.15(ve)
+-.2 G .087(rage e).15 F .087(xceeds the)-.15 F .588(high threshold load a)117
+268.2 R -.15(ve)-.2 G .588(rage \(option).15 F F0(X)3.087 E F1 3.087(,v)C
+(ariable)281.846 268.2 Q F2(RefuseLA)3.087 E F1(\),)A F2(shouldqueue)3.087 E F1
+(returns)3.087 E F3(TR)3.087 E(UE)-.36 E F1(immedi-)3.087 E(ately)117 280.2 Q
+7.125(.O)-.65 G 2.125
+(therwise, it computes the function based on the message priority)152.635 280.2
+R 4.626(,t)-.65 G 2.126(he queue f)438.208 280.2 R(actor)-.1 E(\(option)117
+292.2 Q F0(q)2.5 E F1 2.5(,g)C(lobal v)163.95 292.2 Q(ariable)-.25 E F2(QueueF)
+2.5 E(actor)-.75 E F1(\), and the current and threshold load a)A -.15(ve)-.2 G
+(rages.).15 E 1.067(An implementation wishing to tak)142 308.4 R 3.567(et)-.1 G
+1.066(he actual age of the message into account can also)293.625 308.4 R 1.41
+(use the)117 320.4 R F2(ctime)3.91 E F1(parameter)3.91 E 3.91(,w)-.4 G 1.41
+(hich is the time that the message w)229.15 320.4 R 1.41
+(as \214rst submitted to)-.1 F F2(sendmail)3.91 E F1(.)A .929(Note that the)117
+332.4 R F2(pri)3.428 E F1 .928
+(parameter is already weighted by the number of times the message has been)
+3.428 F .395(tried \(although this tends to lo)117 344.4 R .395
+(wer the priority of the message with time\); the e)-.25 F .395
+(xpectation is that)-.15 F(the)117 356.4 Q F2(ctime)2.674 E F1 -.1(wo)2.674 G
+.174(uld be used as an \231escape clause\232 to ensure that messages are e).1 F
+-.15(ve)-.25 G .174(ntually processed.).15 F F0 2.5(6.3.6. Refusing)102 380.4 R
+(Incoming SMTP Connections)2.5 E F1 1.148(The function)142 396.6 R F2 -.37(re)
+3.648 G(fuseconnections).37 E F1(returns)3.648 E F3(TR)3.648 E(UE)-.36 E F1
+1.148(if incoming SMTP connections should be)3.648 F 3.564(refused. The)117
+408.6 R 1.063(current implementation is based e)3.563 F(xclusi)-.15 E -.15(ve)
+-.25 G 1.063(ly on the current load a).15 F -.15(ve)-.2 G 1.063(rage and the)
+.15 F(refuse load a)117 420.6 Q -.15(ve)-.2 G(rage option \(option).15 E F0(X)
+2.5 E F1 2.5(,g)C(lobal v)273.56 420.6 Q(ariable)-.25 E F2(RefuseLA)2.5 E F1
+(\):)A(bool)157 436.8 Q(refuseconnections\(\))157 448.8 Q({)157 460.8 Q
+(return \(CurrentLA >= RefuseLA\);)175 472.8 Q(})157 484.8 Q 2.5(Am)117 501 S
+(ore cle)134.5 501 Q -.15(ve)-.25 G 2.5(ri).15 G
+(mplementation could look at more system resources.)179.08 501 Q F0 2.5
+(6.3.7. Load)102 525 R -.6 -1(Av e)2.5 H(rage Computation)1 E F1 .243
+(The routine)142 541.2 R F2 -.1(ge)2.743 G(tla).1 E F1 .243
+(returns the current load a)2.743 F -.15(ve)-.2 G .243
+(rage \(as a rounded inte).15 F 2.743(ger\). The)-.15 F(distrib)2.744 E(ution)
+-.2 E(includes se)117 553.2 Q -.15(ve)-.25 G(ral possible implementations.).15
+E F0 2.5(6.4. Con\214guration)87 577.2 R(in sr)2.5 E(c/daemon.c)-.18 E F1 .4
+(The \214le)127 593.4 R F2(sr)2.9 E(c/daemon.c)-.37 E F1 .4
+(contains a number of routines that are dependent on the local netw)2.9 F(ork-)
+-.1 E(ing en)102 605.4 Q 2.5(vironment. The)-.4 F -.15(ve)2.5 G
+(rsion supplied is speci\214c to 4.3 BSD.).15 E 2.16(In pre)127 621.6 R 2.16
+(vious releases, we recommended that you modify the routine)-.25 F F2
+(maphostname)4.66 E F1 2.16(if you)4.66 F -.1(wa)102 633.6 S 1.919
+(nted to generalize).1 F F0($[)4.418 E F1(...)4.418 E F0($])4.418 E F1 4.418
+(lookups. W)4.418 F 4.418(en)-.8 G 2.418 -.25(ow r)293.906 633.6 T 1.918
+(ecommend that you create a ne).25 F 4.418(wk)-.25 G -.15(ey)463.632 633.6 S
+1.918(ed map).15 F(instead.)102 645.6 Q F0 2.5(7. CHANGES)72 669.6 R
+(IN VERSION 6)2.5 E F1 2.661(The follo)112 685.8 R 2.662
+(wing summarizes changes since the last commonly a)-.25 F -.25(va)-.2 G 2.662
+(ilable v).25 F 2.662(ersion of)-.15 F F0(sendmail)5.162 E F1(\(5.67\):)87
+697.8 Q EP
+%%Page: 51 48
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-51)452.9 60 Q 2.5(7.1. Connection)87 96 R(Caching)2.5 E/F1 10
+/Times-Roman@0 SF .398(Instead of closing SMTP connections immediately)127
+112.2 R 2.897(,t)-.65 G .397(hose connections are cached for possible)339.005
+112.2 R .597(future use.)102 124.2 R .597(The adv)5.597 F .597
+(ent of MX records made this ef)-.15 F(fecti)-.25 E .897 -.15(ve f)-.25 H .598
+(or mailing lists; in addition, substantial).15 F(performance impro)102 136.2 Q
+-.15(ve)-.15 G(ments can be e).15 E(xpected for queue processing.)-.15 E F0 2.5
+(7.2. MX)87 160.2 R(Piggybacking)2.5 E F1 1.258(If tw)127 176.4 R 3.757(oh)-.1
+G 1.257(osts with dif)161.075 176.4 R 1.257
+(ferent names in a single message happen to ha)-.25 F 1.557 -.15(ve t)-.2 H
+1.257(he same set of MX).15 F .94(hosts, the)102 188.4 R 3.44(yc)-.15 G .94
+(an be sent in the same transaction.)153.45 188.4 R -1.11(Ve)5.94 G .94
+(rsion 6 notices this and tries to batch the mes-)1.11 F(sages.)102 200.4 Q F0
+2.5(7.3. Eight-Bit)87 224.4 R(Clean)2.5 E F1(Pre)127 240.6 Q 1.105(vious v)-.25
+F 1.105(ersions of)-.15 F F0(sendmail)3.605 E F1 1.104
+(used the 0200 bit for quoting.)3.605 F 1.104(This v)6.104 F 1.104(ersion a)
+-.15 F -.2(vo)-.2 G 1.104(ids that use.).2 F(Ho)102 252.6 Q(we)-.25 E -.15(ve)
+-.25 G .8 -.4(r, f).15 H
+(or compatibility with RFC 822, you can set option `7' to get se).4 E -.15(ve)
+-.25 G 2.5(nb).15 G(it stripping.)418.86 252.6 Q(Indi)127 268.8 Q
+(vidual mailers can still produce se)-.25 E -.15(ve)-.25 G 2.5(nb).15 G
+(it out put using the `7' mailer \215ag.)300.77 268.8 Q F0 2.5(7.4. User)87
+292.8 R(Database)2.5 E F1 1.072(The user database is an as-yet e)127 309 R
+1.072(xperimental attempt to pro)-.15 F 1.073(vide uni\214ed lar)-.15 F 1.073
+(ge-site name sup-)-.18 F 2.5(port. W)102 321 R 2.5(ea)-.8 G
+(re installing it at Berk)145.63 321 Q(ele)-.1 E(y; future v)-.15 E
+(ersions may sho)-.15 E 2.5(ws)-.25 G(igni\214cant modi\214cations.)363.57 321
+Q F0 2.5(7.5. Impr)87 345 R -.1(ove)-.18 G 2.5(dB).1 G(IND Support)158.01 345 Q
+F1 .489(The BIND support, particularly for MX records, had a number of anno)127
+361.2 R .489(ying \231features\232 which)-.1 F(ha)102 373.2 Q 1.212 -.15(ve b)
+-.2 H .912(een remo).15 F -.15(ve)-.15 G 3.412(di).15 G 3.412(nt)187.116 373.2
+S .912(his release.)198.308 373.2 R .912(In particular)5.912 F 3.412(,t)-.4 G
+.912(hese more tightly bind \(pun intended\) the name)307.916 373.2 R(serv)102
+385.2 Q(er to sendmail, so that the name serv)-.15 E
+(er resolution rules are incorporated directly into)-.15 E F0(sendmail)2.5 E F1
+(.)A F0 2.5(7.6. K)87 409.2 R(ey)-.25 E(ed Files)-.1 E F1 .207(Generalized k)
+127 425.4 R -.15(ey)-.1 G .206(ed \214les is an idea tak).15 F .206
+(en directly from)-.1 F/F2 9/Times-Roman@0 SF(ID)2.706 E(A)-.36 E F0(sendmail)
+2.706 E F1 .206(\(albeit with a completely)2.706 F(dif)102 437.4 Q
+(ferent implementation\).)-.25 E(The)5 E 2.5(yc)-.15 G(an be useful on lar)
+239.63 437.4 Q(ge sites.)-.18 E(R6 also understands YP)127 453.6 Q(.)-1.11 E F0
+2.5(7.7. Multi-W)87 477.6 R(ord Classes)-.75 E F1(Classes can no)127 493.8 Q
+2.5(wb)-.25 G 2.5(em)200.35 493.8 S(ultiple w)215.07 493.8 Q 2.5(ords. F)-.1 F
+(or e)-.15 E(xample,)-.15 E(CShofmann.CS.Berk)142 510 Q(ele)-.1 E -.65(y.)-.15
+G(EDU).65 E(allo)102 526.2 Q 2.663
+(ws you to match the entire string \231hofmann.CS.Berk)-.25 F(ele)-.1 E -.65
+(y.)-.15 G 2.664(EDU\232 using the single construct).65 F(\231$=S\232.)102
+538.2 Q F0 2.5(7.8. Deferr)87 562.2 R(ed Macr)-.18 E 2.5(oE)-.18 G(xpansion)
+184.94 562.2 Q F1(The)127 578.4 Q F0($&)2.5 E/F3 10/Times-Italic@0 SF(x)A F1
+(construct has been adopted from)2.5 E F2(ID)2.5 E(A)-.36 E F1(.)A F0 2.5
+(7.9. IDENT)87 602.4 R(Pr)2.5 E(otocol Support)-.18 E F1
+(The IDENT protocol as de\214ned in RFC 1413 is supported.)127 618.6 Q F0 2.5
+(7.10. P)87 642.6 R(arsing Bug Fixes)-.1 E F1 4.03(An)127 658.8 S 1.53
+(umber of small b)143.25 658.8 R 1.53(ugs ha)-.2 F 1.53
+(ving to do with things lik)-.2 F 4.03(eb)-.1 G 1.53
+(ackslash-escaped quotes inside of)364.72 658.8 R(comments ha)102 670.8 Q .3
+-.15(ve b)-.2 H(een \214x).15 E(ed.)-.15 E F0 2.5(7.11. Separate)87 694.8 R(En)
+2.5 E -.1(ve)-.4 G(lope/Header Pr).1 E(ocessing)-.18 E F1 .854
+(Since the From: line is passed in separately from the en)127 711 R -.15(ve)-.4
+G .854(lope sender).15 F 3.354(,t)-.4 G .854(hese ha)420.978 711 R 1.154 -.15
+(ve b)-.2 H .854(oth been).15 F 1.76(made visible; the)102 723 R F0($g)4.26 E
+F1 1.76(macro is set to the en)4.26 F -.15(ve)-.4 G 1.76
+(lope sender during processing of mailer ar).15 F(gument)-.18 E EP
+%%Page: 52 49
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-52 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF -.15(ve)102 96 S
+(ctors and the header sender during processing of headers.).15 E .084
+(It is also possible to specify separate per)127 112.2 R .085(-mailer en)-.2 F
+-.15(ve)-.4 G .085(lope and header processing.).15 F(The)5.085 E F0(S)2.585 E
+F1(ender)A(-)-.2 E -.55(RW)102 124.2 S .513(Set and).55 F F0(R)3.013 E F1
+(ecipientR)A .513(Wset ar)-.55 F .512
+(guments for mailers can be speci\214ed as)-.18 F/F2 10/Times-Italic@0 SF(en)
+3.012 E(velope/header)-.4 E F1 .512(to gi)3.012 F .812 -.15(ve d)-.25 H(if-).15
+E(ferent re)102 136.2 Q(writings for en)-.25 E -.15(ve)-.4 G(lope v).15 E
+(ersus header addresses.)-.15 E F0 2.5(7.12. Owner)87 160.2 R(-List Pr)-.37 E
+(opagates to En)-.18 E -.1(ve)-.4 G(lope).1 E F1 1
+(When an alias has an associated o)127 176.4 R 1.001
+(wner\255list name, that alias is used to change the en)-.25 F -.15(ve)-.4 G
+(lope).15 E(sender address.)102 188.4 Q(This will cause do)5 E
+(wnstream errors to be returned to that o)-.25 E(wner)-.25 E(.)-.55 E F0 2.5
+(7.13. Dynamic)87 212.4 R(Header Allocation)2.5 E F1(The \214x)127 228.6 Q
+(ed size limit on header lines has been eliminated.)-.15 E F0 2.5(7.14. New)87
+252.6 R(Command Line Flag)2.5 E F1
+(The \255p \215ag has been added to pass in protocol information.)127 268.8 Q
+F0 2.5(7.15. New)87 292.8 R(and Old Con\214guration Line T)2.5 E(ypes)-.74 E F1
+(The)127 309 Q F0(T)2.767 E F1(\(T)2.767 E .267
+(rusted users\) con\214guration line has been deleted.)-.35 F .267
+(It will still be accepted b)5.267 F .266(ut will be)-.2 F(ignored.)102 321 Q
+(The)127 337.2 Q F0(K)2.5 E F1(line has been added to declare database maps.)
+2.5 E(The)127 353.4 Q F0(V)2.5 E F1
+(line has been added to declare the con\214guration v)2.5 E(ersion le)-.15 E
+-.15(ve)-.25 G(l.).15 E F0 2.5(7.16. New)87 377.4 R(Options)2.5 E F1(Se)127
+393.6 Q -.15(ve)-.25 G .9(ral ne).15 F 3.4(wo)-.25 G .9(ptions ha)184.8 393.6 R
+1.2 -.15(ve b)-.2 H .9(een added, man).15 F 3.4(yt)-.15 G 3.4(os)314.89 393.6 S
+.9(upport ne)327.18 393.6 R 3.4(wf)-.25 G .9(eatures, others to allo)379.83
+393.6 R 3.4(wt)-.25 G(uning)481.22 393.6 Q 1.187(that w)102 405.6 R 1.187
+(as pre)-.1 F 1.187(viously a)-.25 F -.25(va)-.2 G 1.187
+(ilable only by recompiling.).25 F(The)6.186 E 3.686(ya)-.15 G 1.186
+(re described in detail in Section 5.1.5.)345.514 405.6 R(Brie\215y)102 417.6 Q
+(,)-.65 E 20(bI)102 433.8 S(nsist on a minimum number of disk blocks.)130.33
+433.8 Q 18.33(CS)102 450 S(et checkpoint interv)132.56 450 Q(al.)-.25 E 18.89
+(ED)102 466.2 S(ef)134.22 466.2 Q(ault error message.)-.1 E 17.78(GE)102 482.4
+S(nable GECOS matching.)133.11 482.4 Q 20(hM)102 498.6 S(aximum hop count.)
+135.89 498.6 Q 22.22(jS)102 514.8 S(end errors in MIME-encapsulated format.)
+132.56 514.8 Q 21.11(JF)102 531 S(orw)132.41 531 Q(ard \214le path.)-.1 E 20
+(kC)102 547.2 S(onnection cache size)133.67 547.2 Q 17.78(KC)102 563.4 S
+(onnection cache lifetime.)133.67 563.4 Q 22.22(lE)102 579.6 S .123
+(nable Errors-T)133.11 579.6 R .123(o: header)-.8 F 5.123(.T)-.55 G .123
+(hese headers violate RFC 1123; this option is included to pro)241.259 579.6 R
+(vide)-.15 E(back compatibility with old v)127 591.6 Q(ersions of sendmail.)
+-.15 E 20(pP)102 607.8 S(ri)132.56 607.8 Q -.25(va)-.25 G .3 -.15(cy o).25 H
+(ptions.).15 E 17.78(UU)102 624 S(ser database spec.)134.22 624 Q 20(7D)102
+640.2 S 2.5(on)134.22 640.2 S(ot run eight bit clean.)146.72 640.2 Q F0 2.5
+(7.17. Extended)87 664.2 R(Options)2.5 E F1(The)127 680.4 Q F0(r)3.764 E F1
+1.264(\(read timeout\),)3.764 F F0(I)3.764 E F1 1.264(\(use BIND\), and)3.764 F
+F0(T)3.764 E F1 1.264(\(queue timeout\) options ha)3.764 F 1.564 -.15(ve b)-.2
+H 1.264(een e).15 F 1.264(xtended to)-.15 F(pass in more information.)102 692.4
+Q EP
+%%Page: 53 50
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-53)452.9 60 Q 2.5(7.18. New)87 96 R(Mailer Flag)2.5 E/F1 10
+/Times-Roman@0 SF(The)127 112.2 Q F0(c)3.42 E F1 .92(mailer \215ag will strip \
+all comments from addresses; this should only be used as a last)3.42 F
+(resort when dealing with crank)102 124.2 Q 2.5(ym)-.15 G(ailers.)240.99 124.2
+Q F0 2.5(7.19. New)87 148.2 R(LHS T)2.5 E(ok)-.92 E(en)-.1 E F1 -1.11(Ve)127
+164.4 S 1.376(rsion 6 allo)1.11 F(ws)-.25 E F0($@)3.876 E F1 1.376
+(on the Left Hand Side of an \231R\232 line to match zero tok)3.876 F 3.875
+(ens. This)-.1 F(is)3.875 E(intended to be used to match the null input.)102
+176.4 Q F0 2.5(7.20. Bigger)87 200.4 R(Defaults)2.5 E F1 -1.11(Ve)127 216.6 S
+1.283(rsion 6 allo)1.11 F 1.284(ws up to 100 rulesets instead of 30.)-.25 F
+1.284(It is recommended that rulesets 0\2559 be)6.284 F(reserv)102 228.6 Q
+(ed for)-.15 E/F2 10/Times-Italic@0 SF(sendmail)2.5 E F1 1.1 -.55('s d)D
+(edicated use in future releases.).55 E
+(The total number of MX records that can be used has been raised to 20.)127
+244.8 Q .335(The number of queued messages that can be handled at one time has\
+ been raised from 600 to)127 261 R(1000.)102 273 Q F0 2.5(7.21. Differ)87 297 R
+(ent Default T)-.18 E(uning P)-.92 E(arameters)-.1 E F1 -1.11(Ve)127 313.2 S .8
+(rsion 6 has changed the def)1.11 F .8
+(ault parameters for tuning queue costs to mak)-.1 F 3.3(et)-.1 G .8
+(he number of)449.08 313.2 R .712(recipients more important than the size of t\
+he message \(for small messages\).)102 325.2 R .712(This is reasonable if)5.712
+F(you are connected with reasonably f)102 337.2 Q(ast links.)-.1 E F0 2.5
+(7.22. A)87 361.2 R(uto-Quoting in Addr)-.5 E(esses)-.18 E F1(Pre)127 377.4 Q
+(viously)-.25 E 2.61(,t)-.65 G .111
+(he \231Full Name <email address>\232 syntax w)176.77 377.4 R .111
+(ould generate incorrect protocol output)-.1 F
+(if \231Full Name\232 had special characters such as dot.)102 389.4 Q(This v)5
+E(ersion puts quotes around such names.)-.15 E F0 2.5(7.23. Symbolic)87 413.4 R
+(Names On Err)2.5 E(or Mailer)-.18 E F1(Se)127 429.6 Q -.15(ve)-.25 G
+(ral names ha).15 E .3 -.15(ve b)-.2 H(een b).15 E
+(uilt in to the $@ portion of the $#error mailer)-.2 E(.)-.55 E F0 2.5
+(7.24. SMTP)87 453.6 R(VRFY Doesn't Expand)2.5 E F1(Pre)127 469.8 Q 1.438
+(vious v)-.25 F 1.438(ersions of)-.15 F F2(sendmail)3.938 E F1 1.438
+(treated VRFY and EXPN the same.)3.938 F 1.437(In this v)6.437 F 1.437
+(ersion, VRFY)-.15 F(doesn')102 481.8 Q 2.5(te)-.18 G(xpand aliases or follo)
+138.05 481.8 Q 2.5(w.)-.25 G(forw)235.84 481.8 Q(ard \214les.)-.1 E .663
+(As an optimization, if you run with your def)127 498 R .664(ault deli)-.1 F
+-.15(ve)-.25 G .664(ry mode being queue-only).15 F 3.164(,t)-.65 G .664
+(he RCPT)466.386 498 R 1.09(command will also not chase aliases and .forw)102
+510 R 1.09(ard \214les.)-.1 F 1.09(It will chase them when it processes the)
+6.09 F(queue.)102 522 Q F0 2.5(7.25. [IPC])87 546 R(Mailers Allo)2.5 E 2.5(wM)
+-.1 G(ultiple Hosts)210.49 546 Q F1 .447(When an address resolv)127 562.2 R
+.448(es to a mailer that has \231[IPC]\232 as its \231P)-.15 F .448
+(ath\232, the $@ part \(host name\))-.15 F .138
+(can be a colon-separated list of hosts instead of a single hostname.)102 574.2
+R .137(This asks sendmail to search the)5.137 F .16
+(list for the \214rst entry that is a)102 586.2 R -.25(va)-.2 G .16(ilable e)
+.25 F .161(xactly as though it were an MX record.)-.15 F .161
+(The intent is to route)5.161 F .738(internal traf)102 598.2 R .738
+(\214c through internal netw)-.25 F .738
+(orks without publishing an MX record to the net.)-.1 F .737(MX e)5.737 F
+(xpan-)-.15 E(sion is still done on the indi)102 610.2 Q(vidual items.)-.25 E
+F0 2.5(7.26. Aliases)87 634.2 R(Extended)2.5 E F1 1.456
+(The implementation has been mer)127 650.4 R 1.457(ged with maps.)-.18 F 1.457
+(Among other things, this supports NIS-)6.457 F(based aliases.)102 662.4 Q F0
+2.5(7.27. P)87 686.4 R(ortability and Security Enhancements)-.2 E F1 2.5(An)127
+702.6 S(umber of internal changes ha)141.72 702.6 Q .3 -.15(ve b)-.2 H
+(een made to enhance portability).15 E(.)-.65 E EP
+%%Page: 54 51
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-54 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(Se)127 96 Q -.15
+(ve)-.25 G(ral \214x).15 E(es ha)-.15 E .3 -.15(ve b)-.2 H
+(een made to increase the paranoia f).15 E(actor)-.1 E(.)-.55 E F0 2.5(8. A)72
+120 R(CKNO)-.55 E(WLEDGEMENTS)-.5 E F1(I')112 136.2 Q 2.037 -.15(ve w)-.5 H
+(ork).05 E 1.737(ed on)-.1 F/F2 10/Times-Italic@0 SF(sendmail)4.237 E F1 1.737
+(for man)4.237 F 4.237(yy)-.15 G 1.737(ears, and man)267.502 136.2 R 4.237(ye)
+-.15 G(mplo)339.763 136.2 Q 1.737(yers ha)-.1 F 2.037 -.15(ve b)-.2 H 1.737
+(een remarkably patient).15 F .403(about letting me w)87 148.2 R .403
+(ork on a lar)-.1 F .403(ge project that w)-.18 F .404(as not part of my of)-.1
+F .404(\214cial job)-.25 F 5.404(.T)-.4 G .404(his includes time on the)407.384
+148.2 R(INGRES Project at Berk)87 160.2 Q(ele)-.1 E 1.3 -.65(y, a)-.15 H 2.5
+(tB).65 G(ritton Lee, and ag)222.75 160.2 Q(ain on the Mammoth Project at Berk)
+-.05 E(ele)-.1 E -.65(y.)-.15 G .454(Much of the second w)112 176.4 R -2.25 -.2
+(av e)-.1 H .453(of impro)3.153 F -.15(ve)-.15 G .453
+(ments should be credited to Bryan Costales of ICSI.).15 F .453(As he)5.453 F
+.781(passed me drafts of his book on)87 188.4 R F2(sendmail)3.281 E F1 3.281
+(Iw)3.281 G .781(as inspired to start w)274.739 188.4 R .781
+(orking on things ag)-.1 F 3.282(ain. Bryan)-.05 F -.1(wa)3.282 G(s).1 E
+(also a)87 200.4 Q -.25(va)-.2 G(ilable to bounce ideas of).25 E 2.5(fo)-.25 G
+(f.)227.38 200.4 Q(Man)112 216.6 Q 2.857 -.65(y, m)-.15 H(an).65 E 4.057(yp)
+-.15 G 1.557(eople contrib)172.214 216.6 R 1.556
+(uted chunks of code and ideas to)-.2 F F2(sendmail)4.056 E F1 6.556(.I)C 4.056
+(th)418.48 216.6 S 1.556(as pro)430.316 216.6 R -.15(ve)-.15 G 4.056(nt).15 G
+4.056(ob)477.008 216.6 S 4.056(ea)491.064 216.6 S .463(group netw)87 228.6 R
+.463(ork ef)-.1 F 2.963(fort. V)-.25 F .463(ersion 6 in particular w)-1.11 F
+.463(as a group project.)-.1 F .464(The follo)5.464 F .464
+(wing people made notable)-.25 F(contrib)87 240.6 Q(utions:)-.2 E -.25(Ke)127
+256.8 S(ith Bostic, CSRG, Uni).25 E -.15(ve)-.25 G(rsity of California, Berk)
+.15 E(ele)-.1 E(y)-.15 E(Michael J. Corrig)127 268.8 Q(an, Uni)-.05 E -.15(ve)
+-.25 G(rsity of California, San Die).15 E(go)-.15 E
+(Bryan Costales, International Computer Science Institute)127 280.8 Q
+(P{r \(Pell\) Emanuelsson)127 292.8 Q(Craig Ev)127 304.8 Q(erhart, T)-.15 E
+(ransarc Corporation)-.35 E -.8(To)127 316.8 S 2.5(mI).8 G -.25(va)150.92 316.8
+S 2.5(rH).25 G(elbekkmo, Norwe)173.16 316.8 Q(gian School of Economics)-.15 E
+(Allan E. Johannesen, WPI)127 328.8 Q -.8(Ta)127 340.8 S
+(kahiro Kanbe, FujiXerox).8 E(Brian Kantor)127 352.8 Q 2.5(,U)-.4 G(ni)191.31
+352.8 Q -.15(ve)-.25 G(rsity of California, San Die).15 E(go)-.15 E
+(Bruce Lilly)127 364.8 Q 2.5(,S)-.65 G(on)182.74 364.8 Q 2.5(yU)-.15 G(.S.)
+207.31 364.8 Q(Nakamura Motonori, K)127 376.8 Q(yoto Uni)-.25 E -.15(ve)-.25 G
+(rsity).15 E(John Gardiner Myers, Carne)127 388.8 Q(gie Mellon Uni)-.15 E -.15
+(ve)-.25 G(rsity).15 E(Neil Rick)127 400.8 Q(ert, Northern Illinois Uni)-.1 E
+-.15(ve)-.25 G(rsity).15 E(Eric W)127 412.8 Q(assenaar)-.8 E 2.5(,N)-.4 G
+(ational Institute for Nuclear and High Ener)200.49 412.8 Q(gy Ph)-.18 E
+(ysics, Amsterdam)-.05 E(Christophe W)127 424.8 Q(olfhugel, Herv)-.8 E 2.5(eS)
+-.15 G(chauer Consultants \(P)252.7 424.8 Q(aris\))-.15 E 2.688(Ia)87 441 S
+.188(pologize for an)97.458 441 R .188(yone I ha)-.15 F .488 -.15(ve o)-.2 H
+.188(mitted, misspelled, misattrib).15 F .188(uted, or otherwise missed.)-.2 F
+(Man)5.188 E 2.687(yo)-.15 G .187(ther peo-)467.993 441 R(ple ha)87 453 Q .3
+-.15(ve c)-.2 H(ontrib).15 E(uted ideas, comments, and encouragement.)-.2 E 2.5
+(Ia)5 G(ppreciate their contrib)338.06 453 Q(ution as well.)-.2 E EP
+%%Page: 55 52
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 12/Times-Bold@0 SF 3(APPENDIX A)257.172 98.4 R(COMMAND LINE FLA)224.832
+141.6 Q(GS)-.66 E/F1 10/Times-Roman@0 SF(Ar)97 201 Q
+(guments must be presented with \215ags before addresses.)-.18 E
+(The \215ags are:)5 E<ad62>72 217.2 Q/F2 10/Times-Italic@0 SF(x)A F1
+(Set operation mode to)144 217.2 Q F2(x)2.5 E F1 5(.O)C(peration modes are:)
+253.71 217.2 Q 12.22(mD)184 233.4 S(eli)211.22 233.4 Q -.15(ve)-.25 G 2.5(rm)
+.15 G(ail \(def)243.87 233.4 Q(ault\))-.1 E 16.11(sS)184 245.4 S
+(peak SMTP on input side)209.56 245.4 Q 15(dR)184 257.4 S(un as a daemon)210.67
+257.4 Q 17.22(tR)184 269.4 S(un in test mode)210.67 269.4 Q 15(vJ)184 281.4 S
+(ust v)207.89 281.4 Q(erify addresses, don')-.15 E 2.5(tc)-.18 G
+(ollect or deli)319.48 281.4 Q -.15(ve)-.25 G(r).15 E 17.22(iI)184 293.4 S
+(nitialize the alias database)207.33 293.4 Q 15(pP)184 305.4 S
+(rint the mail queue)209.56 305.4 Q 15.56(zF)184 317.4 S
+(reeze the con\214guration \214le)209.56 317.4 Q<ad43>72 337.8 Q F2(\214le)A F1
+.946(Use a dif)144 337.8 R .946(ferent con\214guration \214le.)-.25 F F2
+(Sendmail)5.946 E F1 .946(runs as the in)3.446 F -.2(vo)-.4 G .946
+(king user \(rather than root\)).2 F(when this \215ag is speci\214ed.)144 349.8
+Q<ad64>72 366 Q F2(le)A(vel)-.15 E F1(Set deb)144 366 Q(ugging le)-.2 E -.15
+(ve)-.25 G(l.).15 E<ad66>72 382.2 Q F2(addr)2.5 E F1(The sender')144 382.2 Q
+2.5(sm)-.55 G(achine address is)205.1 382.2 Q F2(addr)2.5 E F1(.)A<ad46>72
+398.4 Q F2(name)A F1(Sets the full name of this user to)144 398.4 Q F2(name)2.5
+E F1(.)A<ad68>72 414.6 Q F2(cnt)2.5 E F1 .726(Sets the \231hop count\232 to)144
+414.6 R F2(cnt)3.226 E F1 5.725(.T)C .725
+(his represents the number of times this message has been)269.455 414.6 R .02
+(processed by)144 426.6 R F2(sendmail)2.52 E F1 .02(\(to the e)2.52 F .02
+(xtent that it is supported by the underlying netw)-.15 F(orks\).)-.1 E F2(Cnt)
+5.02 E F1 1.521
+(is incremented during processing, and if it reaches MAXHOP \(currently 30\))
+144 438.6 R F2(sendmail)4.02 E F1(thro)144 450.6 Q(ws a)-.25 E -.1(wa)-.15 G
+2.5(yt).1 G(he message with an error)199.6 450.6 Q(.)-.55 E 58.86(\255n Don')72
+466.8 R 2.5(td)-.18 G 2.5(oa)174.65 466.8 S(liasing or forw)186.59 466.8 Q
+(arding.)-.1 E<ad72>72 483 Q F2(addr)2.5 E F1(An obsolete form of)144 483 Q/F3
+10/Times-Bold@0 SF<ad66>2.5 E F1(.)A<ad6f>72 499.2 Q F2 1.666(xv)C(alue)-1.666
+E F1(Set option)144 499.2 Q F2(x)2.5 E F1(to the speci\214ed)2.5 E F2(value)2.5
+E F1 5(.T)C(hese options are described in Appendix B.)292.6 499.2 Q<ad70>72
+515.4 Q F2(pr)A(otocol)-.45 E F1 .4(Set the sending protocol.)144 515.4 R .401
+(Programs are encouraged to set this.)5.4 F .401(The protocol \214eld can be)
+5.401 F .115(in the form)144 527.4 R F2(pr)2.615 E(otocol)-.45 E F3(:)A F2
+(host)A F1 .114(to set both the sending protocol and sending host.)2.615 F -.15
+(Fo)5.114 G 2.614(re).15 G(xample,)472.06 527.4 Q 2.147(\231\255pUUCP:uunet\
+\232 sets the sending protocol to UUCP and the sending host to uunet.)144 539.4
+R .974(\(Some e)144 551.4 R .974
+(xisting programs use \255oM to set the r and s macros; this is equi)-.15 F
+-.25(va)-.25 G .973(lent to using).25 F(\255p.\))144 563.4 Q<ad71>72 579.6 Q F2
+(time)A F1 -.35(Tr)144 579.6 S 3.167(yt).35 G 3.167(op)164.037 579.6 S .667
+(rocess the queued up mail.)177.204 579.6 R .667(If the time is gi)5.667 F -.15
+(ve)-.25 G .667(n, a sendmail will run through the).15 F
+(queue at the speci\214ed interv)144 591.6 Q(al to deli)-.25 E -.15(ve)-.25 G
+2.5(rq).15 G(ueued mail; otherwise, it only runs once.)310.82 591.6 Q<ad71>72
+607.8 Q F2(Xstring)A F1 .313
+(Run the queue once, limiting the jobs to those matching)144 607.8 R F2
+(Xstring)2.812 E F1 5.312(.T)C .312(he k)416.33 607.8 R .612 -.15(ey l)-.1 H
+(etter).15 E F2(X)2.812 E F1 .312(can be)2.812 F F3(I)144 619.8 Q F1 .67
+(to limit based on queue identi\214er)3.17 F(,)-.4 E F3(R)3.17 E F1 .671
+(to limit based on recipient, or)3.17 F F3(S)3.171 E F1 .671(to limit based on)
+3.171 F(sender)144 631.8 Q 6.054(.A)-.55 G 1.054
+(particular queued job is accepted if one of the corresponding addresses con-)
+188.878 631.8 R(tains the indicated)144 643.8 Q F2(string)2.5 E F1(.)A 61.08
+(\255t Read)72 660 R .752(the header for \231T)3.252 F .752
+(o:\232, \231Cc:\232, and \231Bcc:\232 lines, and send to e)-.8 F -.15(ve)-.25
+G .752(ryone listed in those).15 F 2.54(lists. The)144 672 R .039
+(\231Bcc:\232 line will be deleted before sending.)2.54 F(An)5.039 E 2.539(ya)
+-.15 G .039(ddresses in the ar)385.314 672 R .039(gument v)-.18 F(ec-)-.15 E
+(tor will be deleted from the send list.)144 684 Q 1.118
+(There are a number of options that may be speci\214ed as primiti)97 700.2 R
+1.418 -.15(ve \215)-.25 H 1.118(ags \(pro).15 F 1.118(vided for compatibility)
+-.15 F(with)72 712.2 Q F2(delivermail)2.5 E F1 2.5(\). These)B
+(are the e, i, m, and v options.)2.5 E
+(Also, the f option may be speci\214ed as the)5 E F3<ad73>2.5 E F1(\215ag.)2.5
+E F3(Sendmail Installation and Operation Guide)72 756 Q(SMM:08-55)452.9 756 Q
+EP
+%%Page: 56 53
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 12/Times-Bold@0 SF 3(APPENDIX B)250.002 98.4 R -.12(QU)220.29 141.6 S
+(EUE FILE FORMA).12 E(TS)-1.14 E/F1 10/Times-Roman@0 SF .292
+(This appendix describes the format of the queue \214les.)97 201 R .292
+(These \214les li)5.292 F .592 -.15(ve i)-.25 H 2.792(nt).15 G .291
+(he directory de\214ned by the)395.636 201 R/F2 10/Times-Bold@0 SF(Q)72 213 Q
+F1(option in the)2.5 E/F3 10/Times-Italic@0 SF(sendmail.cf)2.5 E F1
+(\214le, usually)2.5 E F3(/var/spool/mqueue)2.5 E F1(or)2.5 E F3
+(/usr/spool/mqueue)2.5 E F1(.)A .229(All queue \214les ha)97 229.2 R .529 -.15
+(ve t)-.2 H .229(he name).15 F F3(x)2.729 E F2(f)1.666 E F3(AAA99999)A F1
+(where)2.73 E F3(AAA99999)2.73 E F1 .23(is the)2.73 F F3(id)2.73 E F1 .23
+(for this message and the)2.73 F F3(x)2.73 E F1 .23(is a)2.73 F 3.601
+(type. The)72 241.2 R 1.101
+(\214rst letter of the id encodes the hour of the day that the message w)3.601
+F 1.101(as recei)-.1 F -.15(ve)-.25 G 3.601(db).15 G 3.601(yt)451.798 241.2 S
+1.101(he system)463.179 241.2 R .551
+(\(with A being the hour between midnight and 1:00AM\).)72 253.2 R .552
+(All \214les with the same id collecti)5.552 F -.15(ve)-.25 G .552
+(ly de\214ne one).15 F(message.)72 265.2 Q(The types are:)97 281.4 Q 31(dT)72
+297.6 S(he data \214le.)114.11 297.6 Q(The message body \(e)5 E
+(xcluding the header\) is k)-.15 E(ept in this \214le.)-.1 E 33.22(lT)72 313.8
+S .312(he lock \214le.)114.11 313.8 R .312(If this \214le e)5.312 F .311
+(xists, the job is currently being processed, and a queue run will not pro-)
+-.15 F .523(cess the \214le.)108 325.8 R -.15(Fo)5.524 G 3.024(rt).15 G .524
+(hat reason, an e)183.274 325.8 R(xtraneous)-.15 E F2(lf)3.024 E F1 .524
+(\214le can cause a job to apparently disappear \(it will)3.024 F .285(not e)
+108 337.8 R -.15(ve)-.25 G 2.785(nt).15 G .284(ime out!\).)147.61 337.8 R
+([Actually)5.284 E 2.784(,t)-.65 G .284
+(his \214le is obsolete on most systems that support the)237.802 337.8 R F2
+(\215ock)2.784 E F1(or)2.784 E F2(lockf)2.784 E F1(system calls.])108 349.8 Q
+31(nT)72 366 S .348(his \214le is created when an id is being created.)114.11
+366 R .348(It is a separate \214le to insure that no mail can e)5.348 F -.15
+(ve)-.25 G(r).15 E .805(be destro)108 378 R .805(yed due to a race condition.)
+-.1 F .805(It should e)5.805 F .805(xist for no more than a fe)-.15 F 3.305(wm)
+-.25 G .805(illiseconds at an)433.1 378 R(y)-.15 E(gi)108 390 Q -.15(ve)-.25 G
+2.5(nt).15 G 2.5(ime. [This)135.1 390 R(is only used on old v)2.5 E
+(ersions of sendmail; it is not used on ne)-.15 E(wer v)-.25 E(ersions.])-.15 E
+31(qT)72 406.2 S(he queue control \214le.)114.11 406.2 Q
+(This \214le contains the information necessary to process the job)5 E(.)-.4 E
+33.22(tA)72 422.4 S .344(temporary \214le.)118.064 422.4 R .344
+(These are an image of the)5.344 F F2(qf)2.844 E F1 .344
+(\214le when it is being reb)2.844 F 2.845(uilt. It)-.2 F .345
+(should be renamed)2.845 F(to a)108 434.4 Q F2(qf)2.5 E F1(\214le v)2.5 E
+(ery quickly)-.15 E(.)-.65 E 31(xA)72 450.6 S .567(transcript \214le, e)118.287
+450.6 R .567(xisting during the life of a session sho)-.15 F .566(wing e)-.25 F
+-.15(ve)-.25 G .566(rything that happens during that).15 F(session.)108 462.6 Q
+(The)97 478.8 Q F2(qf)3.333 E F1 .833
+(\214le is structured as a series of lines each be)3.333 F .834
+(ginning with a code letter)-.15 F 5.834(.T)-.55 G .834(he lines are as fol-)
+427.354 478.8 R(lo)72 490.8 Q(ws:)-.25 E 28.78(DT)72 507 S
+(he name of the data \214le.)114.11 507 Q
+(There may only be one of these lines.)5 E 28.78(HA)72 523.2 S .33
+(header de\214nition.)118.05 523.2 R .33(There may be an)5.33 F 2.829(yn)-.15 G
+.329(umber of these lines.)274.289 523.2 R .329(The order is important: the)
+5.329 F 2.829(yr)-.15 G(epre-)483.46 523.2 Q .046
+(sent the order in the \214nal message.)108 535.2 R .046
+(These use the same syntax as header de\214nitions in the con\214gu-)5.046 F
+(ration \214le.)108 547.2 Q 29.33(CT)72 563.4 S .575(he controlling address.)
+114.11 563.4 R .575(The syntax is \231localuser:aliasname\232.)5.575 F .575
+(Recipient addresses follo)5.575 F .575(wing this)-.25 F 2.814
+(line will be \215agged so that deli)108 575.4 R -.15(ve)-.25 G 2.814
+(ries will be run as the).15 F F3(localuser)5.314 E F1 2.814
+(\(a user name from the)5.314 F .562(/etc/passwd \214le\);)108 587.4 R F3
+(aliasname)3.062 E F1 .561(is the name of the alias that e)3.062 F .561
+(xpanded to this address \(used for print-)-.15 F(ing messages\).)108 599.4 Q
+29.33(RA)72 615.6 S .705(recipient address.)118.425 615.6 R .705
+(This will normally be completely aliased, b)5.705 F .705
+(ut is actually realiased when the)-.2 F(job is processed.)108 627.6 Q
+(There will be one line for each recipient.)5 E 30.44(ST)72 643.8 S
+(he sender address.)114.11 643.8 Q(There may only be one of these lines.)5 E
+29.89(EA)72 660 S 3.742(ne)115.22 660 S 1.242(rror address.)128.402 660 R 1.242
+(If an)6.242 F 3.742(ys)-.15 G 1.241(uch lines e)218.19 660 R 1.241(xist, the)
+-.15 F 3.741(yr)-.15 G 1.241(epresent the addresses that should recei)308.124
+660 R 1.541 -.15(ve e)-.25 H(rror).15 E(messages.)108 672 Q 29.89(TT)72 688.2 S
+(he job creation time.)114.11 688.2 Q
+(This is used to compute when to time out the job)5 E(.)-.4 E 30.44(PT)72 704.4
+S .113(he current message priority)114.11 704.4 R 5.113(.T)-.65 G .113
+(his is used to order the queue.)236.662 704.4 R .114(Higher numbers mean lo)
+5.114 F .114(wer priori-)-.25 F 3.677(ties. The)108 716.4 R 1.176
+(priority changes as the message sits in the queue.)3.677 F 1.176
+(The initial priority depends on the)6.176 F F2 193.36(SMM:08-56 Sendmail)72
+756 R(Installation and Operation Guide)2.5 E EP
+%%Page: 57 54
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-57)452.9 60 Q/F1 10/Times-Roman@0 SF
+(message class and the size of the message.)108 96 Q 27.11(MA)72 112.2 S 2.703
+(message. This)117.923 112.2 R .203(line is printed by the)2.703 F/F2 10
+/Times-Italic@0 SF(mailq)2.703 E F1 .204
+(command, and is generally used to store status infor)2.704 F(-)-.2 E 2.5
+(mation. It)108 124.2 R(can contain an)2.5 E 2.5(yt)-.15 G -.15(ex)219.78 124.2
+S(t.).15 E 30.44(FF)72 140.4 S .044
+(lag bits, represented as one letter per \215ag.)113.56 140.4 R .043
+(De\214ned \215ag bits are)5.043 F F0(r)2.543 E F1 .043
+(indicating that this is a response)2.543 F .142(message and)108 152.4 R F0(w)
+2.642 E F1 .142(indicating that a w)2.642 F .143
+(arning message has been sent announcing that the mail has been)-.1 F(delayed.)
+108 164.4 Q 31($A)72 180.6 S .83(macro de\214nition.)118.55 180.6 R .83(The v)
+5.83 F .829(alues of certain macros \(as of this writing, only)-.25 F F0($r)
+3.329 E F1(and)3.329 E F0($s)3.329 E F1 3.329(\)a)C .829(re passed)466.241
+180.6 R(through to the queue run phase.)108 192.6 Q 29.33(BT)72 208.8 S .924
+(he body type.)114.11 208.8 R .925(The remainder of the line is a te)5.924 F
+.925(xt string de\214ning the body type.)-.15 F .925(If this \214eld is)5.925 F
+.009(missing, the body type is assumed to be \231unde\214ned\232 and no specia\
+l processing is attempted.)108 220.8 R(Le)5.008 E -.05(ga)-.15 G(l).05 E -.25
+(va)108 232.8 S(lues are \2317BIT\232 and \2318BITMIME\232.).25 E 4.072
+(As an e)97 249 R 4.072(xample, the follo)-.15 F 4.073
+(wing is a queue \214le sent to \231eric@mammoth.Berk)-.25 F(ele)-.1 E -.65(y.)
+-.15 G 4.073(EDU\232 and).65 F(\231bostic@ok)72 263 Q(eef)-.1 E(fe.CS.Berk)-.25
+E(ele)-.1 E -.65(y.)-.15 G(EDU\232).65 E/F3 7/Times-Roman@0 SF(1)219.09 259 Q
+F1(:)222.59 263 Q(P835771)112 279.2 Q(T404261372)112 291.2 Q(DdfAAA13557)112
+303.2 Q(Seric)112 315.2 Q(Eo)112 327.2 Q(wner)-.25 E(-sendmail@v)-.2 E
+(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU).65 E(Ceric:sendmail@v)112
+339.2 Q(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU).65 E
+(Reric@mammoth.Berk)112 351.2 Q(ele)-.1 E -.65(y.)-.15 G(EDU).65 E(Rbostic@ok)
+112 363.2 Q(eef)-.1 E(fe.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU).65 E
+(H?P?return-path: <o)112 375.2 Q(wner)-.25 E(-sendmail@v)-.2 E(angogh.CS.Berk)
+-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU>).65 E(Hrecei)112 387.2 Q -.15(ve)-.25 G
+(d: by v).15 E(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G
+(EDU \(5.108/2.7\) id AAA06703;).65 E(Fri, 17 Jul 92 00:28:55 -0700)132 399.2 Q
+(Hrecei)112 411.2 Q -.15(ve)-.25 G(d: from mail.CS.Berk).15 E(ele)-.1 E -.65
+(y.)-.15 G(EDU by v).65 E(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G
+(EDU \(5.108/2.7\)).65 E(id AAA06698; Fri, 17 Jul 92 00:28:54 -0700)132 423.2 Q
+(Hrecei)112 435.2 Q -.15(ve)-.25 G(d: from [128.32.31.21] by mail.CS.Berk).15 E
+(ele)-.1 E -.65(y.)-.15 G(EDU \(5.96/2.5\)).65 E
+(id AA22777; Fri, 17 Jul 92 03:29:14 -0400)132 447.2 Q(Hrecei)112 459.2 Q -.15
+(ve)-.25 G(d: by foo.bar).15 E(.baz.de \(5.57/Ultrix3.0-C\))-.55 E
+(id AA22757; Fri, 17 Jul 92 09:31:25 GMT)132 471.2 Q(H?F?from: eric@foo.bar)112
+483.2 Q(.baz.de \(Eric Allman\))-.55 E(H?x?full-name: Eric Allman)112 495.2 Q
+(Hmessage-id: <9207170931.AA22757@foo.bar)112 507.2 Q(.baz.de>)-.55 E(HT)112
+519.2 Q(o: sendmail@v)-.8 E(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU)
+.65 E(Hsubject: this is an e)112 531.2 Q(xample message)-.15 E 1.083(This sho)
+72 547.4 R 1.084(ws the name of the data \214le, the person who sent the messa\
+ge, the submission time \(in seconds)-.25 F .26
+(since January 1, 1970\), the message priority)72 559.4 R 2.76(,t)-.65 G .259
+(he message class, the recipients, and the headers for the mes-)257.03 559.4 R
+(sage.)72 571.4 Q .32 LW 76 669.2 72 669.2 DL 80 669.2 76 669.2 DL 84 669.2 80
+669.2 DL 88 669.2 84 669.2 DL 92 669.2 88 669.2 DL 96 669.2 92 669.2 DL 100
+669.2 96 669.2 DL 104 669.2 100 669.2 DL 108 669.2 104 669.2 DL 112 669.2 108
+669.2 DL 116 669.2 112 669.2 DL 120 669.2 116 669.2 DL 124 669.2 120 669.2 DL
+128 669.2 124 669.2 DL 132 669.2 128 669.2 DL 136 669.2 132 669.2 DL 140 669.2
+136 669.2 DL 144 669.2 140 669.2 DL 148 669.2 144 669.2 DL 152 669.2 148 669.2
+DL 156 669.2 152 669.2 DL 160 669.2 156 669.2 DL 164 669.2 160 669.2 DL 168
+669.2 164 669.2 DL 172 669.2 168 669.2 DL 176 669.2 172 669.2 DL 180 669.2 176
+669.2 DL 184 669.2 180 669.2 DL 188 669.2 184 669.2 DL 192 669.2 188 669.2 DL
+196 669.2 192 669.2 DL 200 669.2 196 669.2 DL 204 669.2 200 669.2 DL 208 669.2
+204 669.2 DL 212 669.2 208 669.2 DL 216 669.2 212 669.2 DL/F4 5/Times-Roman@0
+SF(1)93.6 679.6 Q/F5 8/Times-Roman@0 SF .719(This e)3.2 J .719
+(xample is contri)-.12 F -.12(ve)-.2 G 2.719(da).12 G .719
+(nd probably inaccurate for your en)186.968 682.8 R 2.719(vironment. Glance)
+-.32 F -.12(ove)2.718 G 2.718(ri).12 G 2.718(tt)384.998 682.8 S 2.718(og)
+392.164 682.8 S .718(et an idea; nothing can replace)402.882 682.8 R
+(looking at what your o)72 692.4 Q(wn system generates.)-.2 E EP
+%%Page: 58 55
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 12/Times-Bold@0 SF 3(APPENDIX C)249.672 98.4 R(SUMMAR)198.282 141.6 Q 3(YO)
+-.42 G 3(FS)274.182 141.6 S(UPPOR)291.186 141.6 Q 3(TF)-.48 G(ILES)350.37 141.6
+Q/F1 10/Times-Roman@0 SF 1.519(This is a summary of the support \214les that)97
+201 R/F2 10/Times-Italic@0 SF(sendmail)4.019 E F1 1.52(creates or generates.)
+4.019 F(Man)6.52 E 4.02(yo)-.15 G 4.02(ft)444.74 201 S 1.52(hese can be)454.87
+201 R(changed by editing the sendmail.cf \214le; check there to \214nd the act\
+ual pathnames.)72 213 Q(/usr/sbin/sendmail)72 229.2 Q(The binary of)144 241.2 Q
+F2(sendmail)2.5 E F1(.)A(/usr/bin/ne)72 257.4 Q -.1(wa)-.25 G(liases).1 E 3.735
+(Al)144 269.4 S 1.235
+(ink to /usr/sbin/sendmail; causes the alias database to be reb)157.735 269.4 R
+3.734(uilt. Running)-.2 F 1.234(this pro-)3.734 F(gram is completely equi)144
+281.4 Q -.25(va)-.25 G(lent to gi).25 E(ving)-.25 E F2(sendmail)2.5 E F1(the)
+2.5 E/F3 10/Times-Bold@0 SF(\255bi)2.5 E F1(\215ag.)2.5 E 13.38
+(/usr/bin/mailq Prints)72 297.6 R 3.702(al)3.702 G 1.202
+(isting of the mail queue.)181.964 297.6 R 1.203(This program is equi)6.202 F
+-.25(va)-.25 G 1.203(lent to using the).25 F F3(\255bp)3.703 E F1 1.203
+(\215ag to)3.703 F F2(sendmail)144 309.6 Q F1(.)A 5.9(/etc/sendmail.cf The)72
+325.8 R(con\214guration \214le, in te)2.5 E(xtual form.)-.15 E 5.9
+(/etc/sendmail.fc The)72 342 R
+(con\214guration \214le represented as a memory image.)2.5 E
+(/usr/lib/sendmail.hf)72 358.2 Q(The SMTP help \214le.)144 370.2 Q 7
+(/etc/sendmail.st A)72 386.4 R(statistics \214le; need not be present.)2.5 E
+.89(/etc/sendmail.pid Created)72 402.6 R .318
+(in daemon mode; it contains the process id of the current SMTP daemon.)2.818 F
+.318(If you)5.318 F .337(use this in scripts; use `)144 414.6 R .337
+(`head \2551')-.74 F 2.838('t)-.74 G 2.838(og)285.78 414.6 S .338
+(et just the \214rst line; later v)298.618 414.6 R .338(ersions of)-.15 F F2
+(sendmail)2.838 E F1(may)2.838 E(add information to subsequent lines.)144 426.6
+Q 25.62(/etc/aliases The)72 442.8 R(te)2.5 E(xtual v)-.15 E
+(ersion of the alias \214le.)-.15 E(/etc/aliases.{pag,dir})72 459 Q
+(The alias \214le in)144 471 Q F2(dbm)2.5 E F1(\(3\) format.)1.666 E(/v)72
+487.2 Q(ar/spool/mqueue)-.25 E
+(The directory in which the mail queue and temporary \214les reside.)144 499.2
+Q(/v)72 515.4 Q(ar/spool/mqueue/qf*)-.25 E
+(Control \(queue\) \214les for messages.)144 527.4 Q(/v)72 543.6 Q
+(ar/spool/mqueue/df*)-.25 E(Data \214les.)144 555.6 Q(/v)72 571.8 Q
+(ar/spool/mqueue/tf*)-.25 E -.7(Te)144 583.8 S(mporary v).7 E
+(ersions of the qf \214les, used during queue \214le reb)-.15 E(uild.)-.2 E(/v)
+72 600 Q(ar/spool/mqueue/xf*)-.25 E 2.5(At)144 612 S
+(ranscript of the current session.)156.5 612 Q F3 193.36(SMM:08-58 Sendmail)72
+756 R(Installation and Operation Guide)2.5 E EP
+%%Page: 2 56
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 198.36(SMM:08-2 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 12/Times-Roman@0 SF -1.116(TA)
+263.226 98.4 S(BLE OF CONTENTS)1.116 E/F2 10/Times-Roman@0 SF 2.5(1. B)72 124.8
+R(ASIC INST)-.35 E(ALLA)-.93 E 1.18(TION .....................................\
+..........................................................................)
+-1.11 F(5)499 124.8 Q 2.5(1.1. Compiling)87 139.2 R .43(Sendmail .............\
+..............................................................................\
+...................)2.5 F(5)499 139.2 Q 2.5(1.1.1. Old)102 153.6 R -.15(ve)2.5
+G(rsions of mak).15 E 2.93(e.)-.1 G 28.5(.....................................\
+.............................................................. 5)220.5 153.6 R
+2.5(1.1.2. Compilation)102 168 R 2.1(\215ags .................................\
+........................................................................)2.5 F
+(5)499 168 Q 2.5(1.1.3. Compilation)102 182.4 R(and installation)2.5 E 28.5(..\
+..............................................................................\
+........ 6)4.6 F 2.5(1.2. Con\214guration)87 196.8 R .99(Files ...............\
+..............................................................................\
+...................)2.5 F(6)499 196.8 Q 2.5(1.3. Details)87 211.2 R
+(of Installation Files)2.5 E 28.5(............................................\
+....................................................... 7)4.89 F 2.5
+(1.3.1. /usr/sbin/sendmail)102 225.6 R 28.5(..................................\
+....................................................................... 7)2.66
+F 2.5(1.3.2. /etc/sendmail.cf)102 240 R 28.5(.................................\
+........................................................................... 8)
+4.9 F 2.5(1.3.3. /usr/ucb/ne)102 254.4 R -.1(wa)-.25 G .53(liases ............\
+..............................................................................\
+.............).1 F(8)499 254.4 Q 2.5(1.3.4. /v)102 268.8 R 1.81(ar/spool/mqueu\
+e ............................................................................\
+............................)-.25 F(8)499 268.8 Q 2.5(1.3.5. /etc/aliases*)102
+283.2 R 28.5(.................................................................\
+................................................. 8)4.62 F 2.5
+(1.3.6. /etc/sendmail.fc)102 297.6 R 28.5(....................................\
+........................................................................ 9)4.9
+F 2.5(1.3.7. /etc/rc)102 312 R 28.5(..........................................\
+..............................................................................\
+.... 9)3.51 F 2.5(1.3.8. /usr/lib/sendmail.hf)102 326.4 R 23.5(...............\
+..............................................................................\
+.......... 10)2.94 F 2.5(1.3.9. /etc/sendmail.st)102 340.8 R 23.5(............\
+..............................................................................\
+................... 10)3.5 F 2.5(1.3.10. /usr/ucb/ne)102 355.2 R -.1(wa)-.25 G
+.53(liases ...................................................................\
+..................................).1 F(11)494 355.2 Q 2.5
+(1.3.11. /usr/ucb/mailq)102 369.6 R 23.5(.....................................\
+........................................................................ 11)
+3.22 F 2.5(2. NORMAL)72 384 R(OPERA)2.5 E 1.56(TIONS .........................\
+..............................................................................\
+......)-1.11 F(11)494 384 Q 2.5(2.1. `)87 398.4 R(`Quick')-.74 E 2.5('C)-.74 G
+(on\214guration Startup)152.45 398.4 Q 23.5(..................................\
+........................................................... 11)2.77 F 2.5
+(2.2. The)87 412.8 R(System Log)2.5 E 23.5(...................................\
+..............................................................................\
+... 11)4.89 F 2.5(2.2.1. F)102 427.2 R 2.26(ormat ............................\
+..............................................................................\
+................)-.15 F(11)494 427.2 Q 2.5(2.2.2. Le)102 441.6 R -.15(ve)-.25 G
+2.24(ls ......................................................................\
+.....................................................).15 F(11)494 441.6 Q 2.5
+(2.3. The)87 456 R(Mail Queue)2.5 E 23.5(.....................................\
+..............................................................................\
+.. 11)2.96 F 2.5(2.3.1. Printing)102 470.4 R(the queue)2.5 E 23.5(............\
+..............................................................................\
+............... 12)2.67 F 2.5(2.3.2. F)102 484.8 R(orcing the queue)-.15 E 23.5
+(.............................................................................\
+............................ 12)3.94 F 2.5(2.4. The)87 499.2 R(Alias Database)
+2.5 E 23.5(...................................................................\
+............................................. 12)2.69 F 2.5(2.4.1. Reb)102
+513.6 R(uilding the alias database)-.2 E 23.5(................................\
+....................................................... 13)4.27 F 2.5
+(2.4.2. Potential)102 528 R .72(problems .....................................\
+...................................................................)2.5 F(13)
+494 528 Q 2.5(2.4.3. List)102 542.4 R -.25(ow)2.5 G 1.81(ners ................\
+..............................................................................\
+.....................).25 F(13)494 542.4 Q 2.5(2.5. User)87 556.8 R
+(Information Database)2.5 E 23.5(.............................................\
+....................................................... 14)2.7 F 2.5(2.6. Per)
+87 571.2 R(-User F)-.2 E(orw)-.15 E(arding \(.forw)-.1 E(ard Files\))-.1 E 23.5
+(.............................................................................\
+...... 14)4.09 F 2.5(2.7. Special)87 585.6 R(Header Lines)2.5 E 23.5(.........\
+..............................................................................\
+...................... 14)2.97 F 2.5(2.7.1. Return-Receipt-T)102 600 R .98(o: \
+..............................................................................\
+.........................)-.8 F(14)494 600 Q 2.5(2.7.2. Errors-T)102 614.4 R
+2.09(o: ......................................................................\
+...............................................)-.8 F(14)494 614.4 Q 2.5
+(2.7.3. Apparently-T)102 628.8 R 2.09(o: .....................................\
+........................................................................)-.8 F
+(14)494 628.8 Q 2.5(2.8. IDENT)87 643.2 R(Protocol Support)2.5 E 23.5(........\
+..............................................................................\
+................. 15)2.95 F 2.5(3. ARGUMENTS)72 657.6 R 23.5(.................\
+..............................................................................\
+................................ 15)3.78 F 2.5(3.1. Queue)87 672 R(Interv)2.5 E
+1.55(al ......................................................................\
+.................................................)-.25 F(15)494 672 Q 2.5
+(3.2. Daemon)87 686.4 R 1.29(Mode ............................................\
+...........................................................................)2.5
+F(15)494 686.4 Q 2.5(3.3. F)87 700.8 R(orcing the Queue)-.15 E 23.5(..........\
+..............................................................................\
+......................... 15)4.22 F 2.5(3.4. Deb)87 715.2 R 1.76(ugging ......\
+..............................................................................\
+.........................................)-.2 F(16)494 715.2 Q EP
+%%Page: 3 57
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-3)457.9 60 Q/F1 10/Times-Roman@0 SF 2.5(3.5. T)87 96 R(rying a Dif)-.35
+E(ferent Con\214guration File)-.25 E 23.5(....................................\
+............................................... 16)4.67 F 2.5(3.6. Changing)87
+110.4 R(the V)2.5 E(alues of Options)-1.11 E 23.5(............................\
+................................................................ 16)3.23 F 2.5
+(4. TUNING)72 124.8 R 23.5(...................................................\
+..............................................................................\
+........ 16)2.68 F 2.5(4.1. T)87 139.2 R 1.07(imeouts ........................\
+..............................................................................\
+..........................)-.35 F(17)494 139.2 Q 2.5(4.1.1. Queue)102 153.6 R
+(interv)2.5 E 2.1(al .........................................................\
+.....................................................)-.25 F(17)494 153.6 Q 2.5
+(4.1.2. Read)102 168 R 1(timeouts ............................................\
+...................................................................)2.5 F(17)
+494 168 Q 2.5(4.1.3. Message)102 182.4 R 1.56(timeouts .......................\
+..............................................................................\
+....)2.5 F(18)494 182.4 Q 2.5(4.2. F)87 196.8 R(orking During Queue Runs)-.15 E
+23.5(.........................................................................\
+........................ 18)4.49 F 2.5(4.3. Queue)87 211.2 R .73(Priorities ..\
+..............................................................................\
+.....................................)2.5 F(18)494 211.2 Q 2.5(4.4. Load)87
+225.6 R .44(Limiting .........................................................\
+...............................................................)2.5 F(19)494
+225.6 Q 2.5(4.5. Deli)87 240 R -.15(ve)-.25 G(ry Mode).15 E 23.5(.............\
+..............................................................................\
+............................ 19)3.08 F 2.5(4.6. Log)87 254.4 R(Le)2.5 E -.15
+(ve)-.25 G 2.52(l.).15 G 23.5(................................................\
+..............................................................................\
+ 19)153 254.4 R 2.5(4.7. File)87 268.8 R .72(Modes ...........................\
+..............................................................................\
+....................)2.5 F(20)494 268.8 Q 2.5(4.7.1. T)102 283.2 R 2.5(os)-.8 G
+(uid or not to suid?)146.2 283.2 Q 23.5(......................................\
+........................................................... 20)6.52 F 2.5
+(4.7.2. Should)102 297.6 R(my alias database be writable?)2.5 E 23.5
+(........................................................................ 20)
+5.47 F 2.5(4.8. Connection)87 312 R 1.56(Caching .............................\
+..............................................................................\
+...)2.5 F(20)494 312 Q 2.5(4.9. Name)87 326.4 R(Serv)2.5 E(er Access)-.15 E
+23.5(.........................................................................\
+..................................... 21)2.85 F 2.5(4.10. Mo)87 340.8 R
+(ving the Per)-.15 E(-User F)-.2 E(orw)-.15 E(ard Files)-.1 E 23.5(...........\
+......................................................................... 21)
+3.84 F 2.5(4.11. Free)87 355.2 R 1.85(Space ..................................\
+..............................................................................\
+...........)2.5 F(22)494 355.2 Q 2.5(4.12. Pri)87 369.6 R -.25(va)-.25 G .3
+-.15(cy F).25 H 1.93(lags ....................................................\
+...................................................................).15 F(22)
+494 369.6 Q 2.5(4.13. Send)87 384 R(to Me T)2.5 E 2.08(oo ....................\
+..............................................................................\
+.................)-.8 F(22)494 384 Q 2.5(5. THE)72 398.4 R
+(WHOLE SCOOP ON THE CONFIGURA)2.5 E(TION FILE)-1.11 E 23.5
+(........................................................ 22)4.64 F 2.5
+(5.1. Con\214guration)87 412.8 R(File Lines)2.5 E 23.5(.......................\
+..............................................................................\
+... 22)2.66 F 2.5(5.1.1. R)102 427.2 R(and S \212 re)2.5 E(writing rules)-.25 E
+23.5(.........................................................................\
+................... 22)3.48 F 2.5(5.1.1.1. The)117 441.6 R(left hand side)2.5 E
+23.5(.........................................................................\
+....................... 23)4.07 F 2.5(5.1.1.2. The)117 456 R(right hand side)
+2.5 E 23.5(...................................................................\
+........................... 23)3.51 F 2.5(5.1.1.3. Semantics)117 470.4 R(of re)
+2.5 E(writing rule sets)-.25 E 23.5
+(.......................................................................... 25)
+4.6 F 2.5(5.1.1.4. IPC)117 484.8 R 1(mailers .................................\
+.........................................................................)2.5 F
+(25)494 484.8 Q 2.5(5.1.2. D)102 499.2 R 2.5<8a64>2.5 G(e\214ne macro)156.72
+499.2 Q 23.5(.................................................................\
+....................................... 26)4.35 F 2.5(5.1.3. C)102 513.6 R
+(and F \212 de\214ne classes)2.5 E 23.5(......................................\
+....................................................... 28)4.62 F 2.5(5.1.4. M)
+102 528 R 2.5<8a64>2.5 G(e\214ne mailer)158.39 528 Q 23.5(....................\
+..............................................................................\
+..... 28)4.62 F 2.5(5.1.5. H)102 542.4 R 2.5<8a64>2.5 G(e\214ne header)156.72
+542.4 Q 23.5(.................................................................\
+....................................... 31)2.69 F 2.5(5.1.6. O)102 556.8 R 2.5
+<8a73>2.5 G(et option)155.61 556.8 Q 23.5(....................................\
+......................................................................... 31)
+4.61 F 2.5(5.1.7. P)102 571.2 R 2.5<8a70>2.5 G(recedence de\214nitions)155.06
+571.2 Q 23.5(.................................................................\
+......................... 35)3.24 F 2.5(5.1.8. V)102 585.6 R 2.5<8a63>2.5 G
+(on\214guration v)156.16 585.6 Q(ersion le)-.15 E -.15(ve)-.25 G 4.62(l.).15 G
+23.5(.........................................................................\
+........ 36)265.5 585.6 R 2.5(5.1.9. K)102 600 R 2.5<8a6b>2.5 G .3 -.15
+(ey \214)156.62 600 T(le declaration).15 E 23.5(..............................\
+................................................................ 36)4.88 F 2.5
+(5.2. Building)87 614.4 R 2.5(aC)2.5 G(on\214guration File From Scratch)158.12
+614.4 Q 23.5
+(......................................................................... 38)
+3.77 F 2.5(5.2.1. What)102 628.8 R(you are trying to do)2.5 E 23.5(...........\
+..............................................................................\
+.... 38)2.96 F 2.5(5.2.2. Philosoph)102 643.2 R 3.54(y.)-.05 G 23.5(..........\
+..............................................................................\
+........................... 38)180.5 643.2 R 2.5(5.2.2.1. Lar)117 657.6 R
+(ge site, man)-.18 E 2.5(yh)-.15 G(osts \212 minimum information)226.1 657.6 Q
+23.5(................................................ 39)2.72 F 2.5
+(5.2.2.2. Small)117 672 R(site \212 complete information)2.5 E 23.5
+(.................................................................... 39)4.89 F
+2.5(5.2.2.3. Single)117 686.4 R 1.27(host ....................................\
+.......................................................................)2.5 F
+(39)494 686.4 Q 2.5(5.2.2.4. A)117 700.8 R(completely dif)2.5 E
+(ferent philosoph)-.25 E 3.26(y.)-.05 G 23.5
+(..................................................................... 39)295.5
+700.8 R 2.5(5.2.3. Rele)102 715.2 R -.25(va)-.25 G(nt issues).25 E 23.5(......\
+..............................................................................\
+......................... 40)4.56 F EP
+%%Page: 4 58
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 198.36(SMM:08-4 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 2.5(5.2.4. Ho)
+102 96 R 2.5(wt)-.25 G 2.5(op)153.97 96 S 2.38(roceed ........................\
+..............................................................................\
+......)166.47 96 R(40)494 96 Q 2.5(5.2.5. T)102 110.4 R(esting the re)-.7 E
+(writing rules \212 the \255bt \215ag)-.25 E 23.5
+(.................................................................... 41)2.99 F
+2.5(5.2.6. Building)102 124.8 R(mailer descriptions)2.5 E 23.5(...............\
+......................................................................... 41)
+4.61 F 2.5(5.3. The)87 139.2 R(User Database)2.5 E 23.5(......................\
+..............................................................................\
+............ 43)4.92 F 2.5(5.3.1. Structure)102 153.6 R(of the user database)
+2.5 E 23.5(...................................................................\
+.................... 43)2.7 F 2.5(5.3.2. User)102 168 R(database semantics)2.5
+E 23.5(.......................................................................\
+........................ 44)3.25 F 2.5(6. O)72 182.4 R(THER CONFIGURA)-.4 E
+1.97(TION ....................................................................\
+.....................................)-1.11 F(44)494 182.4 Q 2.5(6.1. P)87
+196.8 R(arameters in src/Mak)-.15 E 1.55(e\214le .............................\
+.......................................................................)-.1 F
+(44)494 196.8 Q 2.5(6.2. P)87 211.2 R(arameters in src/conf.h)-.15 E 23.5(....\
+..............................................................................\
+...................... 45)4.23 F 2.5(6.3. Con\214guration)87 225.6 R
+(in src/conf.c)2.5 E 23.5(....................................................\
+................................................ 47)3.51 F 2.5(6.3.1. Built-in)
+102 240 R(Header Semantics)2.5 E 23.5(........................................\
+................................................... 47)4.9 F 2.5
+(6.3.2. Restricting)102 254.4 R(Use of Email)2.5 E 23.5(......................\
+........................................................................ 48)
+4.34 F 2.5(6.3.3. Load)102 268.8 R -1.17 -.74(Av e)2.5 H(rage Computation).74 E
+23.5(.........................................................................\
+................. 49)2.74 F 2.5(6.3.4. Ne)102 283.2 R 2.5(wD)-.25 G
+(atabase Map Classes)157.85 283.2 Q 23.5(.....................................\
+.................................................... 49)4.89 F 2.5
+(6.3.5. Queueing)102 297.6 R 1.56(Function ...................................\
+....................................................................)2.5 F(49)
+494 297.6 Q 2.5(6.3.6. Refusing)102 312 R(Incoming SMTP Connections)2.5 E 23.5
+(....................................................................... 50)
+2.94 F 2.5(6.3.7. Load)102 326.4 R -1.17 -.74(Av e)2.5 H(rage Computation).74 E
+23.5(.........................................................................\
+................. 50)2.74 F 2.5(6.4. Con\214guration)87 340.8 R
+(in src/daemon.c)2.5 E 23.5(..................................................\
+............................................ 50)4.62 F 2.5(7. CHANGES)72 355.2
+R(IN VERSION 6)2.5 E 23.5(....................................................\
+...................................................... 50)4.9 F 2.5
+(7.1. Connection)87 369.6 R 1.56(Caching .....................................\
+.........................................................................)2.5 F
+(51)494 369.6 Q 2.5(7.2. MX)87 384 R 2.39(Piggybacking .......................\
+..............................................................................\
+............)2.5 F(51)494 384 Q 2.5(7.3. Eight-Bit)87 398.4 R .44(Clean ......\
+..............................................................................\
+..................................)2.5 F(51)494 398.4 Q 2.5(7.4. User)87 412.8
+R .47(Database ...............................................................\
+.........................................................)2.5 F(51)494 412.8 Q
+2.5(7.5. Impro)87 427.2 R -.15(ve)-.15 G 2.5(dB).15 G(IND Support)154.75 427.2
+Q 23.5(.......................................................................\
+................................ 51)3.81 F 2.5(7.6. K)87 441.6 R -.15(ey)-.25 G
+(ed Files).15 E 23.5(.........................................................\
+................................................................... 51)3.35 F
+2.5(7.7. Multi-W)87 456 R(ord Classes)-.8 E 23.5(.............................\
+..............................................................................\
+.... 51)3.47 F 2.5(7.8. Deferred)87 470.4 R(Macro Expansion)2.5 E 23.5(.......\
+..............................................................................\
+.............. 51)4.65 F 2.5(7.9. IDENT)87 484.8 R(Protocol Support)2.5 E 23.5
+(.............................................................................\
+.......................... 51)2.95 F 2.5(7.10. P)87 499.2 R(arsing Bug Fix)-.15
+E .46(es .....................................................................\
+...........................................)-.15 F(51)494 499.2 Q 2.5
+(7.11. Separate)87 513.6 R(En)2.5 E -.15(ve)-.4 G(lope/Header Processing).15 E
+23.5(.........................................................................\
+....... 51)4.37 F 2.5(7.12. Owner)87 528 R(-List Propag)-.2 E(ates to En)-.05 E
+-.15(ve)-.4 G 1.27(lope ......................................................\
+..............................).15 F(52)494 528 Q 2.5(7.13. Dynamic)87 542.4 R
+(Header Allocation)2.5 E 23.5(................................................\
+................................................ 52)3.25 F 2.5(7.14. Ne)87
+556.8 R 2.5(wC)-.25 G(ommand Line Flag)139.8 556.8 Q 23.5(....................\
+..............................................................................\
+. 52)4.59 F 2.5(7.15. Ne)87 571.2 R 2.5(wa)-.25 G
+(nd Old Con\214guration Line T)137.57 571.2 Q .4(ypes ........................\
+......................................................)-.8 F(52)494 571.2 Q 2.5
+(7.16. Ne)87 585.6 R 2.5(wO)-.25 G .7(ptions .................................\
+..............................................................................\
+.........)140.35 585.6 R(52)494 585.6 Q 2.5(7.17. Extended)87 600 R 1.56(Optio\
+ns ...........................................................................\
+.....................................)2.5 F(52)494 600 Q 2.5(7.18. Ne)87 614.4
+R 2.5(wM)-.25 G(ailer Flag)142.02 614.4 Q 23.5(...............................\
+..............................................................................\
+..... 53)2.93 F 2.5(7.19. Ne)87 628.8 R 2.5(wL)-.25 G(HS T)139.24 628.8 Q(ok)
+-.8 E 1.33(en ................................................................\
+..................................................)-.1 F(53)494 628.8 Q 2.5
+(7.20. Bigger)87 643.2 R(Def)2.5 E(aults .....................................\
+..............................................................................\
+.)-.1 E(53)494 643.2 Q 2.5(7.21. Dif)87 657.6 R(ferent Def)-.25 E(ault T)-.1 E
+(uning P)-.45 E 1.99(arameters ...............................................\
+...................................)-.15 F(53)494 657.6 Q 2.5
+(7.22. Auto-Quoting)87 672 R(in Addresses)2.5 E 23.5(.........................\
+........................................................................ 53)
+3.51 F 2.5(7.23. Symbolic)87 686.4 R(Names On Error Mailer)2.5 E 23.5(........\
+..............................................................................\
+ 53)4.91 F 2.5(7.24. SMTP)87 700.8 R(VRFY Doesn')2.5 E 2.5(tE)-.18 G 1.18(xpan\
+d ............................................................................\
+................)209.88 700.8 R(53)494 700.8 Q 2.5(7.25. [IPC])87 715.2 R
+(Mailers Allo)2.5 E 2.5(wM)-.25 G(ultiple Hosts)205.91 715.2 Q 23.5(..........\
+......................................................................... 53)
+3.75 F EP
+%%Page: 5 59
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-5)457.9 60 Q/F1 10/Times-Roman@0 SF 2.5(7.26. Aliases)87 96 R 1.29(Ext\
+ended ........................................................................\
+.........................................)2.5 F(53)494 96 Q 2.5
+(7.27. Portability)87 110.4 R(and Security Enhancements)2.5 E 23.5(...........\
+.................................................................... 53)2.68 F
+2.5(8. A)72 124.8 R(CKNO)-.4 E .1(WLEDGEMENTS ................................\
+............................................................................)
+-.35 F(54)494 124.8 Q(Appendix A.)72 139.2 Q(COMMAND LINE FLA)5 E 1.97(GS ....\
+..............................................................................\
+.......)-.4 F(55)494 139.2 Q(Appendix B.)72 153.6 Q -.1(QU)5 G(EUE FILE FORMA)
+.1 E 1.38(TS .................................................................\
+...........................)-1.11 F(56)494 153.6 Q(Appendix C.)72 168 Q(SUMMAR)
+5 E 2.5(YO)-.65 G 2.5(FS)188.85 168 S(UPPOR)202.47 168 Q 2.5(TF)-.6 G 1.12(ILE\
+S ............................................................................\
+..)248.27 168 R(58)494 168 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/usr.sbin/sendmail/doc/usenix/usenix.me b/usr.sbin/sendmail/doc/usenix/usenix.me
new file mode 100644 (file)
index 0000000..30da01f
--- /dev/null
@@ -0,0 +1,1076 @@
+.nr si 3n
+.he 'Mail Systems and Addressing in 4.2bsd''%'
+.fo 'Version 8.1'USENIX \- Jan 83'Last Mod 6/7/93'
+.if n .ls 2
+.+c
+.(l C
+.sz 14
+Mail Systems and Addressing
+in 4.2bsd
+.sz
+.sp
+Eric Allman\(dg
+.sp 0.5
+.i
+Britton-Lee, Inc.
+1919 Addison Street, Suite 105.
+Berkeley, California 94704.
+.sp 0.5
+.r
+eric@Berkeley.ARPA
+ucbvax!eric
+.)l
+.sp
+.(l F
+.ce
+ABSTRACT
+.sp \n(psu
+Routing mail through a heterogeneous internet presents many new
+problems.
+Among the worst of these is that of address mapping.
+Historically, this has been handled on an ad hoc basis.
+However,
+this approach has become unmanageable as internets grow.
+.sp \n(psu
+Sendmail acts a unified
+.q "post office"
+to which all mail can be
+submitted.
+Address interpretation is controlled by a production
+system,
+which can parse both old and new format addresses.
+The
+new format is
+.q "domain-based,"
+a flexible technique that can
+handle many common situations.
+Sendmail is not intended to perform
+user interface functions.
+.sp \n(psu
+Sendmail will replace delivermail in the Berkeley 4.2 distribution.
+Several major hosts are now or will soon be running sendmail.
+This change will affect any users that route mail through a sendmail
+gateway.
+The changes that will be user visible are emphasized.
+.)l
+.sp 2
+.(f
+\(dgA considerable part of this work
+was done while under the employ
+of the INGRES Project
+at the University of California at Berkeley.
+.)f
+.pp
+The mail system to appear in 4.2bsd
+will contain a number of changes.
+Most of these changes are based on the replacement of
+.i delivermail
+with a new module called
+.i sendmail.
+.i Sendmail
+implements a general internetwork mail routing facility,
+featuring aliasing and forwarding,
+automatic routing to network gateways,
+and flexible configuration.
+Of key interest to the mail system user
+will be the changes in the network addressing structure.
+.pp
+In a simple network,
+each node has an address,
+and resources can be identified
+with a host-resource pair;
+in particular,
+the mail system can refer to users
+using a host-username pair.
+Host names and numbers have to be administered by a central authority,
+but usernames can be assigned locally to each host.
+.pp
+In an internet,
+multiple networks with different characteristics
+and managements
+must communicate.
+In particular,
+the syntax and semantics of resource identification change.
+Certain special cases can be handled trivially
+by
+.i "ad hoc"
+techniques,
+such as
+providing network names that appear local to hosts
+on other networks,
+as with the Ethernet at Xerox PARC.
+However, the general case is extremely complex.
+For example,
+some networks require that the route the message takes
+be explicitly specified by the sender,
+simplifying the database update problem
+since only adjacent hosts must be entered
+into the system tables,
+while others use logical addressing,
+where the sender specifies the location of the recipient
+but not how to get there.
+Some networks use a left-associative syntax
+and others use a right-associative syntax,
+causing ambiguity in mixed addresses.
+.pp
+Internet standards seek to eliminate these problems.
+Initially, these proposed expanding the address pairs
+to address triples,
+consisting of
+{network, host, username}
+triples.
+Network numbers must be universally agreed upon,
+and hosts can be assigned locally
+on each network.
+The user-level presentation was changed
+to address domains,
+comprised of a local resource identification
+and a hierarchical domain specification
+with a common static root.
+The domain technique
+separates the issue of physical versus logical addressing.
+For example,
+an address of the form
+.q "eric@a.cc.berkeley.arpa"
+describes the logical
+organization of the address space
+(user
+.q eric
+on host
+.q a
+in the Computer Center
+at Berkeley)
+but not the physical networks used
+(for example, this could go over different networks
+depending on whether
+.q a
+were on an ethernet
+or a store-and-forward network).
+.pp
+.i Sendmail
+is intended to help bridge the gap
+between the totally
+.i "ad hoc"
+world
+of networks that know nothing of each other
+and the clean, tightly-coupled world
+of unique network numbers.
+It can accept old arbitrary address syntaxes,
+resolving ambiguities using heuristics
+specified by the system administrator,
+as well as domain-based addressing.
+It helps guide the conversion of message formats
+between disparate networks.
+In short,
+.i sendmail
+is designed to assist a graceful transition
+to consistent internetwork addressing schemes.
+.sp
+.pp
+Section 1 defines some of the terms
+frequently left fuzzy
+when working in mail systems.
+Section 2 discusses the design goals for
+.i sendmail .
+In section 3,
+the new address formats
+and basic features of
+.i sendmail
+are described.
+Section 4 discusses some of the special problems
+of the UUCP network.
+The differences between
+.i sendmail
+and
+.i delivermail
+are presented in section 5.
+.sp
+.(l F
+.b DISCLAIMER:
+A number of examples
+in this paper
+use names of actual people
+and organizations.
+This is not intended
+to imply a commitment
+or even an intellectual agreement
+on the part of these people or organizations.
+In particular,
+Bell Telephone Laboratories (BTL),
+Digital Equipment Corporation (DEC),
+Lawrence Berkeley Laboratories (LBL),
+Britton-Lee Incorporated (BLI),
+and the University of California at Berkeley
+are not committed to any of these proposals at this time.
+Much of this paper
+represents no more than
+the personal opinions of the author.
+.)l
+.sh 1 "DEFINITIONS"
+.pp
+There are four basic concepts
+that must be clearly distinguished
+when dealing with mail systems:
+the user (or the user's agent),
+the user's identification,
+the user's address,
+and the route.
+These are distinguished primarily by their position independence.
+.sh 2 "User and Identification"
+.pp
+The user is the being
+(a person or program)
+that is creating or receiving a message.
+An
+.i agent
+is an entity operating on behalf of the user \*-
+such as a secretary who handles my mail.
+or a program that automatically returns a
+message such as
+.q "I am at the UNICOM conference."
+.pp
+The identification is the tag
+that goes along with the particular user.
+This tag is completely independent of location.
+For example,
+my identification is the string
+.q "Eric Allman,"
+and this identification does not change
+whether I am located at U.C. Berkeley,
+at Britton-Lee,
+or at a scientific institute in Austria.
+.pp
+Since the identification is frequently ambiguous
+(e.g., there are two
+.q "Robert Henry" s
+at Berkeley)
+it is common to add other disambiguating information
+that is not strictly part of the identification
+(e.g.,
+Robert
+.q "Code Generator"
+Henry
+versus
+Robert
+.q "System Administrator"
+Henry).
+.sh 2 "Address"
+.pp
+The address specifies a location.
+As I move around,
+my address changes.
+For example,
+my address might change from
+.q eric@Berkeley.ARPA
+to
+.q eric@bli.UUCP
+or
+.q allman@IIASA.Austria
+depending on my current affiliation.
+.pp
+However,
+an address is independent of the location of anyone else.
+That is,
+my address remains the same to everyone who might be sending me mail.
+For example,
+a person at MIT and a person at USC
+could both send to
+.q eric@Berkeley.ARPA
+and have it arrive to the same mailbox.
+.pp
+Ideally a
+.q "white pages"
+service would be provided to map user identifications
+into addresses
+(for example, see
+[Solomon81]).
+Currently this is handled by passing around
+scraps of paper
+or by calling people on the telephone
+to find out their address.
+.sh 2 "Route"
+.pp
+While an address specifies
+.i where
+to find a mailbox,
+a route specifies
+.i how
+to find the mailbox.
+Specifically,
+it specifies a path
+from sender to receiver.
+As such, the route is potentially different
+for every pair of people in the electronic universe.
+.pp
+Normally the route is hidden from the user
+by the software.
+However,
+some networks put the burden of determining the route
+onto the sender.
+Although this simplifies the software,
+it also greatly impairs the usability
+for most users.
+The UUCP network is an example of such a network.
+.sh 1 "DESIGN GOALS"
+.pp
+Design goals for
+.i sendmail \**
+.(f
+\**This section makes no distinction between
+.i delivermail
+and
+.i sendmail.
+.)f
+include:
+.np
+Compatibility with the existing mail programs,
+including Bell version 6 mail,
+Bell version 7 mail,
+Berkeley
+.i Mail
+[Shoens79],
+BerkNet mail
+[Schmidt79],
+and hopefully UUCP mail
+[Nowitz78].
+ARPANET mail
+[Crocker82]
+was also required.
+.np
+Reliability, in the sense of guaranteeing
+that every message is correctly delivered
+or at least brought to the attention of a human
+for correct disposal;
+no message should ever be completely lost.
+This goal was considered essential
+because of the emphasis on mail in our environment.
+It has turned out to be one of the hardest goals to satisfy,
+especially in the face of the many anomalous message formats
+produced by various ARPANET sites.
+For example,
+certain sites generate improperly formated addresses,
+occasionally
+causing error-message loops.
+Some hosts use blanks in names,
+causing problems with
+mail programs that assume that an address
+is one word.
+The semantics of some fields
+are interpreted slightly differently
+by different sites.
+In summary,
+the obscure features of the ARPANET mail protocol
+really
+.i are
+used and
+are difficult to support,
+but must be supported.
+.np
+Existing software to do actual delivery
+should be used whenever possible.
+This goal derives as much from political and practical considerations
+as technical.
+.np
+Easy expansion to
+fairly complex environments,
+including multiple
+connections to a single network type
+(such as with multiple UUCP or Ethernets).
+This goal requires consideration of the contents of an address
+as well as its syntax
+in order to determine which gateway to use.
+.np
+Configuration information should not be compiled into the code.
+A single compiled program should be able to run as is at any site
+(barring such basic changes as the CPU type or the operating system).
+We have found this seemingly unimportant goal
+to be critical in real life.
+Besides the simple problems that occur when any program gets recompiled
+in a different environment,
+many sites like to
+.q fiddle
+with anything that they will be recompiling anyway.
+.np
+.i Sendmail
+must be able to let various groups maintain their own mailing lists,
+and let individuals specify their own forwarding,
+without modifying the system alias file.
+.np
+Each user should be able to specify which mailer to execute
+to process mail being delivered for him.
+This feature allows users who are using specialized mailers
+that use a different format to build their environment
+without changing the system,
+and facilitates specialized functions
+(such as returning an
+.q "I am on vacation"
+message).
+.np
+Network traffic should be minimized
+by batching addresses to a single host where possible,
+without assistance from the user.
+.pp
+These goals motivated the architecture illustrated in figure 1.
+.(z
+.hl
+.ie t \
+.      sp 18
+.el \{\
+.(c
++---------+   +---------+   +---------+
+| sender1 |   | sender2 |   | sender3 |
++---------+   +---------+   +---------+
+     |            |             |
+     +----------+  +  +----------+
+               |  |  |
+               v  v  v
+            +-------------+
+            |   sendmail  |
+            +-------------+
+               |  |  |
+     +----------+  +  +----------+
+     |            |             |
+     v             v             v
++---------+   +---------+   +---------+
+| mailer1 |   | mailer2 |   | mailer3 |
++---------+   +---------+   +---------+
+.)c
+.\}
+
+.ce
+Figure 1 \*- Sendmail System Structure.
+.hl
+.)z
+The user interacts with a mail generating and sending program.
+When the mail is created,
+the generator calls
+.i sendmail ,
+which routes the message to the correct mailer(s).
+Since some of the senders may be network servers
+and some of the mailers may be network clients,
+.i sendmail
+may be used as an internet mail gateway.
+.sh 1 "USAGE"
+.sh 2 "Address Formats"
+.pp
+Arguments may be flags or addresses.
+Flags set various processing options.
+Following flag arguments,
+address arguments may be given.
+Addresses follow the syntax in RFC822
+[Crocker82]
+for ARPANET
+address formats.
+In brief, the format is:
+.np
+Anything in parentheses is thrown away
+(as a comment).
+.np
+Anything in angle brackets (\c
+.q "<\|>" )
+is preferred
+over anything else.
+This rule implements the ARPANET standard that addresses of the form
+.(b
+user name <machine-address>
+.)b
+will send to the electronic
+.q machine-address
+rather than the human
+.q "user name."
+.np
+Double quotes
+(\ "\ )
+quote phrases;
+backslashes quote characters.
+Backslashes are more powerful
+in that they will cause otherwise equivalent phrases
+to compare differently \*- for example,
+.i user
+and
+.i
+"user"
+.r
+are equivalent,
+but
+.i \euser
+is different from either of them.
+This might be used
+to avoid normal aliasing
+or duplicate suppression algorithms.
+.pp
+Parentheses, angle brackets, and double quotes
+must be properly balanced and nested.
+The rewriting rules control remaining parsing\**.
+.(f
+\**Disclaimer: Some special processing is done
+after rewriting local names; see below.
+.)f
+.pp
+Although old style addresses are still accepted
+in most cases,
+the preferred address format
+is based on ARPANET-style domain-based addresses
+[Su82a].
+These addresses are based on a hierarchical, logical decomposition
+of the address space.
+The addresses are hierarchical in a sense
+similar to the U.S. postal addresses:
+the messages may first be routed to the correct state,
+with no initial consideration of the city
+or other addressing details.
+The addresses are logical
+in that each step in the hierarchy
+corresponds to a set of
+.q "naming authorities"
+rather than a physical network.
+.pp
+For example,
+the address:
+.(l
+eric@HostA.BigSite.ARPA
+.)l
+would first look up the domain
+BigSite
+in the namespace administrated by
+ARPA.
+A query could then be sent to
+BigSite
+for interpretation of
+HostA.
+Eventually the mail would arrive at
+HostA,
+which would then do final delivery
+to user
+.q eric.
+.sh 2 "Mail to Files and Programs"
+.pp
+Files and programs are legitimate message recipients.
+Files provide archival storage of messages,
+useful for project administration and history.
+Programs are useful as recipients in a variety of situations,
+for example,
+to maintain a public repository of systems messages
+(such as the Berkeley
+.i msgs
+program).
+.pp
+Any address passing through the initial parsing algorithm
+as a local address
+(i.e, not appearing to be a valid address for another mailer)
+is scanned for two special cases.
+If prefixed by a vertical bar (\c
+.q \^|\^ )
+the rest of the address is processed as a shell command.
+If the user name begins with a slash mark (\c
+.q /\^ )
+the name is used as a file name,
+instead of a login name.
+.sh 2 "Aliasing, Forwarding, Inclusion"
+.pp
+.i Sendmail
+reroutes mail three ways.
+Aliasing applies system wide.
+Forwarding allows each user to reroute incoming mail
+destined for that account.
+Inclusion directs
+.i sendmail
+to read a file for a list of addresses,
+and is normally used
+in conjunction with aliasing.
+.sh 3 "Aliasing"
+.pp
+Aliasing maps local addresses to address lists using a system-wide file.
+This file is hashed to speed access.
+Only addresses that parse as local
+are allowed as aliases;
+this guarantees a unique key
+(since there are no nicknames for the local host).
+.sh 3 "Forwarding"
+.pp
+After aliasing,
+if an recipient address specifies a local user
+.i sendmail
+searches for a
+.q .forward
+file in the recipient's home directory.
+If it exists,
+the message is
+.i not
+sent to that user,
+but rather to the list of addresses in that file.
+Often
+this list will contain only one address,
+and the feature will be used for network mail forwarding.
+.pp
+Forwarding also permits a user to specify a private incoming mailer.
+For example,
+forwarding to:
+.(b
+"\^|\|/usr/local/newmail myname"
+.)b
+will use a different incoming mailer.
+.sh 3 "Inclusion"
+.pp
+Inclusion is specified in RFC 733 [Crocker77] syntax:
+.(b
+:Include: pathname
+.)b
+An address of this form reads the file specified by
+.i pathname
+and sends to all users listed in that file.
+.pp
+The intent is
+.i not
+to support direct use of this feature,
+but rather to use this as a subset of aliasing.
+For example,
+an alias of the form:
+.(b
+project: :include:/usr/project/userlist
+.)b
+is a method of letting a project maintain a mailing list
+without interaction with the system administration,
+even if the alias file is protected.
+.pp
+It is not necessary to rebuild the index on the alias database
+when a :include: list is changed.
+.sh 2 "Message Collection"
+.pp
+Once all recipient addresses are parsed and verified,
+the message is collected.
+The message comes in two parts:
+a message header and a message body,
+separated by a blank line.
+The body is an uninterpreted
+sequence of text lines.
+.pp
+The header is formated as a series of lines
+of the form
+.(b
+       field-name: field-value
+.)b
+Field-value can be split across lines by starting the following
+lines with a space or a tab.
+Some header fields have special internal meaning,
+and have appropriate special processing.
+Other headers are simply passed through.
+Some header fields may be added automatically,
+such as time stamps.
+.sh 1 "THE UUCP PROBLEM"
+.pp
+Of particular interest
+is the UUCP network.
+The explicit routing
+used in the UUCP environment
+causes a number of serious problems.
+First,
+giving out an address
+is impossible
+without knowing the address of your potential correspondent.
+This is typically handled
+by specifying the address
+relative to some
+.q "well-known"
+host
+(e.g.,
+ucbvax or decvax).
+Second,
+it is often difficult to compute
+the set of addresses
+to reply to
+without some knowledge
+of the topology of the network.
+Although it may be easy for a human being
+to do this
+under many circumstances,
+a program does not have equally sophisticated heuristics
+built in.
+Third,
+certain addresses will become painfully and unnecessarily long,
+as when a message is routed through many hosts in the USENET.
+And finally,
+certain
+.q "mixed domain"
+addresses
+are impossible to parse unambiguously \*-
+e.g.,
+.(l
+decvax!ucbvax!lbl-h!user@LBL-CSAM
+.)l
+might have many possible resolutions,
+depending on whether the message was first routed
+to decvax
+or to LBL-CSAM.
+.pp
+To solve this problem,
+the UUCP syntax
+would have to be changed to use addresses
+rather than routes.
+For example,
+the address
+.q decvax!ucbvax!eric
+might be expressed as
+.q eric@ucbvax.UUCP
+(with the hop through decvax implied).
+This address would itself be a domain-based address;
+for example,
+an address might be of the form:
+.(l
+mark@d.cbosg.btl.UUCP
+.)l
+Hosts outside of Bell Telephone Laboratories
+would then only need to know
+how to get to a designated BTL relay,
+and the BTL topology
+would only be maintained inside Bell.
+.pp
+There are three major problems
+associated with turning UUCP addresses
+into something reasonable:
+defining the namespace,
+creating and propagating the necessary software,
+and building and maintaining the database.
+.sh 2 "Defining the Namespace"
+.pp
+Putting all UUCP hosts into a flat namespace
+(e.g.,
+.q \&...@host.UUCP )
+is not practical for a number of reasons.
+First,
+with over 1600 sites already,
+and (with the increasing availability of inexpensive microcomputers
+and autodialers)
+several thousand more coming within a few years,
+the database update problem
+is simply intractable
+if the namespace is flat.
+Second,
+there are almost certainly name conflicts today.
+Third,
+as the number of sites grow
+the names become ever less mnemonic.
+.pp
+It seems inevitable
+that there be some sort of naming authority
+for the set of top level names
+in the UUCP domain,
+as unpleasant a possibility
+as that may seem.
+It will simply not be possible
+to have one host resolving all names.
+It may however be possible
+to handle this
+in a fashion similar to that of assigning names of newsgroups
+in USENET.
+However,
+it will be essential to encourage everyone
+to become subdomains of an existing domain
+whenever possible \*-
+even though this will certainly bruise some egos.
+For example,
+if a new host named
+.q blid
+were to be added to the UUCP network,
+it would probably actually be addressed as
+.q d.bli.UUCP
+(i.e.,
+as host
+.q d
+in the pseudo-domain
+.q bli
+rather than as host
+.q blid
+in the UUCP domain).
+.sh 2 "Creating and Propagating the Software"
+.pp
+The software required to implement a consistent namespace
+is relatively trivial.
+Two modules are needed,
+one to handle incoming mail
+and one to handle outgoing mail.
+.pp
+The incoming module
+must be prepared to handle either old or new style addresses.
+New-style addresses
+can be passed through unchanged.
+Old style addresses
+must be turned into new style addresses
+where possible.
+.pp
+The outgoing module
+is slightly trickier.
+It must do a database lookup on the recipient addresses
+(passed on the command line)
+to determine what hosts to send the message to.
+If those hosts do not accept new-style addresses,
+it must transform all addresses in the header of the message
+into old style using the database lookup.
+.pp
+Both of these modules
+are straightforward
+except for the issue of modifying the header.
+It seems prudent to choose one format
+for the message headers.
+For a number of reasons,
+Berkeley has elected to use the ARPANET protocols
+for message formats.
+However,
+this protocol is somewhat difficult to parse.
+.pp
+Propagation is somewhat more difficult.
+There are a large number of hosts
+connected to UUCP
+that will want to run completely standard systems
+(for very good reasons).
+The strategy is not to convert the entire network \*-
+only enough of it it alleviate the problem.
+.sh 2 "Building and Maintaining the Database"
+.pp
+This is by far the most difficult problem.
+A prototype for this database
+already exists,
+but it is maintained by hand
+and does not pretend to be complete.
+.pp
+This problem will be reduced considerably
+if people choose to group their hosts
+into subdomains.
+This would require a global update
+only when a new top level domain
+joined the network.
+A message to a host in a subdomain
+could simply be routed to a known domain gateway
+for further processing.
+For example,
+the address
+.q eric@a.bli.UUCP
+might be routed to the
+.q bli
+gateway
+for redistribution;
+new hosts could be added
+within BLI
+without notifying the rest of the world.
+Of course,
+other hosts
+.i could
+be notified as an efficiency measure.
+.pp
+There may be more than one domain gateway.
+A domain such as BTL,
+for instance,
+might have a dozen gateways to the outside world;
+a non-BTL site
+could choose the closest gateway.
+The only restriction
+would be that all gateways
+maintain a consistent view of the domain
+they represent.
+.sh 2 "Logical Structure"
+.pp
+Logically,
+domains are organized into a tree.
+There need not be a host actually associated
+with each level in the tree \*-
+for example,
+there will be no host associated with the name
+.q UUCP.
+Similarly,
+an organization might group names together for administrative reasons;
+for example,
+the name
+.(l
+CAD.research.BigCorp.UUCP
+.)l
+might not actually have a host representing
+.q research.
+.pp
+However,
+it may frequently be convenient to have a host
+or hosts
+that
+.q represent
+a domain.
+For example,
+if a single host exists that
+represents
+Berkeley,
+then mail from outside Berkeley
+can forward mail to that host
+for further resolution
+without knowing Berkeley's
+(rather volatile)
+topology.
+This is not unlike the operation
+of the telephone network.
+.pp
+This may also be useful
+inside certain large domains.
+For example,
+at Berkeley it may be presumed
+that most hosts know about other hosts
+inside the Berkeley domain.
+But if they process an address
+that is unknown,
+they can pass it
+.q upstairs
+for further examination.
+Thus as new hosts are added
+only one host
+(the domain master)
+.i must
+be updated immediately;
+other hosts can be updated as convenient.
+.pp
+Ideally this name resolution process
+would be performed by a name server
+(e.g., [Su82b])
+to avoid unnecessary copying
+of the message.
+However,
+in a batch network
+such as UUCP
+this could result in unnecessary delays.
+.sh 1 "COMPARISON WITH DELIVERMAIL"
+.pp
+.i Sendmail
+is an outgrowth of
+.i delivermail .
+The primary differences are:
+.np
+Configuration information is not compiled in.
+This change simplifies many of the problems
+of moving to other machines.
+It also allows easy debugging of new mailers.
+.np
+Address parsing is more flexible.
+For example,
+.i delivermail
+only supported one gateway to any network,
+whereas
+.i sendmail
+can be sensitive to host names
+and reroute to different gateways.
+.np
+Forwarding and
+:include:
+features eliminate the requirement that the system alias file
+be writable by any user
+(or that an update program be written,
+or that the system administration make all changes).
+.np
+.i Sendmail
+supports message batching across networks
+when a message is being sent to multiple recipients.
+.np
+A mail queue is provided in
+.i sendmail.
+Mail that cannot be delivered immediately
+but can potentially be delivered later
+is stored in this queue for a later retry.
+The queue also provides a buffer against system crashes;
+after the message has been collected
+it may be reliably redelivered
+even if the system crashes during the initial delivery.
+.np
+.i Sendmail
+uses the networking support provided by 4.2BSD
+to provide a direct interface networks such as the ARPANET
+and/or Ethernet
+using SMTP (the Simple Mail Transfer Protocol)
+over a TCP/IP connection.
+.+c
+.ce
+REFERENCES
+.nr ii 1.5i
+.ip [Crocker77]
+Crocker, D. H.,
+Vittal, J. J.,
+Pogran, K. T.,
+and
+Henderson, D. A. Jr.,
+.ul
+Standard for the Format of ARPA Network Text Messages.
+RFC 733,
+NIC 41952.
+In [Feinler78].
+November 1977.
+.ip [Crocker82]
+Crocker, D. H.,
+.ul
+Standard for the Format of Arpa Internet Text Messages.
+RFC 822.
+Network Information Center,
+SRI International,
+Menlo Park, California.
+August 1982.
+.ip [Feinler78]
+Feinler, E.,
+and
+Postel, J.
+(eds.),
+.ul
+ARPANET Protocol Handbook.
+NIC 7104,
+Network Information Center,
+SRI International,
+Menlo Park, California.
+1978.
+.ip [Nowitz78]
+Nowitz, D. A.,
+and
+Lesk, M. E.,
+.ul
+A Dial-Up Network of UNIX Systems.
+Bell Laboratories.
+In
+UNIX Programmer's Manual, Seventh Edition,
+Volume 2.
+August, 1978.
+.ip [Schmidt79]
+Schmidt, E.,
+.ul
+An Introduction to the Berkeley Network.
+University of California, Berkeley California.
+1979.
+.ip [Shoens79]
+Shoens, K.,
+.ul
+Mail Reference Manual.
+University of California, Berkeley.
+In UNIX Programmer's Manual,
+Seventh Edition,
+Volume 2C.
+December 1979.
+.ip [Solomon81]
+Solomon, M.,
+Landweber, L.,
+and
+Neuhengen, D.,
+.ul
+The Design of the CSNET Name Server.
+CS-DN-2.
+University of Wisconsin,
+Madison.
+October 1981.
+.ip [Su82a]
+Su, Zaw-Sing,
+and
+Postel, Jon,
+.ul
+The Domain Naming Convention for Internet User Applications.
+RFC819.
+Network Information Center,
+SRI International,
+Menlo Park, California.
+August 1982.
+.ip [Su82b]
+Su, Zaw-Sing,
+.ul
+A Distributed System for Internet Name Service.
+RFC830.
+Network Information Center,
+SRI International,
+Menlo Park, California.
+October 1982.
diff --git a/usr.sbin/sendmail/doc/usenix/usenix.ps b/usr.sbin/sendmail/doc/usenix/usenix.ps
new file mode 100644 (file)
index 0000000..10bd887
--- /dev/null
@@ -0,0 +1,1004 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Italic
+%%+ font Times-Bold
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 9
+%%PageOrder: Ascend
+%%Orientation: Portrait
+%%EndComments
+%%BeginProlog
+%%BeginResource: procset grops 1.08 0
+/setpacking where{
+pop
+currentpacking
+true setpacking
+}if
+/grops 120 dict dup begin
+/SC 32 def
+/A/show load def
+/B{0 SC 3 -1 roll widthshow}bind def
+/C{0 exch ashow}bind def
+/D{0 exch 0 SC 5 2 roll awidthshow}bind def
+/E{0 rmoveto show}bind def
+/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
+/G{0 rmoveto 0 exch ashow}bind def
+/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/I{0 exch rmoveto show}bind def
+/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
+/K{0 exch rmoveto 0 exch ashow}bind def
+/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/M{rmoveto show}bind def
+/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
+/O{rmoveto 0 exch ashow}bind def
+/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/Q{moveto show}bind def
+/R{moveto 0 SC 3 -1 roll widthshow}bind def
+/S{moveto 0 exch ashow}bind def
+/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
+/SF{
+findfont exch
+[exch dup 0 exch 0 exch neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/MF{
+findfont
+[5 2 roll
+0 3 1 roll 
+neg 0 0]makefont
+dup setfont
+[exch/setfont cvx]cvx bind def
+}bind def
+/level0 0 def
+/RES 0 def
+/PL 0 def
+/LS 0 def
+/PLG{
+gsave newpath clippath pathbbox grestore
+exch pop add exch pop
+}bind def
+/BP{
+/level0 save def
+1 setlinecap
+1 setlinejoin
+72 RES div dup scale
+LS{
+90 rotate
+}{
+0 PL translate
+}ifelse
+1 -1 scale
+}bind def
+/EP{
+level0 restore
+showpage
+}bind def
+/DA{
+newpath arcn stroke
+}bind def
+/SN{
+transform
+.25 sub exch .25 sub exch
+round .25 add exch round .25 add exch
+itransform
+}bind def
+/DL{
+SN
+moveto
+SN
+lineto stroke
+}bind def
+/DC{
+newpath 0 360 arc closepath
+}bind def
+/TM matrix def
+/DE{
+TM currentmatrix pop
+translate scale newpath 0 0 .5 0 360 arc closepath
+TM setmatrix
+}bind def
+/RC/rcurveto load def
+/RL/rlineto load def
+/ST/stroke load def
+/MT/moveto load def
+/CL/closepath load def
+/FL{
+currentgray exch setgray fill setgray
+}bind def
+/BL/fill load def
+/LW/setlinewidth load def
+/RE{
+findfont
+dup maxlength 1 index/FontName known not{1 add}if dict begin
+{
+1 index/FID ne{def}{pop pop}ifelse
+}forall
+/Encoding exch def
+dup/FontName exch def
+currentdict end definefont pop
+}bind def
+/DEFS 0 def
+/EBEGIN{
+moveto
+DEFS begin
+}bind def
+/EEND/end load def
+/CNT 0 def
+/level1 0 def
+/PBEGIN{
+/level1 save def
+translate
+div 3 1 roll div exch scale
+neg exch neg exch translate
+0 setgray
+0 setlinecap
+1 setlinewidth
+0 setlinejoin
+10 setmiterlimit
+[]0 setdash
+/setstrokeadjust where{
+pop
+false setstrokeadjust
+}if
+/setoverprint where{
+pop
+false setoverprint
+}if
+newpath
+/CNT countdictstack def
+userdict begin
+/showpage{}def
+}bind def
+/PEND{
+clear
+countdictstack CNT sub{end}repeat
+level1 restore
+}bind def
+end def
+/setpacking where{
+pop
+setpacking
+}if
+%%EndResource
+%%IncludeResource: font Times-Roman
+%%IncludeResource: font Times-Italic
+%%IncludeResource: font Times-Bold
+grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL
+792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron
+/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
+/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space
+/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft
+/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four
+/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C
+/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash
+/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q
+/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase
+/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger
+/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
+/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
+/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar
+/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus
+/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu
+/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright
+/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde
+/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute
+/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
+/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls
+/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute
+/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve
+/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex
+/udieresis/yacute/thorn/ydieresis]def/Times-Bold@0 ENC0/Times-Bold RE
+/Times-Italic@0 ENC0/Times-Italic RE/Times-Roman@0 ENC0/Times-Roman RE
+%%EndProlog
+%%Page: 1 1
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 14/Times-Roman@0 SF(Mail Systems and Addressing)204.196 141 Q(in 4.2bsd)
+262.331 157.8 Q/F1 10/Times-Roman@0 SF(Eric Allman\207)260.92 181.8 Q/F2 10
+/Times-Italic@0 SF(Britton-Lee)254.86 199.8 Q 2.5(,I)-.1 G(nc.)309.2 199.8 Q
+(1919 Addison Str)225.13 211.8 Q(eet, Suite 105.)-.37 E(Berk)232.645 223.8 Q
+(ele)-.1 E 1.1 -.55(y, C)-.3 H(alifornia 94704.).55 E F1(eric@Berk)244.175
+241.8 Q(ele)-.1 E -.65(y.)-.15 G(ARP).65 E(A)-.92 E(ucb)264.6 253.8 Q -.25(va)
+-.15 G(x!eric).25 E(ABSTRA)262.085 286.2 Q(CT)-.4 E .966
+(Routing mail through a heterogeneous internet presents man)112 302.4 R 3.466
+(yn)-.15 G 1.466 -.25(ew p)373.438 302.4 T 3.466(roblems. Among).25 F .297
+(the w)112 314.4 R .297(orst of these is that of address mapping.)-.1 F
+(Historically)5.297 E 2.797(,t)-.65 G .298(his has been handled on an)355.03
+314.4 R(ad hoc basis.)112 326.4 Q(Ho)5 E(we)-.25 E -.15(ve)-.25 G .8 -.4(r, t)
+.15 H(his approach has become unmanageable as internets gro).4 E -.65(w.)-.25 G
+.099(Sendmail acts a uni\214ed \231post of)112 342.6 R .098
+(\214ce\232 to which all mail can be submitted.)-.25 F .098(Address inter)5.098
+F(-)-.2 E .754(pretation is controlled by a production system, which can parse\
+ both old and ne)112 354.6 R 3.255(wf)-.25 G(or)452.54 354.6 Q(-)-.2 E .242
+(mat addresses.)112 366.6 R .242(The ne)5.242 F 2.742(wf)-.25 G .242
+(ormat is \231domain-based,)216.578 366.6 R 2.742<9a618d>-.7 G -.15(ex)334.326
+366.6 S .241(ible technique that can handle).15 F(man)112 378.6 Q 2.606(yc)-.15
+G .106(ommon situations.)141.116 378.6 R .106
+(Sendmail is not intended to perform user interf)5.106 F .107(ace functions.)
+-.1 F .399(Sendmail will replace deli)112 394.8 R -.15(ve)-.25 G .399
+(rmail in the Berk).15 F(ele)-.1 E 2.899(y4)-.15 G .399(.2 distrib)320.504
+394.8 R 2.899(ution. Se)-.2 F -.15(ve)-.25 G .399(ral major hosts).15 F .421
+(are no)112 406.8 R 2.921(wo)-.25 G 2.921(rw)152.022 406.8 S .421
+(ill soon be running sendmail.)165.493 406.8 R .421(This change will af)5.421 F
+.422(fect an)-.25 F 2.922(yu)-.15 G .422(sers that route)407.056 406.8 R 1.5
+(mail through a sendmail g)112 418.8 R(ate)-.05 E -.1(wa)-.25 G 5.3 -.65(y. T)
+.1 H 1.5(he changes that will be user visible are empha-).65 F(sized.)112 430.8
+Q .906(The mail system to appear in 4.2bsd will contain a number of changes.)97
+475.2 R .906(Most of these changes are)5.906 F .469
+(based on the replacement of)72 487.2 R F2(delivermail)2.969 E F1 .469
+(with a ne)2.969 F 2.969(wm)-.25 G .469(odule called)292.871 487.2 R F2 2.97
+(sendmail. Sendmail)2.97 F F1 .47(implements a gen-)2.97 F 1.834
+(eral internetw)72 499.2 R 1.834(ork mail routing f)-.1 F(acility)-.1 E 4.333
+(,f)-.65 G 1.833(eaturing aliasing and forw)239.739 499.2 R 1.833
+(arding, automatic routing to netw)-.1 F(ork)-.1 E -.05(ga)72 511.2 S(te).05 E
+-.1(wa)-.25 G .205(ys, and \215e).1 F .205(xible con\214guration.)-.15 F .205
+(Of k)5.205 F .505 -.15(ey i)-.1 H .205
+(nterest to the mail system user will be the changes in the net-).15 F -.1(wo)
+72 523.2 S(rk addressing structure.).1 E .624(In a simple netw)97 539.4 R .624
+(ork, each node has an address, and resources can be identi\214ed with a host-\
+resource)-.1 F .374(pair; in particular)72 551.4 R 2.874(,t)-.4 G .374
+(he mail system can refer to users using a host-username pair)149.932 551.4 R
+5.374(.H)-.55 G .375(ost names and numbers)409.276 551.4 R(ha)72 563.4 Q .3
+-.15(ve t)-.2 H 2.5(ob).15 G 2.5(ea)108.31 563.4 S
+(dministered by a central authority)119.69 563.4 Q 2.5(,b)-.65 G
+(ut usernames can be assigned locally to each host.)263.82 563.4 Q .397
+(In an internet, multiple netw)97 579.6 R .396(orks with dif)-.1 F .396
+(ferent characteristics and managements must communicate.)-.25 F .389
+(In particular)72 591.6 R 2.889(,t)-.4 G .389
+(he syntax and semantics of resource identi\214cation change.)129.308 591.6 R
+.39(Certain special cases can be han-)5.389 F 1.033(dled tri)72 603.6 R 1.033
+(vially by)-.25 F F2 1.033(ad hoc)3.533 F F1 1.032(techniques, such as pro)
+3.533 F 1.032(viding netw)-.15 F 1.032
+(ork names that appear local to hosts on other)-.1 F(netw)72 615.6 Q 1.621
+(orks, as with the Ethernet at Xerox P)-.1 F 4.121(ARC. Ho)-.92 F(we)-.25 E
+-.15(ve)-.25 G 2.421 -.4(r, t).15 H 1.622(he general case is e).4 F 1.622
+(xtremely comple)-.15 F 4.122(x. F)-.15 F(or)-.15 E -.15(ex)72 627.6 S .29
+(ample, some netw).15 F .29(orks require that the route the message tak)-.1 F
+.29(es be e)-.1 F .29(xplicitly speci\214ed by the sender)-.15 F 2.79(,s)-.4 G
+(im-)490.11 627.6 Q 1.618(plifying the database update problem since only adja\
+cent hosts must be entered into the system tables,)72 639.6 R .573(while other\
+s use logical addressing, where the sender speci\214es the location of the rec\
+ipient b)72 651.6 R .573(ut not ho)-.2 F 3.072(wt)-.25 G(o)499 651.6 Q 1.065
+(get there.)72 663.6 R 1.065(Some netw)6.065 F 1.066(orks use a left-associati)
+-.1 F 1.366 -.15(ve s)-.25 H 1.066(yntax and others use a right-associati).15 F
+1.366 -.15(ve s)-.25 H 1.066(yntax, causing).15 F .32 LW 76 673.2 72 673.2 DL
+80 673.2 76 673.2 DL 84 673.2 80 673.2 DL 88 673.2 84 673.2 DL 92 673.2 88
+673.2 DL 96 673.2 92 673.2 DL 100 673.2 96 673.2 DL 104 673.2 100 673.2 DL 108
+673.2 104 673.2 DL 112 673.2 108 673.2 DL 116 673.2 112 673.2 DL 120 673.2 116
+673.2 DL 124 673.2 120 673.2 DL 128 673.2 124 673.2 DL 132 673.2 128 673.2 DL
+136 673.2 132 673.2 DL 140 673.2 136 673.2 DL 144 673.2 140 673.2 DL 148 673.2
+144 673.2 DL 152 673.2 148 673.2 DL 156 673.2 152 673.2 DL 160 673.2 156 673.2
+DL 164 673.2 160 673.2 DL 168 673.2 164 673.2 DL 172 673.2 168 673.2 DL 176
+673.2 172 673.2 DL 180 673.2 176 673.2 DL 184 673.2 180 673.2 DL 188 673.2 184
+673.2 DL 192 673.2 188 673.2 DL 196 673.2 192 673.2 DL 200 673.2 196 673.2 DL
+204 673.2 200 673.2 DL 208 673.2 204 673.2 DL 212 673.2 208 673.2 DL 216 673.2
+212 673.2 DL/F3 8/Times-Roman@0 SF .556(\207A considerable part of this w)93.6
+685.2 R .556(ork w)-.08 F .556(as done while under the emplo)-.08 F 2.557(yo)
+-.08 G 2.557(ft)323.107 685.2 S .557(he INGRES Project at the Uni)330.552 685.2
+R -.12(ve)-.2 G .557(rsity of California at).12 F(Berk)72 694.8 Q(ele)-.08 E
+-.52(y.)-.12 G/F4 10/Times-Bold@0 SF(Mail Systems and Addr)72 756 Q
+(essing in 4.2bsd)-.18 E(1)499 756 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Mail Systems and Addr)72 60 Q(essing in 4.2bsd)-.18 E(2)
+499 60 Q/F1 10/Times-Roman@0 SF(ambiguity in mix)72 96 Q(ed addresses.)-.15 E
+.679(Internet standards seek to eliminate these problems.)97 112.2 R(Initially)
+5.678 E 3.178(,t)-.65 G .678(hese proposed e)353.138 112.2 R .678
+(xpanding the address)-.15 F .331
+(pairs to address triples, consisting of {netw)72 124.2 R .331
+(ork, host, username} triples.)-.1 F(Netw)5.332 E .332(ork numbers must be uni)
+-.1 F -.15(ve)-.25 G -.2(r-).15 G 1.452
+(sally agreed upon, and hosts can be assigned locally on each netw)72 136.2 R
+3.952(ork. The)-.1 F(user)3.952 E(-le)-.2 E -.15(ve)-.25 G 3.952(lp).15 G 1.452
+(resentation w)440.718 136.2 R(as)-.1 E .249(changed to address domains, compr\
+ised of a local resource identi\214cation and a hierarchical domain speci\214-)
+72 148.2 R 1.54(cation with a common static root.)72 160.2 R 1.539
+(The domain technique separates the issue of ph)6.539 F 1.539(ysical v)-.05 F
+1.539(ersus logical)-.15 F 3.001(addressing. F)72 172.2 R .501(or e)-.15 F .502
+(xample, an address of the form \231eric@a.cc.berk)-.15 F(ele)-.1 E -.65(y.)
+-.15 G .502(arpa\232 describes the logical or).65 F -.05(ga)-.18 G(niza-).05 E
+.443(tion of the address space \(user \231eric\232 on host \231a\232 in the Co\
+mputer Center at Berk)72 184.2 R(ele)-.1 E .443(y\) b)-.15 F .443
+(ut not the ph)-.2 F(ysical)-.05 E(netw)72 196.2 Q .934(orks used \(for e)-.1 F
+.934(xample, this could go o)-.15 F -.15(ve)-.15 G 3.434(rd).15 G(if)274.722
+196.2 Q .934(ferent netw)-.25 F .935
+(orks depending on whether \231a\232 were on an)-.1 F
+(ethernet or a store-and-forw)72 208.2 Q(ard netw)-.1 E(ork\).)-.1 E/F2 10
+/Times-Italic@0 SF(Sendmail)97 224.4 Q F1 .493
+(is intended to help bridge the g)2.993 F .493(ap between the totally)-.05 F F2
+.493(ad hoc)2.993 F F1 -.1(wo)2.993 G .493(rld of netw).1 F .493(orks that kno)
+-.1 F(w)-.25 E .854(nothing of each other and the clean, tightly-coupled w)72
+236.4 R .854(orld of unique netw)-.1 F .855(ork numbers.)-.1 F .855
+(It can accept old)5.855 F .633(arbitrary address syntax)72 248.4 R .632(es, r\
+esolving ambiguities using heuristics speci\214ed by the system administrator)
+-.15 F 3.132(,a)-.4 G(s)500.11 248.4 Q .347(well as domain-based addressing.)72
+260.4 R .347(It helps guide the con)5.347 F -.15(ve)-.4 G .347
+(rsion of message formats between disparate net-).15 F -.1(wo)72 272.4 S 3.395
+(rks. In).1 F(short,)3.395 E F2(sendmail)3.395 E F1 .894
+(is designed to assist a graceful transition to consistent internetw)3.395 F
+.894(ork addressing)-.1 F(schemes.)72 284.4 Q .689
+(Section 1 de\214nes some of the terms frequently left fuzzy when w)97 312.6 R
+.69(orking in mail systems.)-.1 F .69(Section 2)5.69 F .595
+(discusses the design goals for)72 324.6 R F2(sendmail)3.095 E F1 5.595(.I)C
+3.095(ns)243.33 324.6 S .595(ection 3, the ne)255.315 324.6 R 3.095(wa)-.25 G
+.594(ddress formats and basic features of)332.705 324.6 R F2(send-)3.094 E
+(mail)72 336.6 Q F1 .893(are described.)3.393 F .893
+(Section 4 discusses some of the special problems of the UUCP netw)5.893 F
+3.394(ork. The)-.1 F(dif)3.394 E(fer)-.25 E(-)-.2 E(ences between)72 348.6 Q F2
+(sendmail)2.5 E F1(and)2.5 E F2(delivermail)2.5 E F1
+(are presented in section 5.)2.5 E F0(DISCLAIMER:)112 376.8 Q F1 3.333(An)3.333
+G .833(umber of e)199.216 376.8 R .832
+(xamples in this paper use names of actual people and)-.15 F(or)112 388.8 Q
+-.05(ga)-.18 G 4.572(nizations. This).05 F 2.072
+(is not intended to imply a commitment or e)4.572 F -.15(ve)-.25 G 4.573(na).15
+G 4.573(ni)409.987 388.8 S(ntellectual)422.34 388.8 Q 1.094
+(agreement on the part of these people or or)112 400.8 R -.05(ga)-.18 G 3.594
+(nizations. In).05 F(particular)3.594 E 3.594(,B)-.4 G 1.094(ell T)408.896
+400.8 R(elephone)-.7 E .656
+(Laboratories \(BTL\), Digital Equipment Corporation \(DEC\), La)112 412.8 R
+.657(wrence Berk)-.15 F(ele)-.1 E 3.157(yL)-.15 G(abo-)446.23 412.8 Q 2.136
+(ratories \(LBL\), Britton-Lee Incorporated \(BLI\), and the Uni)112 424.8 R
+-.15(ve)-.25 G 2.136(rsity of California at).15 F(Berk)112 436.8 Q(ele)-.1 E
+3.088(ya)-.15 G .588(re not committed to an)155.378 436.8 R 3.089(yo)-.15 G
+3.089(ft)261.219 436.8 S .589(hese proposals at this time.)270.418 436.8 R .589
+(Much of this paper)5.589 F
+(represents no more than the personal opinions of the author)112 448.8 Q(.)-.55
+E F0 2.5(1. DEFINITIONS)72 477 R F1 .266(There are four basic concepts that mu\
+st be clearly distinguished when dealing with mail systems:)112 493.2 R .514
+(the user \(or the user')87 505.2 R 3.014(sa)-.55 G .515(gent\), the user')
+182.6 505.2 R 3.015(si)-.55 G .515(denti\214cation, the user')253.025 505.2 R
+3.015(sa)-.55 G .515(ddress, and the route.)354.56 505.2 R .515(These are dis-)
+5.515 F(tinguished primarily by their position independence.)87 517.2 Q F0 2.5
+(1.1. User)87 541.2 R(and Identi\214cation)2.5 E F1 .264
+(The user is the being \(a person or program\) that is creating or recei)127
+557.4 R .263(ving a message.)-.25 F(An)5.263 E F2 -.1(age)2.763 G(nt).1 E F1
+.659(is an entity operating on behalf of the user \212 such as a secretary who\
+ handles my mail.)102 569.4 R .66(or a pro-)5.66 F(gram that automatically ret\
+urns a message such as \231I am at the UNICOM conference.)102 581.4 Q<9a>-.7 E
+.931(The identi\214cation is the tag that goes along with the particular user)
+127 597.6 R 5.931(.T)-.55 G .931(his tag is completely)418.707 597.6 R .216
+(independent of location.)102 609.6 R -.15(Fo)5.216 G 2.716(re).15 G .216
+(xample, my identi\214cation is the string \231Eric Allman,)225.324 609.6 R
+2.717<9a61>-.7 G .217(nd this identi-)448.006 609.6 R 1.228
+(\214cation does not change whether I am located at U.C. Berk)102 621.6 R(ele)
+-.1 E 2.527 -.65(y, a)-.15 H 3.727(tB).65 G 1.227
+(ritton-Lee, or at a scienti\214c)390.502 621.6 R(institute in Austria.)102
+633.6 Q 2.379
+(Since the identi\214cation is frequently ambiguous \(e.g., there are tw)127
+649.8 R 4.879<6f99>-.1 G 2.38(Robert Henry\232s at)426.48 649.8 R(Berk)102
+661.8 Q(ele)-.1 E .316(y\) it is common to add other disambiguating informatio\
+n that is not strictly part of the iden-)-.15 F
+(ti\214cation \(e.g., Robert \231Code Generator\232 Henry v)102 673.8 Q
+(ersus Robert \231System Administrator\232 Henry\).)-.15 E F0 -1(Ve)72 756 S
+(rsion 8.1)1 E(USENIX \255 J)249.805 756 Q(an 83)-.15 E(Last Mod 6/7/93)434.55
+756 Q EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Mail Systems and Addr)72 60 Q(essing in 4.2bsd)-.18 E(3)
+499 60 Q 2.5(1.2. Addr)87 96 R(ess)-.18 E/F1 10/Times-Roman@0 SF .785
+(The address speci\214es a location.)127 112.2 R .786(As I mo)5.786 F 1.086
+-.15(ve a)-.15 H .786(round, my address changes.).15 F -.15(Fo)5.786 G 3.286
+(re).15 G .786(xample, my)455.994 112.2 R 9.712
+(address might change from \231eric@Berk)102 124.2 R(ele)-.1 E -.65(y.)-.15 G
+(ARP).65 E 9.711(A\232 to \231eric@bli.UUCP\232 or \231all-)-.92 F
+(man@IIASA.Austria\232 depending on my current af)102 136.2 Q(\214liation.)-.25
+E(Ho)127 152.4 Q(we)-.25 E -.15(ve)-.25 G 2.819 -.4(r, a).15 H 4.519(na).4 G
+2.019(ddress is independent of the location of an)188.018 152.4 R 2.019
+(yone else.)-.15 F 2.02(That is, my address)7.02 F .385(remains the same to e)
+102 164.4 R -.15(ve)-.25 G .385(ryone who might be sending me mail.).15 F -.15
+(Fo)5.385 G 2.885(re).15 G .385(xample, a person at MIT and a)379.22 164.4 R
+(person at USC could both send to \231eric@Berk)102 176.4 Q(ele)-.1 E -.65(y.)
+-.15 G(ARP).65 E(A\232 and ha)-.92 E .3 -.15(ve i)-.2 H 2.5(ta).15 G(rri)388.44
+176.4 Q .3 -.15(ve t)-.25 H 2.5(ot).15 G(he same mailbox.)422.48 176.4 Q .627
+(Ideally a \231white pages\232 service w)127 192.6 R .627(ould be pro)-.1 F
+.627(vided to map user identi\214cations into addresses)-.15 F .444(\(for e)102
+204.6 R .444(xample, see [Solomon81]\).)-.15 F .444
+(Currently this is handled by passing around scraps of paper or by)5.444 F
+(calling people on the telephone to \214nd out their address.)102 216.6 Q F0
+2.5(1.3. Route)87 240.6 R F1 .288(While an address speci\214es)127 256.8 R/F2
+10/Times-Italic@0 SF(wher)2.788 E(e)-.37 E F1 .289
+(to \214nd a mailbox, a route speci\214es)2.789 F F2(how)2.789 E F1 .289
+(to \214nd the mailbox.)2.789 F(Speci\214cally)102 268.8 Q 2.607(,i)-.65 G
+2.607(ts)156.457 268.8 S .106(peci\214es a path from sender to recei)165.734
+268.8 R -.15(ve)-.25 G 3.706 -.55(r. A).15 H 2.606(ss).55 G .106
+(uch, the route is potentially dif)343.364 268.8 R .106(ferent for)-.25 F -2.15
+-.25(ev e)102 280.8 T(ry pair of people in the electronic uni).25 E -.15(ve)
+-.25 G(rse.).15 E .258(Normally the route is hidden from the user by the softw)
+127 297 R 2.758(are. Ho)-.1 F(we)-.25 E -.15(ve)-.25 G 1.058 -.4(r, s).15 H
+.258(ome netw).4 F .258(orks put the)-.1 F -.2(bu)102 309 S 1.972
+(rden of determining the route onto the sender).2 F 6.971(.A)-.55 G 1.971
+(lthough this simpli\214es the softw)322.544 309 R 1.971(are, it also)-.1 F
+(greatly impairs the usability for most users.)102 321 Q(The UUCP netw)5 E
+(ork is an e)-.1 E(xample of such a netw)-.15 E(ork.)-.1 E F0 2.5(2. DESIGN)72
+345 R(GO)2.5 E(ALS)-.4 E F1(Design goals for)112 363.2 Q F2(sendmail)2.5 E/F3 7
+/Times-Roman@0 SF(1)216.71 359.2 Q F1(include:)222.71 363.2 Q 12.5
+(\(1\) Compatibility)92 379.4 R 1.363(with the e)3.863 F 1.363
+(xisting mail programs, including Bell v)-.15 F 1.363(ersion 6 mail, Bell v)
+-.15 F 1.364(ersion 7)-.15 F 3.589(mail, Berk)118.66 391.4 R(ele)-.1 E(y)-.15 E
+F2(Mail)6.089 E F1 3.589
+([Shoens79], BerkNet mail [Schmidt79], and hopefully UUCP mail)6.089 F([No)
+118.66 403.4 Q 2.5(witz78]. ARP)-.25 F(ANET mail [Crock)-.92 E(er82] w)-.1 E
+(as also required.)-.1 E 12.5(\(2\) Reliability)92 419.6 R 4.002(,i)-.65 G
+4.002(nt)169.522 419.6 S 1.502(he sense of guaranteeing that e)181.304 419.6 R
+-.15(ve)-.25 G 1.502(ry message is correctly deli).15 F -.15(ve)-.25 G 1.503
+(red or at least).15 F .368
+(brought to the attention of a human for correct disposal; no message should e)
+118.66 431.6 R -.15(ve)-.25 G 2.868(rb).15 G 2.868(ec)452.252 431.6 S
+(ompletely)464 431.6 Q 2.54(lost. This)118.66 443.6 R .04(goal w)2.54 F .041
+(as considered essential because of the emphasis on mail in our en)-.1 F 2.541
+(vironment. It)-.4 F 1.755
+(has turned out to be one of the hardest goals to satisfy)118.66 455.6 R 4.254
+(,e)-.65 G 1.754(specially in the f)363.756 455.6 R 1.754(ace of the man)-.1 F
+(y)-.15 E .977(anomalous message formats produced by v)118.66 467.6 R .977
+(arious ARP)-.25 F .977(ANET sites.)-.92 F -.15(Fo)5.977 G 3.478(re).15 G .978
+(xample, certain sites)420.114 467.6 R .069
+(generate improperly formated addresses, occasionally causing error)118.66
+479.6 R .069(-message loops.)-.2 F .068(Some hosts)5.069 F .766(use blanks in \
+names, causing problems with mail programs that assume that an address is one)
+118.66 491.6 R -.1(wo)118.66 503.6 S 3.924(rd. The).1 F 1.423
+(semantics of some \214elds are interpreted slightly dif)3.923 F 1.423
+(ferently by dif)-.25 F 1.423(ferent sites.)-.25 F(In)6.423 E(summary)118.66
+515.6 Q 3.022(,t)-.65 G .523(he obscure features of the ARP)163.532 515.6 R
+.523(ANET mail protocol really)-.92 F F2(ar)3.023 E(e)-.37 E F1 .523
+(used and are dif)3.023 F(\214cult)-.25 E(to support, b)118.66 527.6 Q
+(ut must be supported.)-.2 E 12.5(\(3\) Existing)92 543.8 R(softw)2.939 E .439
+(are to do actual deli)-.1 F -.15(ve)-.25 G .439(ry should be used whene).15 F
+-.15(ve)-.25 G 2.938(rp).15 G 2.938(ossible. This)387.658 543.8 R .438
+(goal deri)2.938 F -.15(ve)-.25 G 2.938(sa).15 G(s)500.11 543.8 Q
+(much from political and practical considerations as technical.)118.66 555.8 Q
+12.5(\(4\) Easy)92 572 R -.15(ex)2.898 G .398(pansion to f).15 F .398
+(airly comple)-.1 F 2.898(xe)-.15 G -.4(nv)261.06 572 S .399
+(ironments, including multiple connections to a single net-).4 F -.1(wo)118.66
+584 S .63(rk type \(such as with multiple UUCP or Ethernets\).).1 F .63
+(This goal requires consideration of the)5.63 F
+(contents of an address as well as its syntax in order to determine which g)
+118.66 596 Q(ate)-.05 E -.1(wa)-.25 G 2.5(yt).1 G 2.5(ou)443.48 596 S(se.)
+455.98 596 Q 12.5(\(5\) Con\214guration)92 612.2 R 1.048
+(information should not be compiled into the code.)3.548 F 3.549(As)6.049 G
+1.049(ingle compiled program)405.802 612.2 R .084
+(should be able to run as is at an)118.66 624.2 R 2.584(ys)-.15 G .083
+(ite \(barring such basic changes as the CPU type or the operat-)256.196 624.2
+R .342(ing system\).)118.66 636.2 R 1.942 -.8(We h)5.342 H -2.25 -.2(av e).8 H
+.343(found this seemingly unimportant goal to be critical in real life.)3.042 F
+(Besides)5.343 E .734(the simple problems that occur when an)118.66 648.2 R
+3.234(yp)-.15 G .734(rogram gets recompiled in a dif)295.568 648.2 R .733
+(ferent en)-.25 F(vironment,)-.4 E(man)118.66 660.2 Q 2.5(ys)-.15 G(ites lik)
+147.12 660.2 Q 2.5(et)-.1 G 2.5<6f99>183.69 660.2 S(\214ddle\232 with an)195.63
+660.2 Q(ything that the)-.15 E 2.5(yw)-.15 G(ill be recompiling an)327.27 660.2
+Q(yw)-.15 E(ay)-.1 E(.)-.65 E .32 LW 76 678.8 72 678.8 DL 80 678.8 76 678.8 DL
+84 678.8 80 678.8 DL 88 678.8 84 678.8 DL 92 678.8 88 678.8 DL 96 678.8 92
+678.8 DL 100 678.8 96 678.8 DL 104 678.8 100 678.8 DL 108 678.8 104 678.8 DL
+112 678.8 108 678.8 DL 116 678.8 112 678.8 DL 120 678.8 116 678.8 DL 124 678.8
+120 678.8 DL 128 678.8 124 678.8 DL 132 678.8 128 678.8 DL 136 678.8 132 678.8
+DL 140 678.8 136 678.8 DL 144 678.8 140 678.8 DL 148 678.8 144 678.8 DL 152
+678.8 148 678.8 DL 156 678.8 152 678.8 DL 160 678.8 156 678.8 DL 164 678.8 160
+678.8 DL 168 678.8 164 678.8 DL 172 678.8 168 678.8 DL 176 678.8 172 678.8 DL
+180 678.8 176 678.8 DL 184 678.8 180 678.8 DL 188 678.8 184 678.8 DL 192 678.8
+188 678.8 DL 196 678.8 192 678.8 DL 200 678.8 196 678.8 DL 204 678.8 200 678.8
+DL 208 678.8 204 678.8 DL 212 678.8 208 678.8 DL 216 678.8 212 678.8 DL/F4 5
+/Times-Roman@0 SF(1)93.6 689.2 Q/F5 8/Times-Roman@0 SF(This section mak)3.2 I
+(es no distinction between)-.08 E/F6 8/Times-Italic@0 SF(delivermail)2 E F5
+(and)2 E F6(sendmail.)2 E F0 -1(Ve)72 756 S(rsion 8.1)1 E(USENIX \255 J)249.805
+756 Q(an 83)-.15 E(Last Mod 6/7/93)434.55 756 Q EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Mail Systems and Addr)72 60 Q(essing in 4.2bsd)-.18 E(4)
+499 60 Q/F1 10/Times-Roman@0 SF(\(6\))92 96 Q/F2 10/Times-Italic@0 SF(Sendmail)
+118.66 96 Q F1 .184(must be able to let v)2.684 F .184
+(arious groups maintain their o)-.25 F .184(wn mailing lists, and let indi)-.25
+F(viduals)-.25 E(specify their o)118.66 108 Q(wn forw)-.25 E
+(arding, without modifying the system alias \214le.)-.1 E 12.5(\(7\) Each)92
+124.2 R .313(user should be able to specify which mailer to e)2.814 F -.15(xe)
+-.15 G .313(cute to process mail being deli).15 F -.15(ve)-.25 G .313(red for)
+.15 F 3.098(him. This)118.66 136.2 R .598(feature allo)3.098 F .598
+(ws users who are using specialized mailers that use a dif)-.25 F .598
+(ferent format to)-.25 F -.2(bu)118.66 148.2 S .25(ild their en).2 F .25
+(vironment without changing the system, and f)-.4 F .25
+(acilitates specialized functions \(such)-.1 F(as returning an \231I am on v)
+118.66 160.2 Q(acation\232 message\).)-.25 E 12.5(\(8\) Netw)92 176.4 R 1.552
+(ork traf)-.1 F 1.552(\214c should be minimized by batching addresses to a sin\
+gle host where possible,)-.25 F(without assistance from the user)118.66 188.4 Q
+(.)-.55 E .375(These goals moti)112 204.6 R -.25(va)-.25 G .375
+(ted the architecture illustrated in \214gure 1.).25 F .374
+(The user interacts with a mail gen-)5.375 F .49(erating and sending program.)
+87 216.6 R .491(When the mail is created, the generator calls)5.49 F F2
+(sendmail)2.991 E F1 2.991(,w)C .491(hich routes the)444.138 216.6 R .841
+(message to the correct mailer\(s\).)87 228.6 R .841
+(Since some of the senders may be netw)5.841 F .84(ork serv)-.1 F .84
+(ers and some of the)-.15 F(mailers may be netw)87 240.6 Q(ork clients,)-.1 E
+F2(sendmail)2.5 E F1(may be used as an internet mail g)2.5 E(ate)-.05 E -.1(wa)
+-.25 G -.65(y.).1 G F0 2.5(3. USA)72 264.6 R(GE)-.55 E 2.5(3.1. Addr)87 288.6 R
+(ess F)-.18 E(ormats)-.25 E F1(Ar)127 304.8 Q .886
+(guments may be \215ags or addresses.)-.18 F .886(Flags set v)5.886 F .886
+(arious processing options.)-.25 F -.15(Fo)5.886 G(llo).15 E .886(wing \215ag)
+-.25 F(ar)102 316.8 Q .611(guments, address ar)-.18 F .611(guments may be gi)
+-.18 F -.15(ve)-.25 G 3.111(n. Addresses).15 F(follo)3.111 E 3.111(wt)-.25 G
+.611(he syntax in RFC822 [Crock)365.558 316.8 R(er82])-.1 E(for ARP)102 328.8 Q
+(ANET address formats.)-.92 E(In brief, the format is:)5 E 12.5(\(1\) An)107
+345 R(ything in parentheses is thro)-.15 E(wn a)-.25 E -.1(wa)-.15 G 2.5(y\().1
+G(as a comment\).)299.65 345 Q 12.5(\(2\) An)107 361.2 R .051
+(ything in angle brack)-.15 F .051(ets \(\231<)-.1 F .051
+(>\232\) is preferred o)1.666 F -.15(ve)-.15 G 2.551(ra).15 G -.15(ny)348.064
+361.2 S .051(thing else.).15 F .051(This rule implements the)5.051 F(ARP)133.66
+373.2 Q(ANET standard that addresses of the form)-.92 E .4 LW 77 408 72 408 DL
+79 408 74 408 DL 84 408 79 408 DL 89 408 84 408 DL 94 408 89 408 DL 99 408 94
+408 DL 104 408 99 408 DL 109 408 104 408 DL 114 408 109 408 DL 119 408 114 408
+DL 124 408 119 408 DL 129 408 124 408 DL 134 408 129 408 DL 139 408 134 408 DL
+144 408 139 408 DL 149 408 144 408 DL 154 408 149 408 DL 159 408 154 408 DL 164
+408 159 408 DL 169 408 164 408 DL 174 408 169 408 DL 179 408 174 408 DL 184 408
+179 408 DL 189 408 184 408 DL 194 408 189 408 DL 199 408 194 408 DL 204 408 199
+408 DL 209 408 204 408 DL 214 408 209 408 DL 219 408 214 408 DL 224 408 219 408
+DL 229 408 224 408 DL 234 408 229 408 DL 239 408 234 408 DL 244 408 239 408 DL
+249 408 244 408 DL 254 408 249 408 DL 259 408 254 408 DL 264 408 259 408 DL 269
+408 264 408 DL 274 408 269 408 DL 279 408 274 408 DL 284 408 279 408 DL 289 408
+284 408 DL 294 408 289 408 DL 299 408 294 408 DL 304 408 299 408 DL 309 408 304
+408 DL 314 408 309 408 DL 319 408 314 408 DL 324 408 319 408 DL 329 408 324 408
+DL 334 408 329 408 DL 339 408 334 408 DL 344 408 339 408 DL 349 408 344 408 DL
+354 408 349 408 DL 359 408 354 408 DL 364 408 359 408 DL 369 408 364 408 DL 374
+408 369 408 DL 379 408 374 408 DL 384 408 379 408 DL 389 408 384 408 DL 394 408
+389 408 DL 399 408 394 408 DL 404 408 399 408 DL 409 408 404 408 DL 414 408 409
+408 DL 419 408 414 408 DL 424 408 419 408 DL 429 408 424 408 DL 434 408 429 408
+DL 439 408 434 408 DL 444 408 439 408 DL 449 408 444 408 DL 454 408 449 408 DL
+459 408 454 408 DL 464 408 459 408 DL 469 408 464 408 DL 474 408 469 408 DL 479
+408 474 408 DL 484 408 479 408 DL 489 408 484 408 DL 494 408 489 408 DL 499 408
+494 408 DL 504 408 499 408 DL(Figure 1 \212 Sendmail System Structure.)208 660
+Q 77 672 72 672 DL 79 672 74 672 DL 84 672 79 672 DL 89 672 84 672 DL 94 672 89
+672 DL 99 672 94 672 DL 104 672 99 672 DL 109 672 104 672 DL 114 672 109 672 DL
+119 672 114 672 DL 124 672 119 672 DL 129 672 124 672 DL 134 672 129 672 DL 139
+672 134 672 DL 144 672 139 672 DL 149 672 144 672 DL 154 672 149 672 DL 159 672
+154 672 DL 164 672 159 672 DL 169 672 164 672 DL 174 672 169 672 DL 179 672 174
+672 DL 184 672 179 672 DL 189 672 184 672 DL 194 672 189 672 DL 199 672 194 672
+DL 204 672 199 672 DL 209 672 204 672 DL 214 672 209 672 DL 219 672 214 672 DL
+224 672 219 672 DL 229 672 224 672 DL 234 672 229 672 DL 239 672 234 672 DL 244
+672 239 672 DL 249 672 244 672 DL 254 672 249 672 DL 259 672 254 672 DL 264 672
+259 672 DL 269 672 264 672 DL 274 672 269 672 DL 279 672 274 672 DL 284 672 279
+672 DL 289 672 284 672 DL 294 672 289 672 DL 299 672 294 672 DL 304 672 299 672
+DL 309 672 304 672 DL 314 672 309 672 DL 319 672 314 672 DL 324 672 319 672 DL
+329 672 324 672 DL 334 672 329 672 DL 339 672 334 672 DL 344 672 339 672 DL 349
+672 344 672 DL 354 672 349 672 DL 359 672 354 672 DL 364 672 359 672 DL 369 672
+364 672 DL 374 672 369 672 DL 379 672 374 672 DL 384 672 379 672 DL 389 672 384
+672 DL 394 672 389 672 DL 399 672 394 672 DL 404 672 399 672 DL 409 672 404 672
+DL 414 672 409 672 DL 419 672 414 672 DL 424 672 419 672 DL 429 672 424 672 DL
+434 672 429 672 DL 439 672 434 672 DL 444 672 439 672 DL 449 672 444 672 DL 454
+672 449 672 DL 459 672 454 672 DL 464 672 459 672 DL 469 672 464 672 DL 474 672
+469 672 DL 479 672 474 672 DL 484 672 479 672 DL 489 672 484 672 DL 494 672 489
+672 DL 499 672 494 672 DL 504 672 499 672 DL F0 -1(Ve)72 756 S(rsion 8.1)1 E
+(USENIX \255 J)249.805 756 Q(an 83)-.15 E(Last Mod 6/7/93)434.55 756 Q EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Mail Systems and Addr)72 60 Q(essing in 4.2bsd)-.18 E(5)
+499 60 Q/F1 10/Times-Roman@0 SF(user name <machine-address>)173.66 96 Q(will s\
+end to the electronic \231machine-address\232 rather than the human \231user n\
+ame.)133.66 112.2 Q<9a>-.7 E 12.5(\(3\) Double)107 128.4 R 2.246(quotes \()
+4.746 F -2.754 2.5("\) q)2.5 H 2.246
+(uote phrases; backslashes quote characters.)224.188 128.4 R 2.246
+(Backslashes are more)7.246 F(po)133.66 140.4 Q .654(werful in that the)-.25 F
+3.154(yw)-.15 G .655(ill cause otherwise equi)229.196 140.4 R -.25(va)-.25 G
+.655(lent phrases to compare dif).25 F .655(ferently \212 for)-.25 F -.15(ex)
+133.66 152.4 S(ample,).15 E/F2 10/Times-Italic@0 SF(user)3.873 E F1(and)3.873 E
+F2("user")3.872 E F1 1.372(are equi)3.872 F -.25(va)-.25 G 1.372(lent, b).25 F
+(ut)-.2 E F2(\\user)3.872 E F1 1.372(is dif)3.872 F 1.372
+(ferent from either of them.)-.25 F(This)6.372 E(might be used to a)133.66
+164.4 Q -.2(vo)-.2 G(id normal aliasing or duplicate suppression algorithms.).2
+E -.15(Pa)127 180.6 S 1.12(rentheses, angle brack).15 F 1.12
+(ets, and double quotes must be properly balanced and nested.)-.1 F(The)6.12 E
+(re)102 194.6 Q(writing rules control remaining parsing)-.25 E/F3 7
+/Times-Roman@0 SF(2)266.17 190.6 Q F1(.)269.67 194.6 Q .644(Although old style\
+ addresses are still accepted in most cases, the preferred address format is)
+127 210.8 R .299(based on ARP)102 222.8 R(ANET)-.92 E .299
+(-style domain-based addresses [Su82a].)-.92 F .299
+(These addresses are based on a hierar)5.299 F(-)-.2 E .13
+(chical, logical decomposition of the address space.)102 234.8 R .13
+(The addresses are hierarchical in a sense similar)5.13 F 1.133(to the U.S. po\
+stal addresses: the messages may \214rst be routed to the correct state, with \
+no initial)102 246.8 R .72
+(consideration of the city or other addressing details.)102 258.8 R .72
+(The addresses are logical in that each step in)5.72 F(the hierarch)102 270.8 Q
+2.5(yc)-.05 G
+(orresponds to a set of \231naming authorities\232 rather than a ph)161.37
+270.8 Q(ysical netw)-.05 E(ork.)-.1 E -.15(Fo)127 287 S 2.5(re).15 G
+(xample, the address:)147.53 287 Q(eric@HostA.BigSite.ARP)142 303.2 Q(A)-.92 E
+-.1(wo)102 319.4 S .851
+(uld \214rst look up the domain BigSite in the namespace administrated by ARP)
+.1 F 3.351(A. A)-.92 F .851(query could)3.351 F 1.476
+(then be sent to BigSite for interpretation of HostA.)102 331.4 R(Ev)6.475 E
+1.475(entually the mail w)-.15 F 1.475(ould arri)-.1 F 1.775 -.15(ve a)-.25 H
+3.975(tH).15 G(ostA,)482.61 331.4 Q(which w)102 343.4 Q
+(ould then do \214nal deli)-.1 E -.15(ve)-.25 G(ry to user \231eric.).15 E<9a>
+-.7 E F0 2.5(3.2. Mail)87 367.4 R(to Files and Pr)2.5 E(ograms)-.18 E F1 .609
+(Files and programs are le)127 383.6 R .609(gitimate message recipients.)-.15 F
+.609(Files pro)5.609 F .609(vide archi)-.15 F -.25(va)-.25 G 3.109(ls).25 G .61
+(torage of mes-)445.02 383.6 R .124
+(sages, useful for project administration and history)102 395.6 R 5.124(.P)-.65
+G .124(rograms are useful as recipients in a v)318.308 395.6 R .124(ariety of)
+-.25 F .69(situations, for e)102 407.6 R .691(xample, to maintain a public rep\
+ository of systems messages \(such as the Berk)-.15 F(ele)-.1 E(y)-.15 E F2
+(msgs)102 419.6 Q F1(program\).)2.5 E(An)127 435.8 Q 3.188(ya)-.15 G .688(ddre\
+ss passing through the initial parsing algorithm as a local address \(i.e, not\
+ appear)151.698 435.8 R(-)-.2 E .276(ing to be a v)102 447.8 R .276
+(alid address for another mailer\) is scanned for tw)-.25 F 2.776(os)-.1 G .277
+(pecial cases.)362.128 447.8 R .277(If pre\214x)5.277 F .277(ed by a v)-.15 F
+(erti-)-.15 E .18(cal bar \(\231)102 459.8 R .833<7c9a>.833 G 2.68(\)t)-.833 G
+.179(he rest of the address is processed as a shell command.)156.456 459.8 R
+.179(If the user name be)5.179 F .179(gins with a)-.15 F(slash mark \(\231/)102
+471.8 Q(\232\) the name is used as a \214le name, instead of a login name.).833
+E F0 2.5(3.3. Aliasing,)87 495.8 R -.25(Fo)2.5 G(rwarding, Inclusion).25 E F2
+(Sendmail)127 512 Q F1 1.074(reroutes mail three w)3.574 F 3.574(ays. Aliasing)
+-.1 F 1.075(applies system wide.)3.575 F -.15(Fo)6.075 G(rw).15 E 1.075
+(arding allo)-.1 F 1.075(ws each)-.25 F .233
+(user to reroute incoming mail destined for that account.)102 524 R .233
+(Inclusion directs)5.233 F F2(sendmail)2.733 E F1 .233(to read a \214le for)
+2.733 F 2.5(al)102 536 S
+(ist of addresses, and is normally used in conjunction with aliasing.)111.72
+536 Q F0 2.5(3.3.1. Aliasing)102 560 R F1 .065
+(Aliasing maps local addresses to address lists using a system-wide \214le.)142
+576.2 R .065(This \214le is hashed)5.065 F 1.546(to speed access.)117 588.2 R
+1.545(Only addresses that parse as local are allo)6.546 F 1.545
+(wed as aliases; this guarantees a)-.25 F(unique k)117 600.2 Q .3 -.15(ey \()
+-.1 H(since there are no nicknames for the local host\).).15 E F0 2.5(3.3.2. F)
+102 624.2 R(orwarding)-.25 E F1 .641
+(After aliasing, if an recipient address speci\214es a local user)142 640.4 R
+F2(sendmail)3.141 E F1 .641(searches for a \231.for)3.141 F(-)-.2 E -.1(wa)117
+652.4 S .413(rd\232 \214le in the recipient').1 F 2.913(sh)-.55 G .413
+(ome directory)235.335 652.4 R 5.413(.I)-.65 G 2.913(fi)302.161 652.4 S 2.913
+(te)311.184 652.4 S .413(xists, the message is)321.167 652.4 R F2(not)2.913 E
+F1 .412(sent to that user)2.913 F 2.912(,b)-.4 G(ut)496.22 652.4 Q .745
+(rather to the list of addresses in that \214le.)117 664.4 R .746
+(Often this list will contain only one address, and the)5.746 F
+(feature will be used for netw)117 676.4 Q(ork mail forw)-.1 E(arding.)-.1 E
+.32 LW 76 686 72 686 DL 80 686 76 686 DL 84 686 80 686 DL 88 686 84 686 DL 92
+686 88 686 DL 96 686 92 686 DL 100 686 96 686 DL 104 686 100 686 DL 108 686 104
+686 DL 112 686 108 686 DL 116 686 112 686 DL 120 686 116 686 DL 124 686 120 686
+DL 128 686 124 686 DL 132 686 128 686 DL 136 686 132 686 DL 140 686 136 686 DL
+144 686 140 686 DL 148 686 144 686 DL 152 686 148 686 DL 156 686 152 686 DL 160
+686 156 686 DL 164 686 160 686 DL 168 686 164 686 DL 172 686 168 686 DL 176 686
+172 686 DL 180 686 176 686 DL 184 686 180 686 DL 188 686 184 686 DL 192 686 188
+686 DL 196 686 192 686 DL 200 686 196 686 DL 204 686 200 686 DL 208 686 204 686
+DL 212 686 208 686 DL 216 686 212 686 DL/F4 5/Times-Roman@0 SF(2)93.6 696.4 Q
+/F5 8/Times-Roman@0 SF(Disclaimer: Some special processing is done after re)3.2
+I(writing local names; see belo)-.2 E -.52(w.)-.2 G F0 -1(Ve)72 756 S
+(rsion 8.1)1 E(USENIX \255 J)249.805 756 Q(an 83)-.15 E(Last Mod 6/7/93)434.55
+756 Q EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Mail Systems and Addr)72 60 Q(essing in 4.2bsd)-.18 E(6)
+499 60 Q/F1 10/Times-Roman@0 SF -.15(Fo)142 96 S(rw).15 E 1.152
+(arding also permits a user to specify a pri)-.1 F -.25(va)-.25 G 1.151
+(te incoming mailer).25 F 6.151(.F)-.55 G 1.151(or e)437.348 96 R 1.151
+(xample, for)-.15 F(-)-.2 E -.1(wa)117 108 S(rding to:).1 E -2.5 .833("| /)157
+124.2 T(usr/local/ne)-.833 E(wmail myname")-.25 E(will use a dif)117 140.4 Q
+(ferent incoming mailer)-.25 E(.)-.55 E F0 2.5(3.3.3. Inclusion)102 164.4 R F1
+(Inclusion is speci\214ed in RFC 733 [Crock)142 180.6 Q(er77] syntax:)-.1 E
+(:Include: pathname)157 196.8 Q .391
+(An address of this form reads the \214le speci\214ed by)117 213 R/F2 10
+/Times-Italic@0 SF(pathname)2.891 E F1 .391
+(and sends to all users listed in that)2.891 F(\214le.)117 225 Q .645
+(The intent is)142 241.2 R F2(not)3.145 E F1 .644
+(to support direct use of this feature, b)3.145 F .644
+(ut rather to use this as a subset of)-.2 F 2.5(aliasing. F)117 253.2 R(or e)
+-.15 E(xample, an alias of the form:)-.15 E
+(project: :include:/usr/project/userlist)157 269.4 Q 1.93(is a method of letti\
+ng a project maintain a mailing list without interaction with the system)117
+285.6 R(administration, e)117 297.6 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(ft)203.54
+297.6 S(he alias \214le is protected.)212.15 297.6 Q 2.025
+(It is not necessary to reb)142 313.8 R 2.025(uild the inde)-.2 F 4.524(xo)-.15
+G 4.524(nt)317.828 313.8 S 2.024(he alias database when a :include: list is)
+330.132 313.8 R(changed.)117 325.8 Q F0 2.5(3.4. Message)87 349.8 R(Collection)
+2.5 E F1 .857(Once all recipient addresses are parsed and v)127 366 R .857
+(eri\214ed, the message is collected.)-.15 F .857(The message)5.857 F .574
+(comes in tw)102 378 R 3.074(op)-.1 G .574
+(arts: a message header and a message body)164.452 378 R 3.074(,s)-.65 G .574
+(eparated by a blank line.)349.734 378 R .573(The body is)5.574 F
+(an uninterpreted sequence of te)102 390 Q(xt lines.)-.15 E
+(The header is formated as a series of lines of the form)127 406.2 Q
+(\214eld-name: \214eld-v)178 422.4 Q(alue)-.25 E(Field-v)102 438.6 Q 1.366
+(alue can be split across lines by starting the follo)-.25 F 1.366
+(wing lines with a space or a tab)-.25 F 6.366(.S)-.4 G(ome)486.78 438.6 Q .211
+(header \214elds ha)102 450.6 R .511 -.15(ve s)-.2 H .211
+(pecial internal meaning, and ha).15 F .511 -.15(ve a)-.2 H .211
+(ppropriate special processing.).15 F .21(Other headers)5.21 F
+(are simply passed through.)102 462.6 Q
+(Some header \214elds may be added automatically)5 E 2.5(,s)-.65 G
+(uch as time stamps.)413.53 462.6 Q F0 2.5(4. THE)72 486.6 R(UUCP PR)2.5 E
+(OBLEM)-.3 E F1 .43(Of particular interest is the UUCP netw)112 502.8 R 2.93
+(ork. The)-.1 F -.15(ex)2.93 G .43(plicit routing used in the UUCP en).15 F
+(vironment)-.4 E .909(causes a number of serious problems.)87 514.8 R .909
+(First, gi)5.909 F .908(ving out an address is impossible without kno)-.25 F
+.908(wing the)-.25 F .453(address of your potential correspondent.)87 526.8 R
+.454(This is typically handled by specifying the address relati)5.453 F .754
+-.15(ve t)-.25 H(o).15 E 1.208(some \231well-kno)87 538.8 R 1.208
+(wn\232 host \(e.g., ucb)-.25 F -.25(va)-.15 G 3.708(xo).25 G 3.708(rd)253.47
+538.8 S(ecv)265.508 538.8 Q 3.708(ax\). Second,)-.25 F 1.207(it is often dif)
+3.708 F 1.207(\214cult to compute the set of)-.25 F .157
+(addresses to reply to without some kno)87 550.8 R .157
+(wledge of the topology of the netw)-.25 F 2.657(ork. Although)-.1 F .157
+(it may be easy)2.657 F .352(for a human being to do this under man)87 562.8 R
+2.851(yc)-.15 G .351(ircumstances, a program does not ha)259.713 562.8 R .651
+-.15(ve e)-.2 H .351(qually sophisticated).15 F 1.153(heuristics b)87 574.8 R
+1.153(uilt in.)-.2 F 1.154(Third, certain addresses will become painfully and \
+unnecessarily long, as when a)6.153 F .406(message is routed through man)87
+586.8 R 2.906(yh)-.15 G .406(osts in the USENET)225.81 586.8 R 5.406(.A)-.74 G
+.406(nd \214nally)322.804 586.8 R 2.905(,c)-.65 G .405(ertain \231mix)370.465
+586.8 R .405(ed domain\232 addresses)-.15 F
+(are impossible to parse unambiguously \212 e.g.,)87 598.8 Q(decv)127 615 Q
+(ax!ucb)-.25 E -.25(va)-.15 G(x!lbl-h!user@LBL-CSAM).25 E .378(might ha)87
+631.2 R .678 -.15(ve m)-.2 H(an).15 E 2.878(yp)-.15 G .379
+(ossible resolutions, depending on whether the message w)164.574 631.2 R .379
+(as \214rst routed to decv)-.1 F .379(ax or)-.25 F(to LBL-CSAM.)87 643.2 Q 2.32
+-.8(To s)112 659.4 T(olv).8 E 3.22(et)-.15 G .72
+(his problem, the UUCP syntax w)152.49 659.4 R .719(ould ha)-.1 F 1.019 -.15
+(ve t)-.2 H 3.219(ob).15 G 3.219(ec)346.956 659.4 S .719
+(hanged to use addresses rather than)359.055 659.4 R 3.718(routes. F)87 671.4 R
+1.218(or e)-.15 F 1.218(xample, the address \231decv)-.15 F(ax!ucb)-.25 E -.25
+(va)-.15 G 1.218(x!eric\232 might be e).25 F 1.218(xpressed as \231eric@ucb)
+-.15 F -.25(va)-.15 G(x.UUCP\232).25 E .079(\(with the hop through decv)87
+683.4 R .079(ax implied\).)-.25 F .079(This address w)5.079 F .078
+(ould itself be a domain-based address; for e)-.1 F(xam-)-.15 E
+(ple, an address might be of the form:)87 695.4 Q(mark@d.cbosg.btl.UUCP)127
+711.6 Q F0 -1(Ve)72 756 S(rsion 8.1)1 E(USENIX \255 J)249.805 756 Q(an 83)-.15
+E(Last Mod 6/7/93)434.55 756 Q EP
+%%Page: 7 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Mail Systems and Addr)72 60 Q(essing in 4.2bsd)-.18 E(7)
+499 60 Q/F1 10/Times-Roman@0 SF .311(Hosts outside of Bell T)87 96 R .311
+(elephone Laboratories w)-.7 F .311(ould then only need to kno)-.1 F 2.811(wh)
+-.25 G .811 -.25(ow t)402.982 96 T 2.811(og).25 G .312(et to a designated)
+433.354 96 R(BTL relay)87 108 Q 2.5(,a)-.65 G(nd the BTL topology w)137.17 108
+Q(ould only be maintained inside Bell.)-.1 E .543(There are three major proble\
+ms associated with turning UUCP addresses into something reason-)112 124.2 R
+.465(able: de\214ning the namespace, creating and propag)87 136.2 R .465
+(ating the necessary softw)-.05 F .466(are, and b)-.1 F .466(uilding and main-)
+-.2 F(taining the database.)87 148.2 Q F0 2.5(4.1. De\214ning)87 172.2 R
+(the Namespace)2.5 E F1 1.015(Putting all UUCP hosts into a \215at namespace \
+\(e.g., \231...@host.UUCP\232\) is not practical for a)127 188.4 R .222
+(number of reasons.)102 200.4 R .222(First, with o)5.222 F -.15(ve)-.15 G 2.722
+(r1).15 G .222(600 sites already)253.292 200.4 R 2.722(,a)-.65 G .222
+(nd \(with the increasing a)329.958 200.4 R -.25(va)-.2 G .222
+(ilability of ine).25 F(x-)-.15 E(pensi)102 212.4 Q 1.973 -.15(ve m)-.25 H
+1.673(icrocomputers and autodialers\) se).15 F -.15(ve)-.25 G 1.672
+(ral thousand more coming within a fe).15 F 4.172(wy)-.25 G 1.672(ears, the)
+469.008 212.4 R .078
+(database update problem is simply intractable if the namespace is \215at.)102
+224.4 R .078(Second, there are almost cer)5.078 F(-)-.2 E 2.446
+(tainly name con\215icts today)102 236.4 R 7.446(.T)-.65 G 2.446
+(hird, as the number of sites gro)232.794 236.4 R 4.946(wt)-.25 G 2.446
+(he names become e)386.316 236.4 R -.15(ve)-.25 G 4.946(rl).15 G(ess)491.78
+236.4 Q(mnemonic.)102 248.4 Q .534(It seems ine)127 264.6 R .535
+(vitable that there be some sort of naming authority for the set of top le)-.25
+F -.15(ve)-.25 G 3.035(ln).15 G(ames)483.45 264.6 Q .157
+(in the UUCP domain, as unpleasant a possibility as that may seem.)102 276.6 R
+.157(It will simply not be possible to)5.157 F(ha)102 288.6 Q .536 -.15(ve o)
+-.2 H .236(ne host resolving all names.).15 F .236(It may ho)5.236 F(we)-.25 E
+-.15(ve)-.25 G 2.736(rb).15 G 2.736(ep)316.144 288.6 S .236
+(ossible to handle this in a f)328.32 288.6 R .237(ashion similar to)-.1 F
+1.582(that of assigning names of ne)102 300.6 R 1.582(wsgroups in USENET)-.25 F
+6.582(.H)-.74 G -.25(ow)334.758 300.6 S -2.15 -.25(ev e).25 H 2.382 -.4(r, i)
+.25 H 4.082(tw).4 G 1.582(ill be essential to encourage)386.582 300.6 R -2.15
+-.25(ev e)102 312.6 T .52(ryone to become subdomains of an e).25 F .52
+(xisting domain whene)-.15 F -.15(ve)-.25 G 3.02(rp).15 G .52(ossible \212 e)
+374.85 312.6 R -.15(ve)-.25 G 3.02(nt).15 G .52(hough this will)442.95 312.6 R
+.077(certainly bruise some e)102 324.6 R 2.577(gos. F)-.15 F .077(or e)-.15 F
+.077(xample, if a ne)-.15 F 2.577(wh)-.25 G .076
+(ost named \231blid\232 were to be added to the UUCP)310.843 324.6 R(netw)102
+336.6 Q .65(ork, it w)-.1 F .651(ould probably actually be addressed as \231d.\
+bli.UUCP\232 \(i.e., as host \231d\232 in the pseudo-)-.1 F
+(domain \231bli\232 rather than as host \231blid\232 in the UUCP domain\).)102
+348.6 Q F0 2.5(4.2. Cr)87 372.6 R(eating and Pr)-.18 E(opagating the Softwar)
+-.18 E(e)-.18 E F1 .078(The softw)127 388.8 R .078
+(are required to implement a consistent namespace is relati)-.1 F -.15(ve)-.25
+G .077(ly tri).15 F 2.577(vial. T)-.25 F .277 -.1(wo m)-.8 H(odules).1 E
+(are needed, one to handle incoming mail and one to handle outgoing mail.)102
+400.8 Q 1.136(The incoming module must be prepared to handle either old or ne)
+127 417 R 3.636(ws)-.25 G 1.136(tyle addresses.)416.448 417 R(Ne)6.136 E(w-)
+-.25 E .025(style addresses can be passed through unchanged.)102 429 R .024
+(Old style addresses must be turned into ne)5.025 F 2.524(ws)-.25 G(tyle)489
+429 Q(addresses where possible.)102 441 Q 2.247
+(The outgoing module is slightly trickier)127 457.2 R 7.247(.I)-.55 G 4.747(tm)
+309.932 457.2 S 2.247(ust do a database lookup on the recipient)325.239 457.2 R
+.823(addresses \(passed on the command line\) to determine what hosts to send \
+the message to.)102 469.2 R .823(If those)5.823 F .023(hosts do not accept ne)
+102 481.2 R .024(w-style addresses, it must transform all addresses in the hea\
+der of the message)-.25 F(into old style using the database lookup.)102 493.2 Q
+1.197(Both of these modules are straightforw)127 509.4 R 1.197(ard e)-.1 F
+1.197(xcept for the issue of modifying the header)-.15 F 6.197(.I)-.55 G(t)
+501.22 509.4 Q .944
+(seems prudent to choose one format for the message headers.)102 521.4 R -.15
+(Fo)5.944 G 3.444(ran).15 G .944(umber of reasons, Berk)391.448 521.4 R(ele)-.1
+E(y)-.15 E .824(has elected to use the ARP)102 533.4 R .824
+(ANET protocols for message formats.)-.92 F(Ho)5.823 E(we)-.25 E -.15(ve)-.25 G
+1.623 -.4(r, t).15 H .823(his protocol is some-).4 F(what dif)102 545.4 Q
+(\214cult to parse.)-.25 E(Propag)127 561.6 Q 1.903(ation is some)-.05 F 1.903
+(what more dif)-.25 F 4.403(\214cult. There)-.25 F 1.903(are a lar)4.403 F
+1.903(ge number of hosts connected to)-.18 F .812(UUCP that will w)102 573.6 R
+.811(ant to run completely standard systems \(for v)-.1 F .811
+(ery good reasons\).)-.15 F .811(The strate)5.811 F .811(gy is)-.15 F
+(not to con)102 585.6 Q -.15(ve)-.4 G(rt the entire netw).15 E
+(ork \212 only enough of it it alle)-.1 E(viate the problem.)-.25 E F0 2.5
+(4.3. Building)87 609.6 R(and Maintaining the Database)2.5 E F1 .127
+(This is by f)127 625.8 R .127(ar the most dif)-.1 F .128(\214cult problem.)
+-.25 F 2.628(Ap)5.128 G .128(rototype for this database already e)309.736 625.8
+R .128(xists, b)-.15 F .128(ut it is)-.2 F
+(maintained by hand and does not pretend to be complete.)102 637.8 Q .701(This\
+ problem will be reduced considerably if people choose to group their hosts in\
+to subdo-)127 654 R 3.219(mains. This)102 666 R -.1(wo)3.219 G .719
+(uld require a global update only when a ne).1 F 3.22(wt)-.25 G .72(op le)
+356.47 666 R -.15(ve)-.25 G 3.22(ld).15 G .72(omain joined the netw)396.95 666
+R(ork.)-.1 E 2.805(Am)102 678 S .305
+(essage to a host in a subdomain could simply be routed to a kno)119.805 678 R
+.304(wn domain g)-.25 F(ate)-.05 E -.1(wa)-.25 G 2.804(yf).1 G .304(or further)
+465.656 678 R 3.073(processing. F)102 690 R .573(or e)-.15 F .573(xample, the \
+address \231eric@a.bli.UUCP\232 might be routed to the \231bli\232 g)-.15 F
+(ate)-.05 E -.1(wa)-.25 G 3.074(yf).1 G(or)495.67 690 Q(redistrib)102 702 Q
+1.376(ution; ne)-.2 F 3.876(wh)-.25 G 1.375
+(osts could be added within BLI without notifying the rest of the w)187.632 702
+R 3.875(orld. Of)-.1 F(course, other hosts)102 714 Q/F2 10/Times-Italic@0 SF
+(could)2.5 E F1(be noti\214ed as an ef)2.5 E(\214cienc)-.25 E 2.5(ym)-.15 G
+(easure.)321.01 714 Q F0 -1(Ve)72 756 S(rsion 8.1)1 E(USENIX \255 J)249.805 756
+Q(an 83)-.15 E(Last Mod 6/7/93)434.55 756 Q EP
+%%Page: 8 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Mail Systems and Addr)72 60 Q(essing in 4.2bsd)-.18 E(8)
+499 60 Q/F1 10/Times-Roman@0 SF .966(There may be more than one domain g)127 96
+R(ate)-.05 E -.1(wa)-.25 G 4.767 -.65(y. A).1 H .967
+(domain such as BTL, for instance, might)4.117 F(ha)102 108 Q .653 -.15(ve a d)
+-.2 H .353(ozen g).15 F(ate)-.05 E -.1(wa)-.25 G .353(ys to the outside w).1 F
+.352(orld; a non-BTL site could choose the closest g)-.1 F(ate)-.05 E -.1(wa)
+-.25 G 4.152 -.65(y. T).1 H(he).65 E .308(only restriction w)102 120 R .308
+(ould be that all g)-.1 F(ate)-.05 E -.1(wa)-.25 G .308
+(ys maintain a consistent vie).1 F 2.808(wo)-.25 G 2.808(ft)390.998 120 S .308
+(he domain the)399.916 120 R 2.808(yr)-.15 G(epresent.)468.18 120 Q F0 2.5
+(4.4. Logical)87 144 R(Structur)2.5 E(e)-.18 E F1(Logically)127 160.2 Q 3.803
+(,d)-.65 G 1.303(omains are or)175.983 160.2 R -.05(ga)-.18 G 1.303
+(nized into a tree.).05 F 1.303(There need not be a host actually associated)
+6.303 F .462(with each le)102 172.2 R -.15(ve)-.25 G 2.962(li).15 G 2.962(nt)
+168.806 172.2 S .462(he tree \212 for e)179.548 172.2 R .462
+(xample, there will be no host associated with the name \231UUCP)-.15 F -.7
+<2e9a>-1.11 G(Similarly)102 184.2 Q 3.115(,a)-.65 G 3.115(no)148.635 184.2 S
+-2.19 -.18(rg a)161.75 184.2 T .614
+(nization might group names together for administrati).18 F .914 -.15(ve r)-.25
+H .614(easons; for e).15 F .614(xample, the)-.15 F(name)102 196.2 Q
+(CAD.research.BigCorp.UUCP)142 212.4 Q(might not actually ha)102 228.6 Q .3
+-.15(ve a h)-.2 H(ost representing \231research.).15 E<9a>-.7 E(Ho)127 244.8 Q
+(we)-.25 E -.15(ve)-.25 G 1.531 -.4(r, i).15 H 3.231(tm).4 G .731
+(ay frequently be con)184.902 244.8 R -.15(ve)-.4 G .731(nient to ha).15 F
+1.031 -.15(ve a h)-.2 H .732(ost or hosts that \231represent\232 a domain.).15
+F -.15(Fo)102 256.8 S 3.466(re).15 G .966(xample, if a single host e)123.496
+256.8 R .966(xists that represents Berk)-.15 F(ele)-.1 E 2.266 -.65(y, t)-.15 H
+.966(hen mail from outside Berk).65 F(ele)-.1 E 3.466(yc)-.15 G(an)494.56 256.8
+Q(forw)102 268.8 Q .796
+(ard mail to that host for further resolution without kno)-.1 F .796(wing Berk)
+-.25 F(ele)-.1 E(y')-.15 E 3.296(s\()-.55 G .797(rather v)417.066 268.8 R .797
+(olatile\) topol-)-.2 F(ogy)102 280.8 Q 5(.T)-.65 G(his is not unlik)129.96
+280.8 Q 2.5(et)-.1 G(he operation of the telephone netw)198.76 280.8 Q(ork.)-.1
+E .053(This may also be useful inside certain lar)127 297 R .053(ge domains.)
+-.18 F -.15(Fo)5.053 G 2.553(re).15 G .053(xample, at Berk)365.352 297 R(ele)
+-.1 E 2.553(yi)-.15 G 2.553(tm)450.801 297 S .053(ay be pre-)463.914 297 R .722
+(sumed that most hosts kno)102 309 R 3.222(wa)-.25 G .722
+(bout other hosts inside the Berk)225.64 309 R(ele)-.1 E 3.223(yd)-.15 G 3.223
+(omain. But)380.825 309 R .723(if the)3.223 F 3.223(yp)-.15 G .723(rocess an)
+466.347 309 R .405(address that is unkno)102 321 R .405(wn, the)-.25 F 2.905
+(yc)-.15 G .405(an pass it \231upstairs\232 for further e)229.165 321 R 2.905
+(xamination. Thus)-.15 F .405(as ne)2.905 F 2.905(wh)-.25 G .405(osts are)
+473.325 321 R .488(added only one host \(the domain master\))102 333 R/F2 10
+/Times-Italic@0 SF(must)2.989 E F1 .489
+(be updated immediately; other hosts can be updated)2.989 F(as con)102 345 Q
+-.15(ve)-.4 G(nient.).15 E .583(Ideally this name resolution process w)127
+361.2 R .583(ould be performed by a name serv)-.1 F .582
+(er \(e.g., [Su82b]\) to)-.15 F -.2(avo)102 373.2 S .507(id unnecessary cop).2
+F .507(ying of the message.)-.1 F(Ho)5.507 E(we)-.25 E -.15(ve)-.25 G 1.307 -.4
+(r, i).15 H 3.007(nab).4 G .507(atch netw)346.623 373.2 R .508
+(ork such as UUCP this could)-.1 F(result in unnecessary delays.)102 385.2 Q F0
+2.5(5. COMP)72 409.2 R(ARISON WITH DELIVERMAIL)-.74 E F2(Sendmail)112 425.4 Q
+F1(is an outgro)2.5 E(wth of)-.25 E F2(delivermail)2.5 E F1 5(.T)C
+(he primary dif)286.18 425.4 Q(ferences are:)-.25 E 12.5(\(1\) Con\214guration)
+92 441.6 R .573(information is not compiled in.)3.073 F .572
+(This change simpli\214es man)5.572 F 3.072(yo)-.15 G 3.072(ft)433.684 441.6 S
+.572(he problems of)442.866 441.6 R(mo)118.66 453.6 Q(ving to other machines.)
+-.15 E(It also allo)5 E(ws easy deb)-.25 E(ugging of ne)-.2 E 2.5(wm)-.25 G
+(ailers.)388.06 453.6 Q 12.5(\(2\) Address)92 469.8 R .491
+(parsing is more \215e)2.991 F 2.991(xible. F)-.15 F .491(or e)-.15 F(xample,)
+-.15 E F2(delivermail)2.992 E F1 .492(only supported one g)2.992 F(ate)-.05 E
+-.1(wa)-.25 G 2.992(yt).1 G 2.992(oa)481.718 469.8 S -.15(ny)494.15 469.8 S
+(netw)118.66 481.8 Q(ork, whereas)-.1 E F2(sendmail)2.5 E F1(can be sensiti)2.5
+E .3 -.15(ve t)-.25 H 2.5(oh).15 G(ost names and reroute to dif)310.9 481.8 Q
+(ferent g)-.25 E(ate)-.05 E -.1(wa)-.25 G(ys.).1 E 12.5(\(3\) F)92 498 R(orw)
+-.15 E 2.878(arding and :include: features eliminate the requirement that the \
+system alias \214le be)-.1 F 1.073(writable by an)118.66 510 R 3.573(yu)-.15 G
+1.073
+(ser \(or that an update program be written, or that the system administration)
+191.439 510 R(mak)118.66 522 Q 2.5(ea)-.1 G(ll changes\).)147.16 522 Q(\(4\))92
+538.2 Q F2(Sendmail)118.66 538.2 Q F1 .443
+(supports message batching across netw)2.944 F .443
+(orks when a message is being sent to multiple)-.1 F(recipients.)118.66 550.2 Q
+12.5(\(5\) A)92 566.4 R 1.945(mail queue is pro)4.445 F 1.946(vided in)-.15 F
+F2(sendmail.)4.446 E F1 1.946(Mail that cannot be deli)6.946 F -.15(ve)-.25 G
+1.946(red immediately b).15 F 1.946(ut can)-.2 F .439(potentially be deli)
+118.66 578.4 R -.15(ve)-.25 G .438
+(red later is stored in this queue for a later retry).15 F 5.438(.T)-.65 G .438
+(he queue also pro)404.088 578.4 R .438(vides a)-.15 F -.2(bu)118.66 590.4 S
+-.25(ff).2 G .838(er ag).25 F .839(ainst system crashes; after the message has\
+ been collected it may be reliably redeli)-.05 F(v-)-.25 E(ered e)118.66 602.4
+Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(ft)162.13 602.4 S
+(he system crashes during the initial deli)170.74 602.4 Q -.15(ve)-.25 G(ry).15
+E(.)-.65 E(\(6\))92 618.6 Q F2(Sendmail)118.66 618.6 Q F1 1.351(uses the netw)
+3.851 F 1.351(orking support pro)-.1 F 1.351(vided by 4.2BSD to pro)-.15 F 1.35
+(vide a direct interf)-.15 F 1.35(ace net-)-.1 F -.1(wo)118.66 630.6 S .283
+(rks such as the ARP).1 F .284
+(ANET and/or Ethernet using SMTP \(the Simple Mail T)-.92 F .284
+(ransfer Protocol\))-.35 F -.15(ove)118.66 642.6 S 2.5(raT).15 G
+(CP/IP connection.)151.68 642.6 Q F0 -1(Ve)72 756 S(rsion 8.1)1 E
+(USENIX \255 J)249.805 756 Q(an 83)-.15 E(Last Mod 6/7/93)434.55 756 Q EP
+%%Page: 9 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Roman@0 SF(REFERENCES)264.105 132 Q([Crock)87 148.2 Q 56.73
+(er77] Crock)-.1 F(er)-.1 E 3.535(,D)-.4 G 3.535(.H)239.965 148.2 S 1.035(., V)
+253.22 148.2 R 1.035(ittal, J. J., Pogran, K. T)-.6 F 1.035
+(., and Henderson, D. A. Jr)-.74 F(.,)-.55 E/F1 10/Times-Italic@0 SF(Stan-)
+3.535 E(dar)195 160.2 Q 2.627(df)-.37 G .127(or the F)218.927 160.2 R .127
+(ormat of ARP)-1.05 F 2.627(AN)-.9 G .128(etwork T)320.112 160.2 R -.2(ex)-.92
+G 2.628(tM).2 G(essa)377.018 160.2 Q -.1(ge)-.1 G(s.).1 E F0 .128
+(RFC 733, NIC 41952.)5.128 F(In [Feinler78].)195 172.2 Q(No)5 E -.15(ve)-.15 G
+(mber 1977.).15 E([Crock)87 188.4 Q 56.73(er82] Crock)-.1 F(er)-.1 E 4.272(,D)
+-.4 G 4.272(.H)240.702 188.4 S(.,)254.694 188.4 Q F1(Standar)4.272 E 4.272(df)
+-.37 G 1.772(or the F)307.318 188.4 R 1.772(ormat of Arpa Internet T)-1.05 F
+-.2(ex)-.92 G 4.271(tM).2 G(essa)471.15 188.4 Q -.1(ge)-.1 G(s.).1 E F0 .025
+(RFC 822.)195 200.4 R(Netw)5.025 E .025(ork Information Center)-.1 F 2.526(,S)
+-.4 G .026(RI International, Menlo P)363.506 200.4 R .026(ark, Cali-)-.15 F 2.5
+(fornia. August)195 212.4 R(1982.)2.5 E 60.51([Feinler78] Feinler)87 228.6 R
+2.938(,E)-.4 G .438(., and Postel, J.)234.478 228.6 R(\(eds.\),)5.438 E F1(ARP)
+2.938 E .438(ANET Pr)-.9 F .438(otocol Handbook.)-.45 F F0 .438(NIC 7104,)5.438
+F(Netw)195 240.6 Q 3.011(ork Information Center)-.1 F 5.511(,S)-.4 G 3.012
+(RI International, Menlo P)328.513 240.6 R 3.012(ark, California.)-.15 F(1978.)
+195 252.6 Q([No)87 268.8 Q 59.65(witz78] No)-.25 F .479
+(witz, D. A., and Lesk, M. E.,)-.25 F F1 2.978(AD)2.978 G .478
+(ial-Up Network of UNIX Systems.)344.67 268.8 R F0(Bell)5.478 E 3.528
+(Laboratories. In)195 280.8 R 1.029(UNIX Programmer')3.528 F 3.529(sM)-.55 G
+1.029(anual, Se)363.524 280.8 R -.15(ve)-.25 G 1.029(nth Edition, V).15 F 1.029
+(olume 2.)-1.29 F(August, 1978.)195 292.8 Q 55.5([Schmidt79] Schmidt,)87 309 R
+(E.,)2.631 E F1 .131(An Intr)2.631 F .131(oduction to the Berk)-.45 F(ele)-.1 E
+2.631(yN)-.3 G(etwork.)382.277 309 Q F0(Uni)5.131 E -.15(ve)-.25 G .131
+(rsity of Califor).15 F(-)-.2 E(nia, Berk)195 321 Q(ele)-.1 E 2.5(yC)-.15 G 2.5
+(alifornia. 1979.)257.24 321 R 59.95([Shoens79] Shoens,)87 337.2 R(K.,)3.227 E
+F1 .728(Mail Refer)3.227 F .728(ence Manual.)-.37 F F0(Uni)5.728 E -.15(ve)-.25
+G .728(rsity of California, Berk).15 F(ele)-.1 E 4.528 -.65(y. I)-.15 H(n).65 E
+3.478(UNIX Programmer')195 349.2 R 5.977(sM)-.55 G 3.477(anual, Se)297.495
+349.2 R -.15(ve)-.25 G 3.477(nth Edition, V).15 F 3.477(olume 2C.)-1.29 F
+(December)8.477 E(1979.)195 361.2 Q 52.72([Solomon81] Solomon,)87 377.4 R .251
+(M., Landweber)2.75 F 2.751(,L)-.4 G .251(., and Neuhengen, D.,)308.952 377.4 R
+F1 .251(The Design of the CSNET)2.751 F .397(Name Server)195 389.4 R(.)-1.11 E
+F0 2.896(CS-DN-2. Uni)5.397 F -.15(ve)-.25 G .396(rsity of W).15 F .396
+(isconsin, Madison.)-.4 F .396(October 1981.)5.396 F 73.84([Su82a] Su,)87 405.6
+R(Za)2.844 E .344(w-Sing, and Postel, Jon,)-.15 F F1 .344
+(The Domain Naming Con)2.844 F .344(vention for Internet)-.4 F 2.71
+(User Applications.)195 417.6 R F0 5.21(RFC819. Netw)7.71 F 2.71
+(ork Information Center)-.1 F 5.21(,S)-.4 G 2.71(RI Interna-)457.14 417.6 R
+(tional, Menlo P)195 429.6 Q(ark, California.)-.15 E(August 1982.)5 E 73.28
+([Su82b] Su,)87 445.8 R(Za)4.174 E(w-Sing,)-.15 E F1 4.174(AD)4.174 G(istrib)
+275.702 445.8 Q 1.675(uted System for Internet Name Service)-.2 F(.)-.15 E F0
+(RFC830.)6.675 E(Netw)195 457.8 Q 3.012(ork Information Center)-.1 F 5.512(,S)
+-.4 G 3.011(RI International, Menlo P)328.516 457.8 R 3.011(ark, California.)
+-.15 F(October 1982.)195 469.8 Q/F2 10/Times-Bold@0 SF(Mail Systems and Addr)72
+756 Q(essing in 4.2bsd)-.18 E(9)499 756 Q EP
+%%Trailer
+end
+%%EOF
index eda6ed4..d6a04f0 100644 (file)
@@ -1,4 +1,4 @@
-#      @(#)Makefile    5.1 (Berkeley) 5/11/90
+#      @(#)Makefile    8.1 (Berkeley) 6/7/93
 
 PROG=  mailstats
 CFLAGS+=-I${.CURDIR}/../src
 
 PROG=  mailstats
 CFLAGS+=-I${.CURDIR}/../src
index 27c6994..648f1c6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1988 Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
      The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)mailstats.c        5.7 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)mailstats.c        8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #include <sys/file.h>
 #include <sendmail.h>
 #include <mailstats.h>
 #endif /* not lint */
 
 #include <sys/file.h>
 #include <sendmail.h>
 #include <mailstats.h>
-#include "pathnames.h"
+#include <pathnames.h>
+
+#define MNAMELEN       20      /* max length of mailer name */
 
 main(argc, argv)
        int argc;
 
 main(argc, argv)
        int argc;
@@ -56,40 +58,145 @@ main(argc, argv)
        extern int optind;
        struct statistics stat;
        register int i;
        extern int optind;
        struct statistics stat;
        register int i;
+       int mno;
        int ch, fd;
        int ch, fd;
-       char *sfile, *ctime();
+       char *sfile;
+       char *cfile;
+       FILE *cfp;
+       bool mnames;
+       char mtable[MAXMAILERS][MNAMELEN+1];
+       char sfilebuf[100];
+       char buf[MAXLINE];
+       extern char *ctime();
+
+       cfile = _PATH_SENDMAILCF;
+       sfile = NULL;
+       mnames = TRUE;
+       while ((ch = getopt(argc, argv, "C:f:o")) != EOF)
+       {
+               switch (ch)
+               {
+                 case 'C':
+                       cfile = optarg;
+                       break;
 
 
-       sfile = _PATH_MAILSTATS;
-       while ((ch = getopt(argc, argv, "f:")) != EOF)
-               switch((char)ch) {
-               case 'f':
+                 case 'f':
                        sfile = optarg;
                        break;
                        sfile = optarg;
                        break;
-               case '?':
-               default:
-                       fputs("usage: mailstats [-f file]\n", stderr);
+
+                 case 'o':
+                       mnames = FALSE;
+                       break;
+
+                 case '?':
+                 default:
+  usage:
+                       fputs("usage: mailstats [-C cffile] [-f stfile]\n", stderr);
                        exit(EX_USAGE);
                }
                        exit(EX_USAGE);
                }
+       }
        argc -= optind;
        argv += optind;
 
        argc -= optind;
        argv += optind;
 
+       if (argc != 0)
+               goto usage;
+
+       if ((cfp = fopen(cfile, "r")) == NULL)
+       {
+               fprintf(stderr, "mailstats: ");
+               perror(cfile);
+               exit(EX_NOINPUT);
+       }
+
+       mno = 0;
+       (void) strcpy(mtable[mno++], "prog");
+       (void) strcpy(mtable[mno++], "*file*");
+       (void) strcpy(mtable[mno++], "*include*");
+
+       while (fgets(buf, sizeof(buf), cfp) != NULL)
+       {
+               register char *b;
+               char *s;
+               register char *m;
+
+               b = buf;
+               switch (*b++)
+               {
+                 case 'M':             /* mailer definition */
+                       break;
+
+                 case 'O':             /* option -- see if .st file */
+                       if (*b++ != 'S')
+                               continue;
+
+                       /* yep -- save this */
+                       strcpy(sfilebuf, b);
+                       b = strchr(sfilebuf, '\n');
+                       if (b != NULL)
+                               *b = '\0';
+                       if (sfile == NULL)
+                               sfile = sfilebuf;
+
+                 default:
+                       continue;
+               }
+
+               if (mno >= MAXMAILERS)
+               {
+                       fprintf(stderr,
+                               "Too many mailers defined, %d max.\n",
+                               MAXMAILERS);
+                       exit(EX_SOFTWARE);
+               }
+               m = mtable[mno];
+               s = m + MNAMELEN;               /* is [MNAMELEN+1] */
+               while (*b != ',' && !isspace(*b) && *b != '\0' && m < s)
+                       *m++ = *b++;
+               *m = '\0';
+               for (i = 0; i < mno; i++)
+               {
+                       if (strcmp(mtable[i], mtable[mno]) == 0)
+                               break;
+               }
+               if (i == mno)
+                       mno++;
+       }
+       (void) fclose(cfp);
+       for (; mno < MAXMAILERS; mno++)
+               mtable[mno][0]='\0';
+
+       if (sfile == NULL)
+       {
+               fprintf(stderr, "mailstats: no statistics file located\n");
+               exit (EX_OSFILE);
+       }
+
        if ((fd = open(sfile, O_RDONLY)) < 0) {
                fputs("mailstats: ", stderr);
                perror(sfile);
                exit(EX_NOINPUT);
        }
        if (read(fd, &stat, sizeof(stat)) != sizeof(stat) ||
        if ((fd = open(sfile, O_RDONLY)) < 0) {
                fputs("mailstats: ", stderr);
                perror(sfile);
                exit(EX_NOINPUT);
        }
        if (read(fd, &stat, sizeof(stat)) != sizeof(stat) ||
-           stat.stat_size != sizeof(stat)) {
+           stat.stat_size != sizeof(stat))
+       {
                fputs("mailstats: file size changed.\n", stderr);
                exit(EX_OSERR);
        }
 
        printf("Statistics from %s", ctime(&stat.stat_itime));
                fputs("mailstats: file size changed.\n", stderr);
                exit(EX_OSERR);
        }
 
        printf("Statistics from %s", ctime(&stat.stat_itime));
-       printf(" M msgsfr bytes_from  msgsto   bytes_to\n");
+       printf(" M msgsfr bytes_from  msgsto   bytes_to%s\n",
+               mnames ? "  Mailer" : "");
        for (i = 0; i < MAXMAILERS; i++)
        for (i = 0; i < MAXMAILERS; i++)
+       {
                if (stat.stat_nf[i] || stat.stat_nt[i])
                if (stat.stat_nf[i] || stat.stat_nt[i])
-                       printf("%2d %6ld %10ldK %6ld %10ldK\n", i,
+               {
+                       printf("%2d %6ld %10ldK %6ld %10ldK", i,
                            stat.stat_nf[i], stat.stat_bf[i],
                            stat.stat_nt[i], stat.stat_bt[i]);
                            stat.stat_nf[i], stat.stat_bf[i],
                            stat.stat_nt[i], stat.stat_bt[i]);
-       exit(0);
+                       if (mnames)
+                               printf("  %s", mtable[i]);
+                       printf("\n");
+               }
+       }
+       exit(EX_OK);
 }
 }
diff --git a/usr.sbin/sendmail/makemap/Makefile b/usr.sbin/sendmail/makemap/Makefile
new file mode 100644 (file)
index 0000000..462583a
--- /dev/null
@@ -0,0 +1,8 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/7/93
+
+PROG=  makemap
+MAN8=  makemap.0
+CFLAGS+=-I${.CURDIR}/../src -DNDBM -DNEWDB
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/makemap/makemap.8 b/usr.sbin/sendmail/makemap/makemap.8
new file mode 100644 (file)
index 0000000..70ee446
--- /dev/null
@@ -0,0 +1,127 @@
+.\" Copyright (c) 1988, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"     @(#)makemap.8  8.1 (Berkeley) 6/17/93
+.\"
+.Dd November 16, 1992
+.Dt MAKEMAP 8
+.Os BSD 4.4
+.Sh NAME
+.Nm makemap
+.Nd create database maps for sendmail
+.Sh SYNOPSIS
+.Nm
+.Op Fl N
+.Op Fl f
+.Op Fl o
+.Op Fl r
+.Op Fl v
+.Ar maptype
+.Ar mapname
+.Sh DESCRIPTION
+.Nm
+creates the database maps used by the keyed map lookups in
+.Xr sendmail 8 .
+It reads input from the standard input
+and outputs them to the indicated
+.Ar mapname .
+.Pp
+Depending on how it is compiled,
+.Nm
+handles up to three different database formats,
+selected using the
+.Ar maptype
+parameter.
+They may be
+.Bl -tag -width Fl
+.It Li dbm
+DBM format maps.
+This requires the
+.Xr ndbm 3
+library.
+.It Li btree
+B-Tree format maps.
+This requires the new Berkeley
+.Xr db 3
+library.
+.It Li hash
+Hash format maps.
+This also requires the
+.Xr db 3
+library.
+.El
+.Pp
+In all cases,
+.Nm
+reads lines from the standard input consisting of two
+words separated by white space.
+The first is the database key,
+the second is the value.
+The value may contain
+``%\fIn\fP''
+strings to indicated parameter substitution.
+Literal parentheses should be doubled
+(``%%'').
+Blank lines and lines beginning with ``#'' are ignored.
+.Ss Flags
+.Bl -tag -width Fl
+.It Fl N
+Include the null byte that terminates strings
+in the map.
+This must match the \-N flag in the sendmail.cf
+``K'' line.
+.It Fl f
+Fold all upper case letters in the key
+to lower case;
+this is intended to mesh with the
+\-f flag in the
+\fBK\fP
+line in sendmail.cf.
+The value is not case folded.
+.It Fl o
+Append to an old file.
+This allows you to augment an existing file.
+.It Fl r
+Allow replacement of existing keys.
+Normally
+.Nm
+complains if you repeat a key,
+and does not do the insert.
+.It Fl v
+Verbosely print what it is doing.
+.El
+.Sh SEE ALSO
+.Xr sendmail 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
diff --git a/usr.sbin/sendmail/makemap/makemap.c b/usr.sbin/sendmail/makemap/makemap.c
new file mode 100644 (file)
index 0000000..7996c1a
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 1992 Eric P. Allman.
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)makemap.c  8.1 (Berkeley) 6/7/93";
+#endif /* not lint */
+
+#include <stdio.h>
+#include <sysexits.h>
+#include <sys/file.h>
+#include <ctype.h>
+#include <string.h>
+#include "useful.h"
+#include "conf.h"
+
+#ifdef NDBM
+#include <ndbm.h>
+#endif
+
+#ifdef NEWDB
+#include <db.h>
+#endif
+
+enum type { T_DBM, T_BTREE, T_HASH, T_ERR, T_UNKNOWN };
+
+union dbent
+{
+#ifdef NDBM
+       datum   dbm;
+#endif
+#ifdef NEWDB
+       DBT     db;
+#endif
+       struct
+       {
+               char    *data;
+               int     size;
+       } xx;
+};
+
+#define BUFSIZE                1024
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       char *progname;
+       bool inclnull = FALSE;
+       bool notrunc = FALSE;
+       bool allowreplace = FALSE;
+       bool verbose = FALSE;
+       bool foldcase = FALSE;
+       int exitstat;
+       int opt;
+       char *typename;
+       char *mapname;
+       int lineno;
+       int st;
+       int mode;
+       enum type type;
+       union
+       {
+#ifdef NDBM
+               DBM     *dbm;
+#endif
+#ifdef NEWDB
+               DB      *db;
+#endif
+               void    *dbx;
+       } dbp;
+       union dbent key, val;
+       char ibuf[BUFSIZE];
+       extern char *optarg;
+       extern int optind;
+
+       progname = argv[0];
+
+       while ((opt = getopt(argc, argv, "Nforv")) != EOF)
+       {
+               switch (opt)
+               {
+                 case 'N':
+                       inclnull = TRUE;
+                       break;
+
+                 case 'f':
+                       foldcase = TRUE;
+                       break;
+
+                 case 'o':
+                       notrunc = TRUE;
+                       break;
+
+                 case 'r':
+                       allowreplace = TRUE;
+                       break;
+
+                 case 'v':
+                       verbose = TRUE;
+                       break;
+
+                 default:
+                       type = T_ERR;
+                       break;
+               }
+       }
+
+       argc -= optind;
+       argv += optind;
+       if (argc != 2)
+               type = T_ERR;
+       else
+       {
+               typename = argv[0];
+               mapname = argv[1];
+
+               if (strcmp(typename, "dbm") == 0)
+                       type = T_DBM;
+               else if (strcmp(typename, "btree") == 0)
+                       type = T_BTREE;
+               else if (strcmp(typename, "hash") == 0)
+                       type = T_HASH;
+               else
+                       type = T_UNKNOWN;
+       }
+
+       switch (type)
+       {
+         case T_ERR:
+               fprintf(stderr, "Usage: %s [-N] [-o] [-v] type mapname\n", progname);
+               exit(EX_USAGE);
+
+         case T_UNKNOWN:
+               fprintf(stderr, "%s: Unknown database type %s\n",
+                       progname, typename);
+               exit(EX_USAGE);
+
+#ifndef NDBM
+         case T_DBM:
+#endif
+#ifndef NEWDB
+         case T_BTREE:
+         case T_HASH:
+#endif
+               fprintf(stderr, "%s: Type %s not supported in this version\n",
+                       progname, typename);
+               exit(EX_UNAVAILABLE);
+       }
+
+       /*
+       **  Create the database.
+       */
+
+       mode = O_RDWR;
+       if (!notrunc)
+               mode |= O_CREAT|O_TRUNC;
+       switch (type)
+       {
+#ifdef NDBM
+         case T_DBM:
+               dbp.dbm = dbm_open(mapname, mode, 0644);
+               break;
+#endif
+
+#ifdef NEWDB
+         case T_HASH:
+               dbp.db = dbopen(mapname, mode, 0644, DB_HASH, NULL);
+               break;
+
+         case T_BTREE:
+               dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, NULL);
+               break;
+#endif
+
+         default:
+               fprintf(stderr, "%s: internal error: type %d\n", progname, type);
+               exit(EX_SOFTWARE);
+       }
+
+       if (dbp.dbx == NULL)
+       {
+               fprintf(stderr, "%s: cannot create type %s map %s\n",
+                       progname, typename, mapname);
+               exit(EX_CANTCREAT);
+       }
+
+       /*
+       **  Copy the data
+       */
+
+       lineno = 0;
+       exitstat = EX_OK;
+       while (fgets(ibuf, sizeof ibuf, stdin) != NULL)
+       {
+               register char *p;
+
+               lineno++;
+
+               /*
+               **  Parse the line.
+               */
+
+               p = strchr(ibuf, '\n');
+               if (*p != '\0')
+                       *p = '\0';
+               if (ibuf[0] == '\0' || ibuf[0] == '#')
+                       continue;
+               if (isspace(ibuf[0]))
+               {
+                       fprintf(stderr, "%s: %s: line %d: syntax error (leading space)\n",
+                               progname, mapname, lineno);
+                       continue;
+               }
+               key.xx.data = ibuf;
+               for (p = ibuf; *p != '\0' && !isspace(*p); p++)
+               {
+                       if (foldcase && isupper(*p))
+                               *p = tolower(*p);
+               }
+               key.xx.size = p - key.xx.data;
+               if (inclnull)
+                       key.xx.size++;
+               if (*p != '\0')
+                       *p++ = '\0';
+               while (isspace(*p))
+                       p++;
+               if (*p == '\0')
+               {
+                       fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n",
+                               progname, mapname, lineno, key.xx.data);
+                       continue;
+               }
+               val.xx.data = p;
+               val.xx.size = strlen(p);
+               if (inclnull)
+                       val.xx.size++;
+
+               /*
+               **  Do the database insert.
+               */
+
+               if (verbose)
+               {
+                       printf("key=`%s', val=`%s'\n", key.xx.data, val.xx.data);
+               }
+
+               switch (type)
+               {
+#ifdef NDBM
+                 case T_DBM:
+                       st = dbm_store(dbp.dbm, key.dbm, val.dbm,
+                                       allowreplace ? DBM_REPLACE : DBM_INSERT);
+                       break;
+#endif
+
+#ifdef NEWDB
+                 case T_BTREE:
+                 case T_HASH:
+                       st = (*dbp.db->put)(dbp.db, &key.db, &val.db,
+                                       allowreplace ? 0 : R_NOOVERWRITE);
+                       break;
+#endif
+               }
+
+               if (st < 0)
+               {
+                       fprintf(stderr, "%s: %s: line %d: key %s: put error\n",
+                               progname, mapname, lineno, key.xx.data);
+                       perror(mapname);
+                       exitstat = EX_IOERR;
+               }
+               else if (st > 0)
+               {
+                       fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n",
+                               progname, mapname, lineno, key.xx.data);
+               }
+       }
+
+       /*
+       **  Now close the database.
+       */
+
+       switch (type)
+       {
+#ifdef NDBM
+         case T_DBM:
+               dbm_close(dbp.dbm);
+               break;
+#endif
+
+#ifdef NEWDB
+         case T_HASH:
+         case T_BTREE:
+               if ((*dbp.db->close)(dbp.db) < 0)
+               {
+                       fprintf(stderr, "%s: %s: error on close\n",
+                               progname, mapname);
+                       perror(mapname);
+                       exitstat = EX_IOERR;
+               }
+#endif
+       }
+
+       exit (exitstat);
+}
index a90f2d8..498e171 100644 (file)
@@ -1,9 +1,8 @@
-#      @(#)Makefile    5.1 (Berkeley) 5/11/90
+#      @(#)Makefile    8.1 (Berkeley) 6/7/93
 
 PROG=  praliases
 CFLAGS+=-I${.CURDIR}/../src
 DPADD= ${LIBDBM}
 
 PROG=  praliases
 CFLAGS+=-I${.CURDIR}/../src
 DPADD= ${LIBDBM}
-LDADD= -ldbm
 NOMAN= noman
 
 .include "../../Makefile.inc"
 NOMAN= noman
 
 .include "../../Makefile.inc"
index 9217b68..b637cda 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1988 Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
      The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)praliases.c        5.5 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)praliases.c        8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #endif /* not lint */
 
+#include <ndbm.h>
 #include <sendmail.h>
 #include <sendmail.h>
+#ifdef NEWDB
+#include <db.h>
+#endif
 
 
-typedef struct {
-       char *dptr;
-       int dsize;
-} datum;
-
-
+int
 main(argc, argv)
 main(argc, argv)
+       int argc;
        char **argv;
 {
        extern char *optarg;
        extern int optind;
        char **argv;
 {
        extern char *optarg;
        extern int optind;
-       static char *filename = "/usr/lib/aliases";
-       datum content, key, firstkey(), nextkey(), fetch();
+       DBM *dbp;
+       datum content, key;
+       char *filename;
        int ch;
        int ch;
+#ifdef NEWDB
+       const DB *db;
+       DBT newdbkey, newdbcontent;
+       char buf[MAXNAME];
+#endif
 
 
+       filename = "/etc/aliases";
        while ((ch = getopt(argc, argv, "f:")) != EOF)
                switch((char)ch) {
                case 'f':
        while ((ch = getopt(argc, argv, "f:")) != EOF)
                switch((char)ch) {
                case 'f':
@@ -66,27 +73,56 @@ main(argc, argv)
                        break;
                case '?':
                default:
                        break;
                case '?':
                default:
-                       fputs("usage: praliases [-f file]\n", stderr);
+                       (void)fprintf(stderr, "usage: praliases [-f file]\n");
                        exit(EX_USAGE);
                }
        argc -= optind;
        argv += optind;
 
                        exit(EX_USAGE);
                }
        argc -= optind;
        argv += optind;
 
-       if (dbminit(filename) < 0)
-               exit(EX_OSFILE);
-       if (!argc)
-               for (key = firstkey(); key.dptr; key = nextkey(key)) {
-                       content = fetch(key);
-                       printf("%s:%s\n", key.dptr, content.dptr);
+#ifdef NEWDB
+       (void) strcpy(buf, filename);
+       (void) strcat(buf, ".db");
+       if (db = dbopen(buf, O_RDONLY, 0444 , DB_HASH, NULL)) {
+               if (!argc) {
+                       while(!db->seq(db, &newdbkey, &newdbcontent, R_NEXT))
+                               printf("%s:%s\n", newdbkey.data,
+                                               newdbcontent.data);
+               }
+               else for (; *argv; ++argv) {
+                       newdbkey.data = *argv;
+                       newdbkey.size = strlen(*argv) + 1;
+                       if ( !db->get(db, &newdbkey, &newdbcontent, 0) )
+                               printf("%s:%s\n", newdbkey.data,
+                                       newdbcontent.data);
+                       else
+                               printf("%s: No such key\n",
+                                       newdbkey.data);
+               }
+       }
+       else {
+#endif
+               if ((dbp = dbm_open(filename, O_RDONLY, 0)) == NULL) {
+                       (void)fprintf(stderr,
+                           "praliases: %s: %s\n", filename, strerror(errno));
+                       exit(EX_OSFILE);
+               }
+               if (!argc)
+                       for (key = dbm_nextkey(dbp);
+                           key.dptr != NULL; key = dbm_nextkey(dbp)) {
+                               content = dbm_fetch(dbp, key);
+                               (void)printf("%s:%s\n", key.dptr, content.dptr);
+                       }
+               else for (; *argv; ++argv) {
+                       key.dptr = *argv;
+                       key.dsize = strlen(*argv) + 1;
+                       content = dbm_fetch(dbp, key);
+                       if (!content.dptr)
+                               (void)printf("%s: No such key\n", key.dptr);
+                       else
+                               (void)printf("%s:%s\n", key.dptr, content.dptr);
                }
                }
-       else for (; *argv; ++argv) {
-               key.dptr = *argv;
-               key.dsize = strlen(*argv) + 1;
-               content = fetch(key);
-               if (!content.dptr)
-                       printf("%s: No such key\n", key.dptr);
-               else
-                       printf("%s:%s\n", key.dptr, content.dptr);
+#ifdef NEWDB
        }
        }
+#endif
        exit(EX_OK);
 }
        exit(EX_OK);
 }
diff --git a/usr.sbin/sendmail/rmail/Makefile b/usr.sbin/sendmail/rmail/Makefile
new file mode 100644 (file)
index 0000000..eb2fb48
--- /dev/null
@@ -0,0 +1,6 @@
+#      @(#)Makefile    8.1 (Berkeley) 5/31/93
+
+PROG=  rmail
+MAN8=  rmail.0
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/rmail/rmail.8 b/usr.sbin/sendmail/rmail/rmail.8
new file mode 100644 (file)
index 0000000..2079d4e
--- /dev/null
@@ -0,0 +1,71 @@
+.\" Copyright (c) 1983, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)rmail.8     6.10 (Berkeley) 4/29/93
+.\"
+.Dd April 29, 1993
+.Dt RMAIL 8
+.Os BSD 4.2
+.Sh NAME
+.Nm rmail
+.Nd handle remote mail received via uucp
+.Sh SYNOPSIS
+.Nm rmail
+.Ar user ...
+.Sh DESCRIPTION
+.Nm Rmail
+interprets incoming mail received via
+.Xr uucp 1 ,
+collapsing ``From'' lines in the form generated
+by
+.Xr mail.local 8
+into a single line of the form ``return-path!sender'',
+and passing the processed mail on to
+.Xr sendmail  8  .
+.Pp
+.Nm Rmail
+is explicitly designed for use with
+.Xr uucp
+and
+.Xr sendmail  .
+.Sh SEE ALSO
+.Xr uucp 1 ,
+.Xr mail.local 8 ,
+.Xr sendmail 8
+.Sh HISTORY
+The
+.Nm rmail
+program appeared in
+.Bx 4.2 .
+.Sh BUGS
+.Nm Rmail
+should not reside in
+.Pa /bin .
diff --git a/usr.sbin/sendmail/rmail/rmail.c b/usr.sbin/sendmail/rmail/rmail.c
new file mode 100644 (file)
index 0000000..aac400a
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)rmail.c    8.1 (Berkeley) 5/31/93";
+#endif /* not lint */
+
+/*
+ * RMAIL -- UUCP mail server.
+ *
+ * This program reads the >From ... remote from ... lines that UUCP is so
+ * fond of and turns them into something reasonable.  It then execs sendmail
+ * with various options built from these lines. 
+ *
+ * The expected syntax is:
+ *
+ *      <user> := [-a-z0-9]+
+ *      <date> := ctime format
+ *      <site> := [-a-z0-9!]+
+ * <blank line> := "^\n$"
+ *      <from> := "From" <space> <user> <space> <date>
+ *               [<space> "remote from" <space> <site>]
+ *    <forward> := ">" <from>
+ *         msg := <from> <forward>* <blank-line> <body>
+ *
+ * The output of rmail(8) compresses the <forward> lines into a single
+ * from path.
+ *
+ * The err(3) routine is included here deliberately to make this code
+ * a bit more portable.
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+void err __P((int, const char *, ...));
+void usage __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       extern char *optarg;
+       extern int errno, optind;
+       FILE *fp;
+       struct stat sb;
+       size_t fplen, fptlen, len;
+       off_t offset;
+       int ch, debug, i, pdes[2], pid, status;
+       char *addrp, *domain, *p, *t;
+       char *from_path, *from_sys, *from_user;
+       char *args[100], buf[2048], lbuf[2048];
+
+       debug = 0;
+       domain = "UUCP";                /* Default "domain". */
+       while ((ch = getopt(argc, argv, "D:T")) != EOF)
+               switch (ch) {
+               case 'T':
+                       debug = 1;
+                       break;
+               case 'D':
+                       domain = optarg;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc < 1)
+               usage();
+
+       from_path = from_sys = from_user = NULL;
+       for (offset = 0;;) {
+
+               /* Get and nul-terminate the line. */
+               if (fgets(lbuf, sizeof(lbuf), stdin) == NULL)
+                       exit (EX_DATAERR);
+               if ((p = strchr(lbuf, '\n')) == NULL)
+                       err(EX_DATAERR, "line too long");
+               *p = '\0';
+
+               /* Parse lines until reach a non-"From" line. */
+               if (!strncmp(lbuf, "From ", 5))
+                       addrp = lbuf + 5;
+               else if (!strncmp(lbuf, ">From ", 6))
+                       addrp = lbuf + 6;
+               else if (offset == 0)
+                       err(EX_DATAERR,
+                           "missing or empty From line: %s", lbuf);
+               else {
+                       *p = '\n';
+                       break;
+               }
+
+               if (*addrp == '\0')
+                       err(EX_DATAERR, "corrupted From line: %s", lbuf);
+
+               /* Use the "remote from" if it exists. */
+               for (p = addrp; (p = strchr(p + 1, 'r')) != NULL;)
+                       if (!strncmp(p, "remote from ", 12)) {
+                               for (t = p += 12; *t && !isspace(*t); ++t);
+                               *t = '\0';
+                               if (debug)
+                                       (void)fprintf(stderr,
+                                           "remote from: %s\n", p);
+                               break;
+                       }
+
+               /* Else use the string up to the last bang. */
+               if (p == NULL)
+                       if (*addrp == '!')
+                               err(EX_DATAERR,
+                                   "bang starts address: %s", addrp);
+                       else if ((t = strrchr(addrp, '!')) != NULL) {
+                               *t = '\0';
+                               p = addrp;
+                               addrp = t + 1;
+                               if (*addrp == '\0')
+                                       err(EX_DATAERR,
+                                           "corrupted From line: %s", lbuf);
+                               if (debug)
+                                       (void)fprintf(stderr, "bang: %s\n", p);
+                       }
+
+               /* 'p' now points to any system string from this line. */
+               if (p != NULL) {
+                       /* Nul terminate it as necessary. */
+                       for (t = p; *t && !isspace(*t); ++t);
+                       *t = '\0';
+
+                       /* If the first system, copy to the from_sys string. */
+                       if (from_sys == NULL) {
+                               if ((from_sys = strdup(p)) == NULL)
+                                       err(EX_TEMPFAIL, NULL);
+                               if (debug)
+                                       (void)fprintf(stderr,
+                                           "from_sys: %s\n", from_sys);
+                       }
+
+                       /* Concatenate to the path string. */
+                       len = t - p;
+                       if (from_path == NULL) {
+                               fplen = 0;
+                               if ((from_path = malloc(fptlen = 256)) == NULL)
+                                       err(EX_TEMPFAIL, NULL);
+                       }
+                       if (fplen + len + 2 > fptlen) {
+                               fptlen += MAX(fplen + len + 2, 256);
+                               if ((from_path =
+                                   realloc(from_path, fptlen)) == NULL)
+                                       err(EX_TEMPFAIL, NULL);
+                       }
+                       memmove(from_path + fplen, p, len);
+                       fplen += len;
+                       from_path[fplen++] = '!';
+                       from_path[fplen] = '\0';
+               }
+
+               /* Save off from user's address; the last one wins. */
+               for (p = addrp; *p && !isspace(*p); ++p);
+               *p = '\0';
+               if (from_user != NULL)
+                       free(from_user);
+               if ((from_user = strdup(addrp)) == NULL)
+                       err(EX_TEMPFAIL, NULL);
+
+               if (debug) {
+                       if (from_path != NULL)
+                               (void)fprintf(stderr,
+                                   "from_path: %s\n", from_path);
+                       (void)fprintf(stderr, "from_user: %s\n", from_user);
+               }
+
+               if (offset != -1)
+                       offset = (off_t)ftell(stdin);
+       }
+
+       i = 0;
+       args[i++] = _PATH_SENDMAIL;     /* Build sendmail's argument list. */
+       args[i++] = "-oee";             /* No errors, just status. */
+       args[i++] = "-odq";             /* Queue it, don't try to deliver. */
+       args[i++] = "-oi";              /* Ignore '.' on a line by itself. */
+
+       if (from_sys != NULL) {         /* Set sender's host name. */
+               if (strchr(from_sys, '.') == NULL)
+                       (void)snprintf(buf, sizeof(buf),
+                           "-oMs%s.%s", from_sys, domain);
+               else
+                       (void)snprintf(buf, sizeof(buf), "-oMs%s", from_sys);
+               if ((args[i++] = strdup(buf)) == NULL)
+                        err(EX_TEMPFAIL, NULL);
+       }
+                                       /* Set protocol used. */
+       (void)snprintf(buf, sizeof(buf), "-oMr%s", domain);
+       if ((args[i++] = strdup(buf)) == NULL)
+               err(EX_TEMPFAIL, NULL);
+
+                                       /* Set name of ``from'' person. */
+       (void)snprintf(buf, sizeof(buf), "-f%s%s",
+           from_path ? from_path : "", from_user);
+       if ((args[i++] = strdup(buf)) == NULL)
+               err(EX_TEMPFAIL, NULL);
+
+       /*
+        * Don't copy arguments beginning with - as they will be
+        * passed to sendmail and could be interpreted as flags.
+        */
+       do {
+               if (*argv && **argv == '-')
+                       err(EX_USAGE, "dash precedes argument: %s", *argv);
+       } while ((args[i++] = *argv++) != NULL);
+
+       if (debug) {
+               (void)fprintf(stderr, "Sendmail arguments:\n");
+               for (i = 0; args[i]; i++)
+                       (void)fprintf(stderr, "\t%s\n", args[i]);
+       }
+
+       /*
+        * If called with a regular file as standard input, seek to the right
+        * position in the file and just exec sendmail.  Could probably skip
+        * skip the stat, but it's not unreasonable to believe that a failed
+        * seek will cause future reads to fail.
+        */
+       if (!fstat(STDIN_FILENO, &sb) && S_ISREG(sb.st_mode)) {
+               if (lseek(STDIN_FILENO, offset, SEEK_SET) != offset)
+                       err(EX_TEMPFAIL, "stdin seek");
+               execv(_PATH_SENDMAIL, args);
+               err(EX_OSERR, "%s", _PATH_SENDMAIL);
+       }
+
+       if (pipe(pdes) < 0)
+               err(EX_OSERR, NULL);
+
+       switch (pid = vfork()) {
+       case -1:                                /* Err. */
+               err(EX_OSERR, NULL);
+       case 0:                                 /* Child. */
+               if (pdes[0] != STDIN_FILENO) {
+                       (void)dup2(pdes[0], STDIN_FILENO);
+                       (void)close(pdes[0]);
+               }
+               (void)close(pdes[1]);
+               execv(_PATH_SENDMAIL, args);
+               _exit(127);
+               /* NOTREACHED */
+       }
+
+       if ((fp = fdopen(pdes[1], "w")) == NULL)
+               err(EX_OSERR, NULL);
+       (void)close(pdes[0]);
+
+       /* Copy the file down the pipe. */
+       do {
+               (void)fprintf(fp, "%s", lbuf);
+       } while (fgets(lbuf, sizeof(lbuf), stdin) != NULL);
+
+       if (ferror(stdin))
+               err(EX_TEMPFAIL, "stdin: %s", strerror(errno));
+
+       if (fclose(fp))
+               err(EX_OSERR, NULL);
+
+       if ((waitpid(pid, &status, 0)) == -1)
+               err(EX_OSERR, "%s", _PATH_SENDMAIL);
+
+       if (!WIFEXITED(status))
+               err(EX_OSERR,
+                   "%s: did not terminate normally", _PATH_SENDMAIL);
+
+       if (WEXITSTATUS(status))
+               err(status, "%s: terminated with %d (non-zero) status",
+                   _PATH_SENDMAIL, WEXITSTATUS(status));
+       exit(EX_OK);
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr, "usage: rmail [-T] [-D domain] user ...\n");
+       exit(EX_USAGE);
+}
+
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#ifdef __STDC__
+err(int eval, const char *fmt, ...)
+#else
+err(eval, fmt, va_alist)
+       int eval;
+       const char *fmt;
+       va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)fprintf(stderr, "rmail: ");
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       (void)fprintf(stderr, "\n");
+       exit(eval);
+}
index 7ba330e..32e6ca6 100644 (file)
@@ -1,15 +1,26 @@
-#      @(#)Makefile    5.21 (Berkeley) 3/9/91
+#      @(#)Makefile    8.1 (Berkeley) 6/7/93
 
 PROG=  sendmail
 
 
 PROG=  sendmail
 
-CFLAGS+=-I${.CURDIR} -DVMUNIX -DUSE_DB
+# define the database format to use for aliases et al.  Can be -DNEWDB (for
+# the new BSD database package -- this is preferred) or -DNDBM for the NDBM
+# database package.  The old putrescent V7 DBM package is no longer
+# supported.
+# You can define both NEWDB and NDBM during a transition period; old
+# databases are read, but the new format will be used on any rebuilds.  On
+# really gnarly systems, you can set this to null; it will crawl like a high
+# spiral snail, but it will work.
+DBMDEF=        -DNEWDB -DNDBM
+
+CFLAGS+=-I${.CURDIR} ${DBMDEF} -DNETISO
 
 SRCS=  alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
 
 SRCS=  alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
-       deliver.c domain.c envelope.c err.c headers.c macro.c main.c \
-       parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
-       stab.c stats.c sysexits.c trace.c usersmtp.c util.c version.c
-DPADD= ${LIBUTIL}
-LDADD= -lutil
+       deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
+       mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
+       stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
+       util.c version.c
+DPADD= ${LIBDBM} ${LIBCOMPAT} ${LIBUTIL}
+LDADD= ${LIBUTIL}
 MAN1=  newaliases.0
 MAN5=  aliases.0
 MAN8=  sendmail.0 
 MAN1=  newaliases.0
 MAN5=  aliases.0
 MAN8=  sendmail.0 
@@ -21,8 +32,8 @@ BINGRP=       kmem
 BINMODE=6555
 
 beforeinstall:
 BINMODE=6555
 
 beforeinstall:
-       install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
-           ${DESTDIR}/etc/sendmail.fc
+#      install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+#          ${DESTDIR}/etc/sendmail.fc
        install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
            ${DESTDIR}/var/log/sendmail.st
        install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
        install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
            ${DESTDIR}/var/log/sendmail.st
        install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
diff --git a/usr.sbin/sendmail/src/Makefile.AIX b/usr.sbin/sendmail/src/Makefile.AIX
new file mode 100644 (file)
index 0000000..a883ebf
--- /dev/null
@@ -0,0 +1,99 @@
+#
+#  This Makefile is designed to work on the old "make" program.  It does
+#  not use the obj subdirectory.  It also does not install documentation
+#  automatically -- think of it as a quick start for sites that have the
+#  old make program (I recommend that you get and port the new make if you
+#  are going to be doing any signficant work on sendmail).
+#
+#  This has been tested on Ultrix.
+#
+#      @(#)Makefile.dist       6.5 (Berkeley) 2/26/93
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O=     -g
+
+# define the database mechanism used for alias lookups:
+#      -DNDBM -- use new DBM
+#      -DNEWDB -- use new Berkeley DB
+#      -DNDBM -DNEWDB -- use both new DBM and new Berkeley DB
+#      -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
+# The really old (V7) DBM library is no longer supported.
+# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
+#   both the NEWDB and DBM libraries (the DBM just for YP).
+#
+DBMDEF=        -DNDBM
+
+# define the load average calculation on your system: -DLA_TYPE=LA_INT,
+#   -DLA_TYPE=LA_FLOAT, -DLA_TYPE=LA_SUBR, or -DLA_TYPE=LA_ZERO
+# leave undefined to use internal guess
+#LADEF=        -DLA_TYPE=LA_SUBR
+
+# define UNSETENV if you need to compile in a local version of setenv
+ENVDEF=        -D_AIX3
+
+# see also conf.h for additional compilation flags
+
+# include directories
+#INCDIRS=-I/usr/sww/include/db
+
+# library directories
+#LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS=  -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR=        ${DESTDIR}/usr/sbin
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/share/misc
+
+###################  end of user configuration flags  ######################
+
+CFLAGS=        -I. $O ${INCDIRS} ${DBMDEF} ${LADEF} ${ENVDEF}
+
+OBJS=  alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+       deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+       map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+       savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+       trace.o udb.o usersmtp.o util.o version.o
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN=        root
+BINGRP=        kmem
+BINMODE=6555
+
+sendmail: ${OBJS}
+       ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+aliases.0: aliases.5
+       nroff -h -mandoc aliases.5 > aliases.0
+
+newaliases.0: newaliases.1
+       nroff -h -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+       nroff -h -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+       install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+       for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+       install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
+           ${STDIR}/sendmail.st
+       install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 newaliases.0 sendmail.0
+
+clean:
+       rm -f ${OBJS} sendmail aliases.0 newaliases.0 sendmail.0
+
+# dependencies
+#   gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.HPUX b/usr.sbin/sendmail/src/Makefile.HPUX
new file mode 100644 (file)
index 0000000..c99e969
--- /dev/null
@@ -0,0 +1,99 @@
+#
+#  This Makefile is designed to work on the old "make" program.  It does
+#  not use the obj subdirectory.  It also does not install documentation
+#  automatically -- think of it as a quick start for sites that have the
+#  old make program (I recommend that you get and port the new make if you
+#  are going to be doing any signficant work on sendmail).
+#
+#  This has been tested on Ultrix.
+#
+#      @(#)Makefile.dist       6.5 (Berkeley) 2/26/93
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O=     
+
+# define the database mechanism used for alias lookups:
+#      -DNDBM -- use new DBM
+#      -DNEWDB -- use new Berkeley DB
+#      -DNDBM -DNEWDB -- use both new DBM and new Berkeley DB
+#      -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
+# The really old (V7) DBM library is no longer supported.
+# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
+#   both the NEWDB and DBM libraries (the DBM just for YP).
+#
+DBMDEF=        -DNDBM -DNEWDB
+
+# define the load average calculation on your system: -DLA_TYPE=LA_INT,
+#   -DLA_TYPE=LA_FLOAT, -DLA_TYPE=LA_SUBR, or -DLA_TYPE=LA_ZERO
+# leave undefined to use internal guess
+#LADEF=        -DLA_TYPE=LA_SUBR
+
+# define UNSETENV if you need to compile in a local version of setenv
+#ENVDEF=       -DUNSETENV
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS=  -ldb -ldbm
+
+# 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}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/lib
+
+###################  end of user configuration flags  ######################
+
+CFLAGS=        -I. $O ${INCDIRS} ${DBMDEF} ${LADEF} ${ENVDEF}
+
+OBJS=  alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+       deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+       map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+       savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+       trace.o udb.o usersmtp.o util.o version.o
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN=        root
+BINGRP=        kmem
+BINMODE=6555
+
+sendmail: ${OBJS}
+       ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+aliases.0: aliases.5
+       nroff -h -mandoc aliases.5 > aliases.0
+
+newaliases.0: newaliases.1
+       nroff -h -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+       nroff -h -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+       install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+       for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+       install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
+           ${STDIR}/sendmail.st
+       install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 newaliases.0 sendmail.0
+
+clean:
+       rm -f ${OBJS} sendmail aliases.0 newaliases.0 sendmail.0
+
+# dependencies
+#   gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.OSF1 b/usr.sbin/sendmail/src/Makefile.OSF1
new file mode 100644 (file)
index 0000000..dc5a425
--- /dev/null
@@ -0,0 +1,99 @@
+#
+#  This Makefile is designed to work on the old "make" program.  It does
+#  not use the obj subdirectory.  It also does not install documentation
+#  automatically -- think of it as a quick start for sites that have the
+#  old make program (I recommend that you get and port the new make if you
+#  are going to be doing any signficant work on sendmail).
+#
+#  This has been tested on Ultrix.
+#
+#      @(#)Makefile.dist       6.5 (Berkeley) 2/26/93
+#
+
+# use O=-O (usual) or O=-g (debugging)
+O=     -O
+
+# define the database mechanism used for alias lookups:
+#      -DNDBM -- use new DBM
+#      -DNEWDB -- use new Berkeley DB
+#      -DNDBM -DNEWDB -- use both new DBM and new Berkeley DB
+#      -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
+# The really old (V7) DBM library is no longer supported.
+# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
+#   both the NEWDB and DBM libraries (the DBM just for YP).
+#
+DBMDEF=        -DNDBM
+
+# define the load average calculation on your system: -DLA_TYPE=LA_INT,
+#   -DLA_TYPE=LA_FLOAT, -DLA_TYPE=LA_SUBR, or -DLA_TYPE=LA_ZERO
+# leave undefined to use internal guess
+#LADEF=        -DLA_TYPE=LA_SUBR
+
+# define UNSETENV if you need to compile in a local version of setenv
+#ENVDEF=       -DUNSETENV
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS=  -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR=        ${DESTDIR}/usr/sbin
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/share/misc
+
+###################  end of user configuration flags  ######################
+
+CFLAGS=        -I. $O ${INCDIRS} ${DBMDEF} ${LADEF} ${ENVDEF}
+
+OBJS=  alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+       deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+       map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+       savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+       trace.o udb.o usersmtp.o util.o version.o
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN=        root
+BINGRP=        kmem
+BINMODE=6555
+
+sendmail: ${OBJS}
+       ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+aliases.0: aliases.5
+       nroff -h -mandoc aliases.5 > aliases.0
+
+newaliases.0: newaliases.1
+       nroff -h -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+       nroff -h -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+       install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+       for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+       install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
+           ${STDIR}/sendmail.st
+       install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 newaliases.0 sendmail.0
+
+clean:
+       rm -f ${OBJS} sendmail aliases.0 newaliases.0 sendmail.0
+
+# dependencies
+#   gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.SunOS b/usr.sbin/sendmail/src/Makefile.SunOS
new file mode 100644 (file)
index 0000000..b7be76d
--- /dev/null
@@ -0,0 +1,36 @@
+#      @(#)Makefile    5.22 (Berkeley) 7/26/91
+
+PROG=  sendmail
+
+DBMDEF=        -DNEWDB -DNDBM -DNIS
+INCLS= -I/usr/local/include -I/usr/sww/include/db
+CFLAGS+=-I${.CURDIR} ${INCLS} ${DBMDEF} ${OPTNS}
+
+SRCS=  alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
+       deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
+       mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
+       stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
+       util.c version.c
+DPADD= ${LIBDBM} ${LIBCOMPAT} ${LIBUTIL}
+LDADD= -L/usr/sww/lib -ldb -ldbm -lresolv -Bstatic
+#LDADD=        /usr/sww/build/lib/db/libdb.a -ldbm
+#MAN1= newaliases.0
+#MAN5= aliases.0
+#MAN8= sendmail.0 
+NOMAN=
+LINKS= ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/newaliases \
+       ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/mailq
+BINDIR=        /usr/sbin
+BINOWN=        root
+BINGRP=        kmem
+BINMODE=6555
+
+beforeinstall:
+       install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+           ${DESTDIR}/etc/sendmail.fc
+       install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
+           ${DESTDIR}/var/log/sendmail.st
+       install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
+           ${DESTDIR}/usr/share/misc
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/src/Makefile.ULTRIX b/usr.sbin/sendmail/src/Makefile.ULTRIX
new file mode 100644 (file)
index 0000000..ccacfe5
--- /dev/null
@@ -0,0 +1,34 @@
+#      @(#)Makefile    5.22 (Berkeley) 7/26/91
+
+PROG=  sendmail
+
+CFLAGS+=-I${.CURDIR} -I/usr/local/include -I/usr/sww/include/db -DNEWDB -DNDBM
+
+SRCS=  alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
+       deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
+       mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
+       stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
+       util.c version.c unsetenv.c
+DPADD= ${LIBDBM} ${LIBCOMPAT} ${LIBUTIL}
+LDADD= -L/usr/sww/lib -ldb
+#LDADD=        /usr/sww/build/lib/db/libdb.a -ldbm
+#MAN1= newaliases.0
+#MAN5= aliases.0
+#MAN8= sendmail.0 
+NOMAN=
+LINKS= ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/newaliases \
+       ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/mailq
+BINDIR=        /usr/sbin
+BINOWN=        root
+BINGRP=        kmem
+BINMODE=6555
+
+beforeinstall:
+       install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
+           ${DESTDIR}/etc/sendmail.fc
+       install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
+           ${DESTDIR}/var/log/sendmail.st
+       install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
+           ${DESTDIR}/usr/share/misc
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/src/Makefile.dist b/usr.sbin/sendmail/src/Makefile.dist
new file mode 100644 (file)
index 0000000..2e5d022
--- /dev/null
@@ -0,0 +1,99 @@
+#
+#  This Makefile is designed to work on the old "make" program.  It does
+#  not use the obj subdirectory.  It also does not install documentation
+#  automatically -- think of it as a quick start for sites that have the
+#  old make program (I recommend that you get and port the new make if you
+#  are going to be doing any signficant work on sendmail).
+#
+#  This has been tested on Ultrix.
+#
+#      @(#)Makefile.dist       8.1 (Berkeley) 6/7/93
+#
+
+# 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.
+# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
+#   both the NEWDB and DBM libraries (the DBM just for YP).
+#
+DBMDEF=        -DNDBM -DNEWDB
+
+# define the load average calculation on your system: -DLA_TYPE=LA_INT,
+#   -DLA_TYPE=LA_FLOAT, -DLA_TYPE=LA_SUBR, or -DLA_TYPE=LA_ZERO
+# leave undefined to use internal guess
+#LADEF=        -DLA_TYPE=LA_SUBR
+
+# define UNSETENV if you need to compile in a local version of setenv
+#ENVDEF=       -DUNSETENV
+
+# see also conf.h for additional compilation flags
+
+# include directories
+INCDIRS=-I/usr/sww/include/db
+
+# library directories
+LIBDIRS=-L/usr/sww/lib
+
+# libraries required on your system
+LIBS=  -ldb -ldbm
+
+# location of sendmail binary (usually /usr/sbin or /usr/lib)
+BINDIR=        ${DESTDIR}/usr/sbin
+
+# location of sendmail.st file (usually /var/log or /usr/lib)
+STDIR= ${DESTDIR}/var/log
+
+# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
+HFDIR= ${DESTDIR}/usr/share/misc
+
+###################  end of user configuration flags  ######################
+
+CFLAGS=        -I. $O ${INCDIRS} ${DBMDEF} ${LADEF} ${ENVDEF}
+
+OBJS=  alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
+       deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
+       map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
+       savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
+       trace.o udb.o usersmtp.o util.o version.o
+
+LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
+BINOWN=        root
+BINGRP=        kmem
+BINMODE=6555
+
+sendmail: ${OBJS}
+       ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+
+aliases.0: aliases.5
+       nroff -h -mandoc aliases.5 > aliases.0
+
+newaliases.0: newaliases.1
+       nroff -h -mandoc newaliases.1 > newaliases.0
+
+sendmail.0: sendmail.8
+       nroff -h -mandoc sendmail.8 > sendmail.0
+
+install: install-sendmail install-docs
+
+install-sendmail: sendmail
+       install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+       for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+       install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
+           ${STDIR}/sendmail.st
+       install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+
+# doesn't actually install them -- you may want to install pre-nroff versions
+install-docs: aliases.0 newaliases.0 sendmail.0
+
+clean:
+       rm -f ${OBJS} sendmail aliases.0 newaliases.0 sendmail.0
+
+# dependencies
+#   gross overkill, and yet still not quite enough....
+${OBJS}: sendmail.h conf.h
index 5384273..74426e8 100644 (file)
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-#      @(#)READ_ME     4.6 (Berkeley) 4/23/91
+#      @(#)READ_ME     8.1 (Berkeley) 6/7/93
 #
 
 This directory contains the source files for sendmail.
 
 #
 
 This directory contains the source files for sendmail.
 
-For installation instructions, please read the document ../doc/op.me:
+For detailed instructions, please read the document ../doc/op.me:
 
 
-       nroff -me ../doc/op.me
+       eqn ../doc/op.me | pic | ditroff -me
+
+The Makefile is for the new Berkeley make, available from ftp.uu.net
+in the directory /systems/unix/bsd-sources/usr.bin/make.  There is
+also a Makefile.dist which is much less clever, but works on the old
+traditional make.  You can use this using:
+
+       make -f Makefile.dist
+
+There are a couple of other Makefiles for other systems -- these are
+the ones that I use, they have "Berkeley quirks" in them, and I don't
+guarantee that they will work in your environment.  To make it worse,
+some are for the new Berkeley make, and some are for the old make.
+I provide them for information only.  Still, they may help you get
+started.  They have names like "Makefile.HPUX".
+
+Whereever possible, I try to make sendmail pull in the correct
+compilation options needed to compile on various environments based on
+automatically defined symbols.  Some machines don't seem to have useful
+symbols availble, requiring the following compilation flags in the
+Makefile:
+
+SOLARIS                Define this if you are running Solaris 2.0 or higher.
+NeXT           Define this if you are on a NeXT box.
+_AIX3          Define this if you are IBM AIX 3.x.
+
+If you are a system that sendmail has already been ported to, you
+probably won't have to touch these.  But if you are porting, you may
+have to tweak the following compilation flags in order to get
+it to compile and link properly:
+
+UNSETENV       Define this if your system library does NOT include the
+               "unsetenv" subroutine.
+SYSTEM5                Adjust for System V.
+LOCKF          Set this if you do not have the flock system call -- it
+               will revert to System V file locking.  There are some
+               semantic gotchas, so flock is preferred.  Implied by
+               SYSTEM5.
+SYS5TZ         Use System V-style time zones.  If not set, the TZ
+               environment variable is ignored.  Implied by SYSTEM5.
+HASUNAME       Set if you have the "uname" system call.  Implied by
+               SYSTEM5.
+HASSTATFS      Define this if you have the statfs(2) system call.  It's
+               not a disaster to get this wrong -- but you do lose the
+               queue free space code.
+HASUSTAT       Define this if you have the ustat(2) system call.  It's
+               not a disaster to get this wrong -- but you do lose the
+               queue free space code.
+HASSETSID      Define this if you have the setsid(2) system call.  This
+               is implied if your system appears to be POSIX compliant.
+HASINITGROUPS  Define this if you have the initgroups(3) routine.
+LA_TYPE                The type of load average your kernel supports.  These
+               can be LA_SUBR (4) if you have the getloadavg(3) routine,
+               LA_FLOAT (3) if you read kmem and interpret the value
+               as a floating point number, LA_INT (2) to interpret as
+               an integer.  These last two have several other parameters
+               that they try to divine: the name of your kernel, the name
+               of the variable in the kernel to examine, the number of
+               bits of precision in a fixed point load average, and so
+               forth.  In desparation, use LA_ZERO -- it always returns
+               the load average as "zero" (and does so on all architectures).
+               The actual code is in conf.c -- it can be tweaked if you
+               are brave.
+
+There are a bunch of features that you can decide to compile in, such
+as selecting various database packages and special protocol support.
+Several are assumed based on other compilation flags -- if you want to
+"un-assume" something, you probably need to edit conf.h.  Compilation
+flags that add support for special features include:
+
+NDBM           Include support for "new" DBM library for aliases and maps.
+NEWDB          Include support for Berkeley "db" package (hash & btree)
+               for aliases and maps.
+NIS            Define this to get NIS (YP) support for aliases and maps.
+YPCOMPAT       Define this to force building of DBM versions of alias
+               files even if you have NEWDB defined; this will only
+               occur on NIS master machines.  It is independent of NIS.
+USERDB         Include support for the User Information Database.  Implied
+               by NEWDB conf.h.
+IDENTPROTO     Define this to get IDENT (RFC 1413) protocol support.
+               This is assumed unless you are running on Ultrix or
+               HP-UX, both of which have a problem in the UDP
+               implementation.
+MIME           Include support for MIME-encapsulated error messages.
+FROZENCONFIG   Define this to get support for frozen configuration
+               files.  Frozen configurations make sense if your I/O system
+               is fast relative to your processor.  At this point this
+               is NOT recommended.
+LOG            Set this to get syslog(3) support.  Defined by default
+               in conf.h.  You want this if at all possible.
+NETINET                Set this to get TCP/IP support.  Defined by default
+               in conf.h.  You probably want this.
+NETISO         Define this to get ISO networking support.
+SMTP           Define this to get the SMTP code.  Implied by NETINET
+               or NETISO.
+NAMED_BIND     Define this to get DNS (name daemon) support, including
+               MX support.  The specs you must use this if you run
+               SMTP.  Defined by default in conf.h.
+QUEUE          Define this to get queueing code.  Implied by NETINET
+               or NETISO; required by SMTP.  This gives you other good
+               stuff -- it should be on.
+DAEMON         Define this to get general network support.  Implied by
+               NETINET or NETISO.  Defined by default in conf.h.  You
+               almost certainly want it on.
+MATCHGECOS     Permit fuzzy matching of user names against the full
+               name (GECOS) field in the /etc/passwd file.  This should
+               probably be on, since you can disable it from the config
+               file if you want to.  Defined by default in conf.h.
+SETPROCTITLE   Try to set the string printed by "ps" to something
+               informative about what sendmail is doing.  Defined by
+               default in conf.h.
+
+If you are compiling on SunOS and want to use frozen configuration
+files, you must use -Bstatic -- if you do not, frozen configuration
+files fail in bizarre ways and you will open up several security holes.
+
+If you are compiling on OSF/1 (DEC Alpha), you must use -lmld.
+
+If you use both -DNDBM and -DNEWDB, you must delete the module ndbm.o
+from libdb.a and delete the file "ndbm.h" from the files that get
+installed (that is, use the OLD ndbm.h, not the new ndbm.h).  This
+compatibility module maps ndbm calls into DB calls, and breaks things
+rather badly.
+
+You probably want to look over the compilation options in conf.h
+before you compile.  These are intended to be per-site information.
 
 The following list describes the files in this directory:
 
 
 The following list describes the files in this directory:
 
-Makefile       The makefile used here; this is created from
-               makefile.m4.
-Makefile.m4    A makefile template.
+Makefile       The makefile used here; this version only works with
+               the new Berkeley make.
+Makefile.dist  A trimmed down version of the makefile that works with
+               the old make.
 READ_ME                This file.
 READ_ME                This file.
-TODO           New features to be put in (maybe) at some time.
-Version.c      The version number and information about this
-               version of sendmail.  Theoretically, this gets
-               modified on every change.
+TRACEFLAGS     My own personal list of the trace flags -- not guaranteed
+               to be particularly up to date.
 alias.c                Does name aliasing in all forms.
 arpadate.c     A subroutine which creates ARPANET standard dates.
 clock.c                Routines to implement real-time oriented functions
 alias.c                Does name aliasing in all forms.
 arpadate.c     A subroutine which creates ARPANET standard dates.
 clock.c                Routines to implement real-time oriented functions
@@ -65,6 +189,8 @@ convtime.c   A routine to sanely process times.
 daemon.c       Routines to implement daemon mode.  This version is
                specifically for Berkeley 4.1 IPC.
 deliver.c      Routines to deliver mail.
 daemon.c       Routines to implement daemon mode.  This version is
                specifically for Berkeley 4.1 IPC.
 deliver.c      Routines to deliver mail.
+domain.c       Routines that interface with DNS (the Domain Name
+               System).
 err.c          Routines to print error messages.
 envelope.c     Routines to manipulate the envelope structure.
 headers.c      Routines to process message headers.
 err.c          Routines to print error messages.
 envelope.c     Routines to manipulate the envelope structure.
 headers.c      Routines to process message headers.
@@ -72,6 +198,8 @@ macro.c              The macro expander.  This is used internally to
                insert information from the configuration file.
 main.c         The main routine to sendmail.  This file also
                contains some miscellaneous routines.
                insert information from the configuration file.
 main.c         The main routine to sendmail.  This file also
                contains some miscellaneous routines.
+map.c          Support for database maps.
+mci.c          Routines that handle mail connection information caching.
 parseaddr.c    The routines which do address parsing.
 queue.c                Routines to implement message queueing.
 readcf.c       The routine that reads the configuration file and
 parseaddr.c    The routines which do address parsing.
 queue.c                Routines to implement message queueing.
 readcf.c       The routine that reads the configuration file and
@@ -86,12 +214,13 @@ sysexits.c List of error messages associated with error codes
                in sysexits.h.
 trace.c                The trace package.  These routines allow setting and
                testing of trace flags with a high granularity.
                in sysexits.h.
 trace.c                The trace package.  These routines allow setting and
                testing of trace flags with a high granularity.
-trace.h                Definitions needed for the trace package.
+udb.c          The user database interface module.
 usersmtp.c     Routines to implement user SMTP.
 util.c         Some general purpose routines used by sendmail.
 usersmtp.c     Routines to implement user SMTP.
 util.c         Some general purpose routines used by sendmail.
-version.c      A master file for Version.c -- it may not exist in
-               your distribution.
+version.c      The version number and information about this
+               version of sendmail.  Theoretically, this gets
+               modified on every change.
 
 Eric Allman
 
 
 Eric Allman
 
-(Version 4.6, last update 4/23/91 19:52:27)
+(Version 8.1, last update 6/7/93 10:26:59)
diff --git a/usr.sbin/sendmail/src/TRACEFLAGS b/usr.sbin/sendmail/src/TRACEFLAGS
new file mode 100644 (file)
index 0000000..e6514ac
--- /dev/null
@@ -0,0 +1,60 @@
+0, 1   main.c          main    skip background fork
+0, 4   main.c          main    canonical name, UUCP node name, a.k.a.s
+0, 15  main.c          main    print configuration
+0, 44  util.c          printav print address of each string
+1      main.c          main    print from person
+2      main.c          finis
+3      conf.c          getla
+4      conf.c          enoughspace
+5      clock.c         setevent, clrevent, tick
+6      savemail.c      savemail, returntosender
+7      queue.c         queuename
+8      domain.c        getmxrr, getcanonname
+9      daemon.c        getauthinfo     IDENT protocol
+9      daemon.c        maphostname
+10     deliver.c       deliver
+11     deliver.c       openmailer, mailfile
+12     parseaddr.c     remotename
+13     deliver.c       sendall, sendenvelope
+14     headers.c       commaize
+15     daemon.c        getrequests
+16     daemon.c        makeconnection
+17     deliver.c       hostsignature
+17     domain.c        mxrand
+17     usersmtp.c      smtpinit, smtpmailfrom
+18     usersmtp.c      reply, smtpmessage
+19     srvrsmtp.c      smtp
+20     parseaddr.c     parseaddr
+21     parseaddr.c     rewrite
+22     parseaddr.c     prescan
+24     parseaddr.c     buildaddr, allocaddr
+25     recipient.c     sendtolist
+26     recipient.c     recipient
+27     alias.c         alias
+27     alias.c         readaliases
+27     alias.c         forward
+27     recipient.c     include
+28     udb.c           udbexpand, udbsender
+29     parseaddr.c     maplocaluser
+29     recipient.c     recipient (local users), finduser
+30     collect.c       collect
+30     collect.c       eatfrom
+31     headers.c       chompheader
+32     headers.c       eatheader
+33     headers.c       crackaddr
+34     headers.c       putheader
+35     macro.c         expand, define
+36     stab.c          stab
+37     readcf.c        (many)
+38     map.c           initmaps
+39     map.c           map_rewrite
+40     queue.c         queueup, orderq, dowork
+41     queue.c         orderq
+42     mci.c           mci_get
+45     envelope.c      setsender
+50     envelope.c      dropenvelope
+51     queue.c         unlockqueue
+52     main.c          disconnect
+53     util.c          xfclose
+59     Extended Load Average implementation from Christophe Wolfhugel
+60     map.c
index 172ba74..f71335e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * SUCH DAMAGE.
  */
 
  * SUCH DAMAGE.
  */
 
+# include "sendmail.h"
+# include <signal.h>
+# include <pwd.h>
+
 #ifndef lint
 #ifndef lint
-#ifdef DBM
-static char sccsid[] = "@(#)alias.c    5.22 (Berkeley) 3/2/91 (with DBM)";
-#else
-#ifdef USE_DB
-static char sccsid[] = "@(#)alias.c    5.22 (Berkeley) 3/2/91 (with DB)";
-#else
-static char sccsid[] = "@(#)alias.c    5.22 (Berkeley) 3/2/91 (without DBM)";
-#endif
-#endif
+static char sccsid[] = "@(#)alias.c    8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #endif /* not lint */
 
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <signal.h>
-# include <errno.h>
-# include "sendmail.h"
-# include <sys/file.h>
-# include <pwd.h>
 
 
-/*
+MAP    *AliasDB[MAXALIASDB + 1];       /* actual database list */
+int    NAliasDBs;                      /* number of alias databases */
+\f/*
 **  ALIAS -- Compute aliases.
 **
 **     Scans the alias file for an alias for the given address.
 **  ALIAS -- Compute aliases.
 **
 **     Scans the alias file for an alias for the given address.
@@ -63,6 +54,7 @@ static char sccsid[] = "@(#)alias.c   5.22 (Berkeley) 3/2/91 (without DBM)";
 **             a -- address to alias.
 **             sendq -- a pointer to the head of the send queue
 **                     to put the aliases in.
 **             a -- address to alias.
 **             sendq -- a pointer to the head of the send queue
 **                     to put the aliases in.
+**             e -- the current envelope.
 **
 **     Returns:
 **             none
 **
 **     Returns:
 **             none
@@ -70,56 +62,39 @@ static char sccsid[] = "@(#)alias.c 5.22 (Berkeley) 3/2/91 (without DBM)";
 **     Side Effects:
 **             Aliases found are expanded.
 **
 **     Side Effects:
 **             Aliases found are expanded.
 **
-**     Notes:
-**             If NoAlias (the "-n" flag) is set, no aliasing is
-**                     done.
-**
 **     Deficiencies:
 **             It should complain about names that are aliased to
 **                     nothing.
 */
 
 **     Deficiencies:
 **             It should complain about names that are aliased to
 **                     nothing.
 */
 
-
-#ifdef DBM
-typedef struct
-{
-       char    *dptr;
-       int     dsize;
-} DATUM;
-extern DATUM fetch();
-#endif DBM
-# ifdef USE_DB
-# include <db.h>
-/*
-** DB is a database structure containing pointers to access methods.
-*/
-static DB *aliasdb;
-# endif USE_DB
-
-alias(a, sendq)
+alias(a, sendq, e)
        register ADDRESS *a;
        ADDRESS **sendq;
        register ADDRESS *a;
        ADDRESS **sendq;
+       register ENVELOPE *e;
 {
        register char *p;
 {
        register char *p;
+       int naliases;
+       char *owner;
+       char obuf[MAXNAME + 6];
        extern char *aliaslookup();
 
        if (tTd(27, 1))
                printf("alias(%s)\n", a->q_paddr);
 
        /* don't realias already aliased names */
        extern char *aliaslookup();
 
        if (tTd(27, 1))
                printf("alias(%s)\n", a->q_paddr);
 
        /* don't realias already aliased names */
-       if (bitset(QDONTSEND, a->q_flags))
+       if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))
                return;
 
                return;
 
-       CurEnv->e_to = a->q_paddr;
+       if (NoAlias)
+               return;
+
+       e->e_to = a->q_paddr;
 
        /*
        **  Look up this name
        */
 
 
        /*
        **  Look up this name
        */
 
-       if (NoAlias)
-               p = NULL;
-       else
-               p = aliaslookup(a->q_user);
+       p = aliaslookup(a->q_user, e);
        if (p == NULL)
                return;
 
        if (p == NULL)
                return;
 
@@ -131,10 +106,49 @@ alias(a, sendq)
        if (tTd(27, 1))
                printf("%s (%s, %s) aliased to %s\n",
                    a->q_paddr, a->q_host, a->q_user, p);
        if (tTd(27, 1))
                printf("%s (%s, %s) aliased to %s\n",
                    a->q_paddr, a->q_host, a->q_user, p);
-       message(Arpa_Info, "aliased to %s", p);
+       if (bitset(EF_VRFYONLY, e->e_flags))
+       {
+               a->q_flags |= QVERIFIED;
+               e->e_nrcpts++;
+               return;
+       }
+       message("aliased to %s", p);
+#ifdef LOG
+       if (LogLevel > 9)
+               syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p);
+#endif
+       a->q_flags &= ~QSELFREF;
        AliasLevel++;
        AliasLevel++;
-       sendtolist(p, a, sendq);
+       naliases = sendtolist(p, a, sendq, e);
        AliasLevel--;
        AliasLevel--;
+       if (naliases > 0 && !bitset(QSELFREF, a->q_flags))
+       {
+               if (tTd(27, 5))
+               {
+                       printf("alias: QDONTSEND ");
+                       printaddr(a, FALSE);
+               }
+               a->q_flags |= QDONTSEND;
+       }
+
+       /*
+       **  Look for owner of alias
+       */
+
+       (void) strcpy(obuf, "owner-");
+       if (strncmp(a->q_user, "owner-", 6) == 0)
+               (void) strcat(obuf, "owner");
+       else
+               (void) strcat(obuf, a->q_user);
+       if (!bitnset(M_USR_UPPER, a->q_mailer->m_flags))
+               makelower(obuf);
+       owner = aliaslookup(obuf, e);
+       if (owner != NULL)
+       {
+               if (strchr(owner, ',') != NULL)
+                       owner = obuf;
+               a->q_owner = newstr(owner);
+       }
 }
 \f/*
 **  ALIASLOOKUP -- look up a name in the alias file.
 }
 \f/*
 **  ALIASLOOKUP -- look up a name in the alias file.
@@ -154,319 +168,314 @@ alias(a, sendq)
 */
 
 char *
 */
 
 char *
-aliaslookup(name)
+aliaslookup(name, e)
        char *name;
        char *name;
+       ENVELOPE *e;
 {
 {
-# ifdef DBM
-       DATUM rhs, lhs;
-
-       /* create a key for fetch */
-       lhs.dptr = name;
-       lhs.dsize = strlen(name) + 1;
-       rhs = fetch(lhs);
-       return (rhs.dptr);
-# else DBM
-# ifdef USE_DB
-       DBT rhs, lhs;
-
-       /* create a key for fetch */
-       lhs.data = name;
-       lhs.size = strlen(name) + 1;
-       aliasdb->get(aliasdb, &lhs, &rhs, 0);
-       return (rhs.data);
-# else USE_DB
-       register STAB *s;
-
-       s = stab(name, ST_ALIAS, ST_FIND);
-       if (s == NULL)
-               return (NULL);
-       return (s->s_alias);
-# endif USE_DB
-# endif DBM
+       register int dbno;
+       register MAP *map;
+       register char *p;
+
+       for (dbno = 0; dbno < NAliasDBs; dbno++)
+       {
+               auto int stat;
+
+               map = AliasDB[dbno];
+               if (!bitset(MF_OPEN, map->map_mflags))
+                       continue;
+               p = (*map->map_class->map_lookup)(map, name, NULL, &stat);
+               if (p != NULL)
+                       return p;
+       }
+       return NULL;
 }
 \f/*
 }
 \f/*
-**  INITALIASES -- initialize for aliasing
+**  SETALIAS -- set up an alias map
 **
 **
-**     Very different depending on whether we are running DBM or not.
+**     Called when reading configuration file.
 **
 **     Parameters:
 **
 **     Parameters:
-**             aliasfile -- location of aliases.
-**             init -- if set and if DBM, initialize the DBM files.
+**             spec -- the alias specification
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
-**
-**     Side Effects:
-**             initializes aliases:
-**             if DBM:  opens the database.
-**             if ~DBM: reads the aliases into the symbol table.
 */
 
 */
 
-# define DBMMODE       0644
-# define DBEXTENSION   ".db"   /* extension for the database filename */
-
-initaliases(aliasfile, init)
-       char *aliasfile;
-       bool init;
+setalias(spec)
+       char *spec;
 {
 {
-#if defined (DBM) || defined (USE_DB)
-       int atcnt;
-       time_t modtime;
-       bool automatic = FALSE;
-       char buf[MAXNAME];
-#endif
-       struct stat stb;
-       static bool initialized = FALSE;
-       static int readaliases();
+       register char *p;
+       register MAP *map;
+       char *class;
+       STAB *s;
 
 
-       if (initialized)
-               return;
-       initialized = TRUE;
+       if (tTd(27, 8))
+               printf("setalias(%s)\n", spec);
 
 
-       if (aliasfile == NULL || stat(aliasfile, &stb) < 0)
+       for (p = spec; p != NULL; )
        {
        {
-               if (aliasfile != NULL && init)
-                       syserr("Cannot open %s", aliasfile);
-               NoAlias = TRUE;
-               errno = 0;
-               return;
+               char aname[50];
+
+               while (isspace(*p))
+                       p++;
+               if (*p == '\0')
+                       break;
+               spec = p;
+
+               if (NAliasDBs >= MAXALIASDB)
+               {
+                       syserr("Too many alias databases defined, %d max", MAXALIASDB);
+                       return;
+               }
+               (void) sprintf(aname, "Alias%d", NAliasDBs);
+               s = stab(aname, ST_MAP, ST_ENTER);
+               map = &s->s_map;
+               AliasDB[NAliasDBs] = map;
+               bzero(map, sizeof *map);
+
+               p = strpbrk(p, " ,/:");
+               if (p != NULL && *p == ':')
+               {
+                       /* map name */
+                       *p++ = '\0';
+                       class = spec;
+                       spec = p;
+               }
+               else
+               {
+                       class = "implicit";
+                       map->map_mflags = MF_OPTIONAL|MF_INCLNULL;
+               }
+
+               /* find end of spec */
+               if (p != NULL)
+                       p = strchr(p, ',');
+               if (p != NULL)
+                       *p++ = '\0';
+
+               /* look up class */
+               s = stab(class, ST_MAPCLASS, ST_FIND);
+               if (s == NULL)
+               {
+                       if (tTd(27, 1))
+                               printf("Unknown alias class %s\n", class);
+               }
+               else if (!bitset(MCF_ALIASOK, s->s_mapclass.map_cflags))
+               {
+                       syserr("setalias: map class %s can't handle aliases",
+                               class);
+               }
+               else
+               {
+                       map->map_class = &s->s_mapclass;
+                       if (map->map_class->map_parse(map, spec))
+                       {
+                               map->map_mflags |= MF_VALID|MF_ALIAS;
+                               NAliasDBs++;
+                       }
+               }
        }
        }
+}
+\f/*
+**  ALIASWAIT -- wait for distinguished @:@ token to appear.
+**
+**     This can decide to reopen or rebuild the alias file
+*/
 
 
-#if defined (DBM) || defined (USE_DB)
-       /*
-       **  Check to see that the alias file is complete.
-       **      If not, we will assume that someone died, and it is up
-       **      to us to rebuild it.
-       */
+aliaswait(map, ext)
+       MAP *map;
+       char *ext;
+{
+       int atcnt;
+       time_t mtime;
+       struct stat stb;
+       char buf[MAXNAME];
+
+       if (tTd(27, 3))
+               printf("aliaswait(%s:%s)\n",
+                       map->map_class->map_cname, map->map_file);
 
 
-       if (!init)
-# ifdef DBM
-               dbminit(aliasfile);
-# endif
-# ifdef USE_DB
-         {
-           (void) strcpy(buf, aliasfile);
-           (void) strcat(buf, DBEXTENSION);
-           if (aliasdb) aliasdb->close (aliasdb);
-           aliasdb = dbopen(buf, O_RDWR, DBMMODE, DB_BTREE, 0);
-           if (aliasdb == NULL)
-             {
-               syserr("Cannot open database %s", buf);
-               NoAlias = TRUE;
-               return;
-             }
-         }
-# endif USE_DB
        atcnt = SafeAlias * 2;
        if (atcnt > 0)
        {
        atcnt = SafeAlias * 2;
        if (atcnt > 0)
        {
-               while (!init && atcnt-- >= 0 && aliaslookup("@") == NULL)
+               auto int st;
+
+               while (atcnt-- >= 0 &&
+                      map->map_class->map_lookup(map, "@", NULL, &st) == NULL)
                {
                        /*
                {
                        /*
-                       **  Reinitialize alias file in case the new
-                       **  one is mv'ed in instead of cp'ed in.
-                       **
-                       **      Only works with new DBM -- old one will
-                       **      just consume file descriptors forever.
-                       **      If you have a dbmclose() it can be
-                       **      added before the sleep(30).
+                       **  Close and re-open the alias database in case
+                       **  the one is mv'ed instead of cp'ed in.
                        */
 
                        */
 
-# ifdef USE_DB
-                       if(aliasdb)
-                               aliasdb->close (aliasdb); 
-# endif USE_DB
+                       if (tTd(27, 2))
+                               printf("aliaswait: sleeping\n");
+
+                       map->map_class->map_close(map);
                        sleep(30);
                        sleep(30);
-# ifdef NDBM
-                       dbminit(aliasfile);
-# endif NDBM
-# ifdef USE_DB
-                       aliasdb = dbopen(buf, O_RDWR, DBMMODE, DB_BTREE, 0);
-                       if (aliasdb == NULL)
-                         {
-                           syserr("Cannot open database %s", buf);
-                           NoAlias = TRUE;
-                           return;
-                         }
-# endif USE_DB
+                       map->map_class->map_open(map, O_RDONLY);
                }
        }
                }
        }
-       else
-               atcnt = 1;
 
 
-       /*
-       **  See if the DBM version of the file is out of date with
-       **  the text version.  If so, go into 'init' mode automatically.
-       **      This only happens if our effective userid owns the DBM.
-       **      Note the unpalatable hack to see if the stat succeeded.
-       */
-
-       modtime = stb.st_mtime;
-       (void) strcpy(buf, aliasfile);
-# ifdef DBM
-       (void) strcat(buf, ".pag");
-# endif DBM
-# ifdef USE_DB
-       (void) strcat(buf, DBEXTENSION);
-# endif USE_DB
-       stb.st_ino = 0;
-       if (!init && (stat(buf, &stb) < 0 || stb.st_mtime < modtime || atcnt < 0))
+       /* see if we need to go into auto-rebuild mode */
+       if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
        {
        {
-               errno = 0;
+               if (tTd(27, 3))
+                       printf("aliaswait: not rebuildable\n");
+               return;
+       }
+       if (stat(map->map_file, &stb) < 0)
+       {
+               if (tTd(27, 3))
+                       printf("aliaswait: no source file\n");
+               return;
+       }
+       mtime = stb.st_mtime;
+       (void) strcpy(buf, map->map_file);
+       if (ext != NULL)
+               (void) strcat(buf, ext);
+       if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || atcnt < 0)
+       {
+               /* database is out of date */
                if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid())
                {
                if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid())
                {
-                       init = TRUE;
-                       automatic = TRUE;
-                       message(Arpa_Info, "rebuilding alias database");
-#ifdef LOG
-                       if (LogLevel >= 7)
-                               syslog(LOG_INFO, "rebuilding alias database");
-#endif LOG
+                       message("auto-rebuilding alias database %s", buf);
+                       rebuildaliases(map, TRUE);
                }
                else
                {
 #ifdef LOG
                }
                else
                {
 #ifdef LOG
-                       if (LogLevel >= 7)
-                               syslog(LOG_INFO, "alias database out of date");
-#endif LOG
-                       message(Arpa_Info, "Warning: alias database out of date");
+                       if (LogLevel > 3)
+                               syslog(LOG_INFO, "alias database %s out of date",
+                                       buf);
+#endif /* LOG */
+                       message("Warning: alias database %s out of date", buf);
                }
        }
                }
        }
-
-
-       /*
-       **  If necessary, load the DBM file.
-       **      If running without DBM, load the symbol table.
-       */
-
-       if (init)
-       {
-#ifdef LOG
-               if (LogLevel >= 6)
-               {
-                       extern char *username();
-
-                       syslog(LOG_NOTICE, "alias database %srebuilt by %s",
-                               automatic ? "auto" : "", username());
-               }
-#endif LOG
-               readaliases(aliasfile, TRUE);
-# ifdef USE_DB
-               aliasdb->sync (aliasdb, 0);
-# endif USE_DB
-       }
-#else /* defined (DBM) || defined (USE_DB) */
-       readaliases(aliasfile, init);
-#endif /* defined (DBM) || defined (USE_DB) */
 }
 \f/*
 }
 \f/*
-**  READALIASES -- read and process the alias file.
-**
-**     This routine implements the part of initaliases that occurs
-**     when we are not going to use the DBM stuff.
+**  REBUILDALIASES -- rebuild the alias database.
 **
 **     Parameters:
 **
 **     Parameters:
-**             aliasfile -- the pathname of the alias file master.
-**             init -- if set, initialize the DBM stuff.
+**             map -- the database to rebuild.
+**             automatic -- set if this was automatically generated.
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
-**             Reads aliasfile into the symbol table.
-**             Optionally, builds the .dir & .pag files.
+**             Reads the text version of the database, builds the
+**             DBM or DB version.
 */
 
 */
 
-static
-readaliases(aliasfile, init)
-       char *aliasfile;
-       bool init;
+rebuildaliases(map, automatic)
+       register MAP *map;
+       bool automatic;
 {
 {
-       register char *p;
-       char *rhs;
-       bool skipping;
-       int naliases, bytes, longest;
        FILE *af;
        void (*oldsigint)();
        FILE *af;
        void (*oldsigint)();
-       ADDRESS al, bl;
-       register STAB *s;
-       char line[BUFSIZ];
 
 
-       if ((af = fopen(aliasfile, "r")) == NULL)
+       if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
+               return;
+
+#ifdef LOG
+       if (LogLevel > 7)
+       {
+               syslog(LOG_NOTICE, "alias database %s %srebuilt by %s",
+                       map->map_file, automatic ? "auto" : "", username());
+       }
+#endif /* LOG */
+
+       /* try to lock the source file */
+       if ((af = fopen(map->map_file, "r+")) == NULL)
        {
                if (tTd(27, 1))
        {
                if (tTd(27, 1))
-                       printf("Can't open %s\n", aliasfile);
+                       printf("Can't open %s: %s\n",
+                               map->map_file, errstring(errno));
                errno = 0;
                errno = 0;
-               NoAlias++;
                return;
        }
 
                return;
        }
 
-#if defined (DBM) || defined (USE_DB)
-       /* see if someone else is rebuilding the alias file already */
-       if (flock(fileno(af), LOCK_EX | LOCK_NB) < 0 && errno == EWOULDBLOCK)
+       /* see if someone else is rebuilding the alias file */
+       if (!lockfile(fileno(af), map->map_file, LOCK_EX|LOCK_NB))
        {
        {
-               /* yes, they are -- wait until done and then return */
-               message(Arpa_Info, "Alias file is already being rebuilt");
+               /* yes, they are -- wait until done */
+               message("Alias file %s is already being rebuilt",
+                       map->map_file);
                if (OpMode != MD_INITALIAS)
                {
                        /* wait for other rebuild to complete */
                if (OpMode != MD_INITALIAS)
                {
                        /* wait for other rebuild to complete */
-                       (void) flock(fileno(af), LOCK_EX);
+                       (void) lockfile(fileno(af), map->map_file,
+                                       LOCK_EX);
                }
                (void) fclose(af);
                errno = 0;
                return;
        }
 
                }
                (void) fclose(af);
                errno = 0;
                return;
        }
 
-       /*
-       **  If initializing, create the new DBM files.
-       */
+       oldsigint = signal(SIGINT, SIG_IGN);
 
 
-       if (init)
+       if (map->map_class->map_open(map, O_RDWR))
        {
        {
-               oldsigint = signal(SIGINT, SIG_IGN);
-# ifdef USE_DB
-               if (aliasdb) aliasdb->close (aliasdb);
-# endif USE_DB
-               (void) strcpy(line, aliasfile);
-# ifdef DBM
-               (void) strcat(line, ".dir");
-               if (close(creat(line, DBMMODE)) < 0)
-               {
-                       syserr("cannot make %s", line);
-                       (void) signal(SIGINT, oldsigint);
-                       return;
-               }
-               (void) strcpy(line, aliasfile);
-               (void) strcat(line, ".pag");
-               if (close(creat(line, DBMMODE)) < 0)
-               {
-                       syserr("cannot make %s", line);
-                       (void) signal(SIGINT, oldsigint);
-                       return;
-               }
-               dbminit(aliasfile);
-# endif DBM
-# ifdef USE_DB
-               (void) strcat(line, DBEXTENSION);
-               /* unconditionally remove the database file so that a
-                  corrupt file cannot cause the following open to fail */
-               unlink (line);
-               aliasdb = dbopen(line, O_RDWR|O_CREAT, DBMMODE, DB_BTREE, 0);
-               if (aliasdb == NULL)
-               {
-                       syserr("Cannot open database file %s", line);
-                       (void) signal(SIGINT, oldsigint);
-                       return;
-               }
-# endif USE_DB
+               map->map_mflags |= MF_OPEN|MF_WRITABLE;
+               readaliases(map, af, automatic);
        }
        }
-#endif /* defined (DBM) || defined (USE_DB) */
+       else
+       {
+               if (tTd(27, 1))
+                       printf("Can't create database for %s: %s\n",
+                               map->map_file, errstring(errno));
+               if (!automatic)
+                       syserr("Cannot create database for alias file %s",
+                               map->map_file);
+       }
+
+       /* close the file, thus releasing locks */
+       fclose(af);
+
+       /* add distinguished entries and close the database */
+       if (bitset(MF_OPEN, map->map_mflags))
+               map->map_class->map_close(map);
+
+       /* restore the old signal */
+       (void) signal(SIGINT, oldsigint);
+}
+\f/*
+**  READALIASES -- read and process the alias file.
+**
+**     This routine implements the part of initaliases that occurs
+**     when we are not going to use the DBM stuff.
+**
+**     Parameters:
+**             map -- the alias database descriptor.
+**             af -- file to read the aliases from.
+**             automatic -- set if this was an automatic rebuild.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Reads aliasfile into the symbol table.
+**             Optionally, builds the .dir & .pag files.
+*/
+
+readaliases(map, af, automatic)
+       register MAP *map;
+       FILE *af;
+       int automatic;
+{
+       register char *p;
+       char *rhs;
+       bool skipping;
+       long naliases, bytes, longest;
+       ADDRESS al, bl;
+       char line[BUFSIZ];
 
        /*
        **  Read and interpret lines
        */
 
 
        /*
        **  Read and interpret lines
        */
 
-       FileName = aliasfile;
+       FileName = map->map_file;
        LineNumber = 0;
        naliases = bytes = longest = 0;
        skipping = FALSE;
        LineNumber = 0;
        naliases = bytes = longest = 0;
        skipping = FALSE;
@@ -475,7 +484,7 @@ readaliases(aliasfile, init)
                int lhssize, rhssize;
 
                LineNumber++;
                int lhssize, rhssize;
 
                LineNumber++;
-               p = index(line, '\n');
+               p = strchr(line, '\n');
                if (p != NULL)
                        *p = '\0';
                switch (line[0])
                if (p != NULL)
                        *p = '\0';
                switch (line[0])
@@ -488,7 +497,7 @@ readaliases(aliasfile, init)
                  case ' ':
                  case '\t':
                        if (!skipping)
                  case ' ':
                  case '\t':
                        if (!skipping)
-                               syserr("Non-continuation line starts with space");
+                               syserr("554 Non-continuation line starts with space");
                        skipping = TRUE;
                        continue;
                }
                        skipping = TRUE;
                        continue;
                }
@@ -496,7 +505,7 @@ readaliases(aliasfile, init)
 
                /*
                **  Process the LHS
 
                /*
                **  Process the LHS
-               **      Find the final colon, and parse the address.
+               **      Find the colon separator, and parse the address.
                **      It should resolve to a local name -- this will
                **      be checked later (we want to optionally do
                **      parsing of the RHS first to maximize error
                **      It should resolve to a local name -- this will
                **      be checked later (we want to optionally do
                **      parsing of the RHS first to maximize error
@@ -507,15 +516,14 @@ readaliases(aliasfile, init)
                        continue;
                if (*p++ != ':')
                {
                        continue;
                if (*p++ != ':')
                {
-                       syserr("missing colon");
+                       syserr("554 missing colon");
                        continue;
                }
                        continue;
                }
-               if (parseaddr(line, &al, 1, ':') == NULL)
+               if (parseaddr(line, &al, 1, ':', NULL, CurEnv) == NULL)
                {
                {
-                       syserr("illegal alias name");
+                       syserr("554 illegal alias name");
                        continue;
                }
                        continue;
                }
-               loweraddr(&al);
 
                /*
                **  Process the RHS.
 
                /*
                **  Process the RHS.
@@ -523,32 +531,38 @@ readaliases(aliasfile, init)
                **      'p' points to the text of the RHS.
                */
 
                **      'p' points to the text of the RHS.
                */
 
+               while (isascii(*p) && isspace(*p))
+                       p++;
                rhs = p;
                for (;;)
                {
                        register char c;
                rhs = p;
                for (;;)
                {
                        register char c;
+                       register char *nlp;
+
+                       nlp = &p[strlen(p)];
+                       if (nlp[-1] == '\n')
+                               *--nlp = '\0';
 
 
-                       if (init && CheckAliases)
+                       if (CheckAliases)
                        {
                                /* do parsing & compression of addresses */
                                while (*p != '\0')
                                {
                        {
                                /* do parsing & compression of addresses */
                                while (*p != '\0')
                                {
-                                       extern char *DelimChar;
+                                       auto char *delimptr;
 
 
-                                       while (isspace(*p) || *p == ',')
+                                       while ((isascii(*p) && isspace(*p)) ||
+                                                               *p == ',')
                                                p++;
                                        if (*p == '\0')
                                                break;
                                                p++;
                                        if (*p == '\0')
                                                break;
-                                       if (parseaddr(p, &bl, -1, ',') == NULL)
-                                               usrerr("%s... bad address", p);
-                                       p = DelimChar;
+                                       if (parseaddr(p, &bl, -1, ',', &delimptr, CurEnv) == NULL)
+                                               usrerr("553 %s... bad address", p);
+                                       p = delimptr;
                                }
                        }
                        else
                        {
                                }
                        }
                        else
                        {
-                               p = &p[strlen(p)];
-                               if (p[-1] == '\n')
-                                       *--p = '\0';
+                               p = nlp;
                        }
 
                        /* see if there should be a continuation line */
                        }
 
                        /* see if there should be a continuation line */
@@ -562,10 +576,17 @@ readaliases(aliasfile, init)
                        if (fgets(p, sizeof line - (p - line), af) == NULL)
                                break;
                        LineNumber++;
                        if (fgets(p, sizeof line - (p - line), af) == NULL)
                                break;
                        LineNumber++;
+
+                       /* check for line overflow */
+                       if (strchr(p, '\n') == NULL)
+                       {
+                               usrerr("554 alias too long");
+                               break;
+                       }
                }
                if (al.q_mailer != LocalMailer)
                {
                }
                if (al.q_mailer != LocalMailer)
                {
-                       syserr("cannot alias non-local names");
+                       syserr("554 cannot alias non-local names");
                        continue;
                }
 
                        continue;
                }
 
@@ -573,40 +594,19 @@ readaliases(aliasfile, init)
                **  Insert alias into symbol table or DBM file
                */
 
                **  Insert alias into symbol table or DBM file
                */
 
-               lhssize = strlen(al.q_user) + 1;
-               rhssize = strlen(rhs) + 1;
-
-# ifdef DBM
-               if (init)
-               {
-                       DATUM key, content;
-
-                       key.dsize = lhssize;
-                       key.dptr = al.q_user;
-                       content.dsize = rhssize;
-                       content.dptr = rhs;
-                       store(key, content);
-               }
-               else
-# endif DBM
-# ifdef USE_DB
-               if (init)
-               {
-                       DBT key, content;
+               if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags))
+                       makelower(al.q_user);
 
 
-                       key.size = lhssize;
-                       key.data = al.q_user;
-                       content.size = rhssize;
-                       content.data = rhs;
+               lhssize = strlen(al.q_user);
+               rhssize = strlen(rhs);
+               map->map_class->map_store(map, al.q_user, rhs);
 
 
-                       aliasdb->put (aliasdb, &key, &content, 0);
-               }
-               else
-# endif USE_DB
-               {
-                       s = stab(al.q_user, ST_ALIAS, ST_ENTER);
-                       s->s_alias = newstr(rhs);
-               }
+               if (al.q_paddr != NULL)
+                       free(al.q_paddr);
+               if (al.q_host != NULL)
+                       free(al.q_host);
+               if (al.q_user != NULL)
+                       free(al.q_user);
 
                /* statistics */
                naliases++;
 
                /* statistics */
                naliases++;
@@ -615,46 +615,16 @@ readaliases(aliasfile, init)
                        longest = rhssize;
        }
 
                        longest = rhssize;
        }
 
-# ifdef DBM
-       if (init)
-       {
-               /* add the distinquished alias "@" */
-               DATUM key;
-
-               key.dsize = 2;
-               key.dptr = "@";
-               store(key, key);
-
-               /* restore the old signal */
-               (void) signal(SIGINT, oldsigint);
-       }
-# endif DBM
-# ifdef USE_DB
-       if (init)
-       {
-               /* add the distinquished alias "@" */
-               DBT key;
-
-               key.size = 2;
-               key.data = "@";
-               aliasdb->put (aliasdb, &key, &key, 0);
-
-               /* restore the old signal */
-               (void) signal(SIGINT, oldsigint);
-       }
-# endif USE_DB
-
-       /* closing the alias file drops the lock */
-       (void) fclose(af);
        CurEnv->e_to = NULL;
        FileName = NULL;
        CurEnv->e_to = NULL;
        FileName = NULL;
-       message(Arpa_Info, "%d aliases, longest %d bytes, %d bytes total",
-                       naliases, longest, bytes);
+       if (Verbose || !automatic)
+               message("%s: %d aliases, longest %d bytes, %d bytes total",
+                       map->map_file, naliases, longest, bytes);
 # ifdef LOG
 # ifdef LOG
-       if (LogLevel >= 8)
-               syslog(LOG_INFO, "%d aliases, longest %d bytes, %d bytes total",
-                       naliases, longest, bytes);
-# endif LOG
+       if (LogLevel > 7)
+               syslog(LOG_INFO, "%s: %d aliases, longest %d bytes, %d bytes total",
+                       map->map_file, naliases, longest, bytes);
+# endif /* LOG */
 }
 \f/*
 **  FORWARD -- Try to forward mail
 }
 \f/*
 **  FORWARD -- Try to forward mail
@@ -676,12 +646,13 @@ readaliases(aliasfile, init)
 **             New names are added to send queues.
 */
 
 **             New names are added to send queues.
 */
 
-forward(user, sendq)
+forward(user, sendq, e)
        ADDRESS *user;
        ADDRESS **sendq;
        ADDRESS *user;
        ADDRESS **sendq;
+       register ENVELOPE *e;
 {
 {
-       char buf[60];
-       extern bool safefile();
+       char *pp;
+       char *ep;
 
        if (tTd(27, 1))
                printf("forward(%s)\n", user->q_paddr);
 
        if (tTd(27, 1))
                printf("forward(%s)\n", user->q_paddr);
@@ -689,14 +660,47 @@ forward(user, sendq)
        if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags))
                return;
        if (user->q_home == NULL)
        if (user->q_mailer != LocalMailer || bitset(QBADADDR, user->q_flags))
                return;
        if (user->q_home == NULL)
-               syserr("forward: no home");
+       {
+               syserr("554 forward: no home");
+               user->q_home = "/nosuchdirectory";
+       }
 
        /* good address -- look for .forward file in home */
 
        /* good address -- look for .forward file in home */
-       define('z', user->q_home, CurEnv);
-       expand("\001z/.forward", buf, &buf[sizeof buf - 1], CurEnv);
-       if (!safefile(buf, user->q_uid, S_IREAD))
-               return;
+       define('z', user->q_home, e);
+       define('u', user->q_user, e);
+       define('h', user->q_host, e);
+       if (ForwardPath == NULL)
+               ForwardPath = newstr("\201z/.forward");
 
 
-       /* we do have an address to forward to -- do it */
-       include(buf, "forwarding", user, sendq);
+       for (pp = ForwardPath; pp != NULL; pp = ep)
+       {
+               int err;
+               char buf[MAXPATHLEN+1];
+
+               ep = strchr(pp, ':');
+               if (ep != NULL)
+                       *ep = '\0';
+               expand(pp, buf, &buf[sizeof buf - 1], e);
+               if (ep != NULL)
+                       *ep++ = ':';
+               if (tTd(27, 3))
+                       printf("forward: trying %s\n", buf);
+               err = include(buf, TRUE, user, sendq, e);
+               if (err == 0)
+                       break;
+               if (transienterror(err))
+               {
+                       /* we have to suspend this message */
+                       if (tTd(27, 2))
+                               printf("forward: transient error on %s\n", buf);
+#ifdef LOG
+                       if (LogLevel > 2)
+                               syslog(LOG_ERR, "%s: forward %s: transient error: %s",
+                                       e->e_id, buf, errstring(err));
+#endif
+                       message("%s: %s: message queued", buf, errstring(err));
+                       user->q_flags |= QQUEUEUP|QDONTSEND;
+                       return;
+               }
+       }
 }
 }
diff --git a/usr.sbin/sendmail/src/aliases b/usr.sbin/sendmail/src/aliases
new file mode 100644 (file)
index 0000000..9a9508b
--- /dev/null
@@ -0,0 +1,52 @@
+#
+#      @(#)aliases     8.1 (Berkeley) 6/9/93
+#
+#  Aliases in this file will NOT be expanded in the header from
+#  Mail, but WILL be visible over networks or from /bin/mail.
+#
+#      >>>>>>>>>>      The program "newaliases" must be run after
+#      >> NOTE >>      this file is updated for any changes to
+#      >>>>>>>>>>      show through to sendmail.
+#
+
+# Basic system aliases -- these MUST be present.
+MAILER-DAEMON: postmaster
+postmaster:    root
+
+# General redirections for pseudo accounts.
+bin:           root
+daemon:                root
+games:         root
+ingres:                root
+nobody:                root
+system:                root
+toor:          root
+uucp:          root
+
+# Well-known aliases.
+manager:       root
+dumper:                root
+operator:      root
+
+# trap decode to catch security attacks
+decode:                root
+
+# OFFICIAL CSRG/BUG ADDRESSES
+
+# Ftp maintainer.
+ftp-bugs: bigbug@cs.berkeley.edu
+
+# Distribution office.
+bsd-dist: bsd-dist@cs.berkeley.edu
+
+# Fortune maintainer.
+fortune: fortune@cs.berkeley.edu
+
+# Termcap maintainer.
+termcap: termcap@cs.berkeley.edu
+
+# General bug address.
+ucb-fixes: bigbug@cs.berkeley.edu
+ucb-fixes-request: bigbug@cs.berkeley.edu
+bugs: bugs@cs.berkeley.edu
+# END OFFICIAL BUG ADDRESSES
index 1f75b75..39f3805 100644 (file)
@@ -1,5 +1,5 @@
-.\" Copyright (c) 1985, 1991 The Regents of the University of California.
-.\" All rights reserved.
+.\" Copyright (c) 1985, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
@@ -29,9 +29,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"     @(#)aliases.5  6.5 (Berkeley) 5/10/91
+.\"     @(#)aliases.5  8.1 (Berkeley) 6/16/93
 .\"
 .\"
-.Dd May 10, 1991
+.Dd June 16, 1993
 .Dt ALIASES 5
 .Os BSD 4
 .Sh NAME
 .Dt ALIASES 5
 .Os BSD 4
 .Sh NAME
@@ -71,10 +71,8 @@ file in their home directory have messages forwarded to the
 list of users defined in that file.
 .Pp
 This is only the raw data file; the actual aliasing information is
 list of users defined in that file.
 .Pp
 This is only the raw data file; the actual aliasing information is
-placed into a binary format in the files
-.Pa /etc/aliases.dir
-and
-.Pa /etc/aliases.pag
+placed into a binary format in the file
+.Pa /etc/aliases.db
 using the program
 .Xr newaliases 1 .
 A
 using the program
 .Xr newaliases 1 .
 A
@@ -83,6 +81,7 @@ command should be executed each time the aliases file is changed for the
 change to take effect.
 .Sh SEE  ALSO
 .Xr newaliases 1 ,
 change to take effect.
 .Sh SEE  ALSO
 .Xr newaliases 1 ,
+.Xr dbopen 3 ,
 .Xr dbm 3 ,
 .Xr sendmail 8
 .Rs
 .Xr dbm 3 ,
 .Xr sendmail 8
 .Rs
@@ -92,9 +91,12 @@ change to take effect.
 .%T "SENDMAIL An Internetwork Mail Router"
 .Re
 .Sh BUGS
 .%T "SENDMAIL An Internetwork Mail Router"
 .Re
 .Sh BUGS
-Because of restrictions in
+If you have compiled
+.Xr sendmail
+with DBM support instead of NEWDB,
+you may have encounter problems in
 .Xr dbm 3
 .Xr dbm 3
-a single alias cannot contain more than about 1000 bytes of information.
+restricting a single alias to about 1000 bytes of information.
 You can get longer aliases by ``chaining''; that is, make the last name in
 the alias be a dummy name which is a continuation alias.
 .Sh HISTORY
 You can get longer aliases by ``chaining''; that is, make the last name in
 the alias be a dummy name which is a continuation alias.
 .Sh HISTORY
index 29bf644..d3f9ac5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)arpadate.c 5.11 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)arpadate.c 8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #endif /* not lint */
 
-# include "conf.h"
-# include <time.h>
-# include <sys/types.h>
-# include "useful.h"
+# include "sendmail.h"
 
 /*
 **  ARPADATE -- Create date in ARPANET format
 
 /*
 **  ARPADATE -- Create date in ARPANET format
@@ -79,9 +76,6 @@ arpadate(ud)
        time_t t;
        struct tm gmt;
        static char b[40];
        time_t t;
        struct tm gmt;
        static char b[40];
-       extern struct tm *localtime(), *gmtime();
-       extern char *ctime();
-       extern time_t time();
 
        /*
        **  Get current time.
 
        /*
        **  Get current time.
@@ -120,7 +114,9 @@ arpadate(ud)
        *q++ = *p++;
        *q++ = ' ';
 
        *q++ = *p++;
        *q++ = ' ';
 
-       p = &ud[22];            /* 79 */
+       p = &ud[20];            /* 1979 */
+       *q++ = *p++;
+       *q++ = *p++;
        *q++ = *p++;
        *q++ = *p++;
        *q++ = ' ';
        *q++ = *p++;
        *q++ = *p++;
        *q++ = ' ';
diff --git a/usr.sbin/sendmail/src/cdefs.h b/usr.sbin/sendmail/src/cdefs.h
new file mode 100644 (file)
index 0000000..a04665e
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)cdefs.h     8.1 (Berkeley) 6/2/93
+ */
+
+#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
+
+#else  /* !(__STDC__ || __cplusplus) */
+#define        __P(protos)     ()              /* traditional C preprocessor */
+#define        __CONCAT(x,y)   x/**/y
+#define        __STRING(x)     "x"
+
+#ifdef __GNUC__
+#define        const           __const         /* GCC: ANSI C with -traditional */
+#define        inline          __inline
+#define        signed          __signed
+#define        volatile        __volatile
+
+#else  /* !__GNUC__ */
+#define        const                           /* delete ANSI C keywords */
+#define        inline
+#define        signed
+#define        volatile
+#endif /* !__GNUC__ */
+#endif /* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC has extensions for declaring functions as `pure' (always returns
+ * the same value given the same inputs, i.e., has no external state and
+ * no side effects) and `dead' (nonreturning).  These mainly affect
+ * optimization and warnings.  Unfortunately, GCC complains if these are
+ * used under strict ANSI mode (`gcc -ansi -pedantic'), hence we need to
+ * define them only if compiling without this.
+ */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define __dead __volatile
+#define __pure __const
+#else
+#define __dead
+#define __pure
+#endif
+
+#endif /* !_CDEFS_H_ */
index 890bfc0..ca45d3c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)clock.c    5.10 (Berkeley) 3/4/91";
+static char sccsid[] = "@(#)clock.c    8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 # include "sendmail.h"
 # include <signal.h>
 
 #endif /* not lint */
 
 # include "sendmail.h"
 # include <signal.h>
 
+# ifndef sigmask
+#  define sigmask(s)   (1 << ((s) - 1))
+# endif
+
 /*
 **  SETEVENT -- set an event to happen at a specific time.
 **
 /*
 **  SETEVENT -- set an event to happen at a specific time.
 **
@@ -71,7 +75,7 @@ setevent(intvl, func, arg)
 
        if (intvl <= 0)
        {
 
        if (intvl <= 0)
        {
-               syserr("setevent: intvl=%ld\n", intvl);
+               syserr("554 setevent: intvl=%ld\n", intvl);
                return (NULL);
        }
 
                return (NULL);
        }
 
@@ -189,7 +193,7 @@ tick()
 #ifdef SIGVTALRM
                /* reset 4.2bsd signal mask to allow future alarms */
                (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
 #ifdef SIGVTALRM
                /* reset 4.2bsd signal mask to allow future alarms */
                (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
-#endif SIGVTALRM
+#endif /* SIGVTALRM */
 
                f = ev->ev_func;
                arg = ev->ev_arg;
 
                f = ev->ev_func;
                arg = ev->ev_arg;
@@ -231,6 +235,7 @@ tick()
 
 static bool    SleepDone;
 
 
 static bool    SleepDone;
 
+unsigned int
 sleep(intvl)
        unsigned int intvl;
 {
 sleep(intvl)
        unsigned int intvl;
 {
index a96df15..4398b85 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)collect.c  5.9 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)collect.c  8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 # include <errno.h>
 #endif /* not lint */
 
 # include <errno.h>
@@ -47,8 +47,13 @@ static char sccsid[] = "@(#)collect.c        5.9 (Berkeley) 6/1/90";
 **     stripped off (after important information is extracted).
 **
 **     Parameters:
 **     stripped off (after important information is extracted).
 **
 **     Parameters:
-**             sayok -- if set, give an ARPANET style message
-**                     to say we are ready to collect input.
+**             smtpmode -- if set, we are running SMTP: give an RFC821
+**                     style message to say we are ready to collect
+**                     input, and never ignore a single dot to mean
+**                     end of message.
+**             requeueflag -- this message will be requeued later, so
+**                     don't do final processing on it.
+**             e -- the current envelope.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -58,13 +63,15 @@ static char sccsid[] = "@(#)collect.c       5.9 (Berkeley) 6/1/90";
 **             The from person may be set.
 */
 
 **             The from person may be set.
 */
 
-collect(sayok)
-       bool sayok;
+collect(smtpmode, requeueflag, e)
+       bool smtpmode;
+       bool requeueflag;
+       register ENVELOPE *e;
 {
        register FILE *tf;
 {
        register FILE *tf;
-       char buf[MAXFIELD], buf2[MAXFIELD];
+       bool ignrdot = smtpmode ? FALSE : IgnrDot;
+       char buf[MAXLINE], buf2[MAXLINE];
        register char *workbuf, *freebuf;
        register char *workbuf, *freebuf;
-       register int workbuflen;
        extern char *hvalue();
        extern bool isheader(), flusheol();
 
        extern char *hvalue();
        extern bool isheader(), flusheol();
 
@@ -72,27 +79,27 @@ collect(sayok)
        **  Create the temp file name and create the file.
        */
 
        **  Create the temp file name and create the file.
        */
 
-       CurEnv->e_df = newstr(queuename(CurEnv, 'd'));
-       if ((tf = dfopen(CurEnv->e_df, "w")) == NULL)
+       e->e_df = newstr(queuename(e, 'd'));
+       if ((tf = dfopen(e->e_df, O_WRONLY|O_CREAT, FileMode)) == NULL)
        {
        {
-               syserr("Cannot create %s", CurEnv->e_df);
+               syserr("Cannot create %s", e->e_df);
                NoReturn = TRUE;
                finis();
        }
                NoReturn = TRUE;
                finis();
        }
-       (void) chmod(CurEnv->e_df, FileMode);
 
        /*
        **  Tell ARPANET to go ahead.
        */
 
 
        /*
        **  Tell ARPANET to go ahead.
        */
 
-       if (sayok)
-               message("354", "Enter mail, end with \".\" on a line by itself");
+       if (smtpmode)
+               message("354 Enter mail, end with \".\" on a line by itself");
 
        /*
        **  Try to read a UNIX-style From line
        */
 
 
        /*
        **  Try to read a UNIX-style From line
        */
 
-       if (sfgets(buf, MAXFIELD, InChannel) == NULL)
+       if (sfgets(buf, MAXLINE, InChannel, TimeOuts.to_datablock,
+                       "initial message read") == NULL)
                goto readerr;
        fixcrlf(buf, FALSE);
 # ifndef NOTUNIX
                goto readerr;
        fixcrlf(buf, FALSE);
 # ifndef NOTUNIX
@@ -100,12 +107,13 @@ collect(sayok)
        {
                if (!flusheol(buf, InChannel))
                        goto readerr;
        {
                if (!flusheol(buf, InChannel))
                        goto readerr;
-               eatfrom(buf);
-               if (sfgets(buf, MAXFIELD, InChannel) == NULL)
+               eatfrom(buf, e);
+               if (sfgets(buf, MAXLINE, InChannel, TimeOuts.to_datablock,
+                               "message header read") == NULL)
                        goto readerr;
                fixcrlf(buf, FALSE);
        }
                        goto readerr;
                fixcrlf(buf, FALSE);
        }
-# endif NOTUNIX
+# endif /* NOTUNIX */
 
        /*
        **  Copy InChannel to temp file & do message editing.
 
        /*
        **  Copy InChannel to temp file & do message editing.
@@ -118,6 +126,11 @@ collect(sayok)
        freebuf = buf2;         /* `freebuf' can be used for read-ahead */
        for (;;)
        {
        freebuf = buf2;         /* `freebuf' can be used for read-ahead */
        for (;;)
        {
+               char *curbuf;
+               int curbuffree;
+               register int curbuflen;
+               char *p;
+
                /* first, see if the header is over */
                if (!isheader(workbuf))
                {
                /* first, see if the header is over */
                if (!isheader(workbuf))
                {
@@ -132,12 +145,19 @@ collect(sayok)
                /* it's okay to toss '\n' now (flusheol() needed it) */
                fixcrlf(workbuf, TRUE);
 
                /* it's okay to toss '\n' now (flusheol() needed it) */
                fixcrlf(workbuf, TRUE);
 
-               workbuflen = strlen(workbuf);
+               curbuf = workbuf;
+               curbuflen = strlen(curbuf);
+               curbuffree = MAXLINE - curbuflen;
+               p = curbuf + curbuflen;
 
                /* get the rest of this field */
                for (;;)
                {
 
                /* get the rest of this field */
                for (;;)
                {
-                       if (sfgets(freebuf, MAXFIELD, InChannel) == NULL)
+                       int clen;
+
+                       if (sfgets(freebuf, MAXLINE, InChannel,
+                                       TimeOuts.to_datablock,
+                                       "message header read") == NULL)
                                goto readerr;
 
                        /* is this a continuation line? */
                                goto readerr;
 
                        /* is this a continuation line? */
@@ -147,25 +167,32 @@ collect(sayok)
                        if (!flusheol(freebuf, InChannel))
                                goto readerr;
 
                        if (!flusheol(freebuf, InChannel))
                                goto readerr;
 
-                       /* yes; append line to `workbuf' if there's room */
-                       if (workbuflen < MAXFIELD-3)
+                       fixcrlf(freebuf, TRUE);
+                       clen = strlen(freebuf) + 1;
+
+                       /* if insufficient room, dynamically allocate buffer */
+                       if (clen >= curbuffree)
                        {
                        {
-                               register char *p = workbuf + workbuflen;
-                               register char *q = freebuf;
-
-                               /* we have room for more of this field */
-                               fixcrlf(freebuf, TRUE);
-                               *p++ = '\n'; workbuflen++;
-                               while(*q != '\0' && workbuflen < MAXFIELD-1)
-                               {
-                                       *p++ = *q++;
-                                       workbuflen++;
-                               }
-                               *p = '\0';
+                               /* reallocate buffer */
+                               int nbuflen = ((p - curbuf) + clen) * 2;
+                               char *nbuf = xalloc(nbuflen);
+
+                               p = nbuf + curbuflen;
+                               curbuffree = nbuflen - curbuflen;
+                               bcopy(curbuf, nbuf, curbuflen);
+                               if (curbuf != buf && curbuf != buf2)
+                                       free(curbuf);
+                               curbuf = nbuf;
                        }
                        }
+                       *p++ = '\n';
+                       bcopy(freebuf, p, clen - 1);
+                       p += clen - 1;
+                       curbuffree -= clen;
+                       curbuflen += clen;
                }
                }
+               *p++ = '\0';
 
 
-               CurEnv->e_msgsize += workbuflen;
+               e->e_msgsize += curbuflen;
 
                /*
                **  The working buffer now becomes the free buffer, since
 
                /*
                **  The working buffer now becomes the free buffer, since
@@ -189,8 +216,15 @@ collect(sayok)
                **  Snarf header away.
                */
 
                **  Snarf header away.
                */
 
-               if (bitset(H_EOH, chompheader(freebuf, FALSE)))
+               if (bitset(H_EOH, chompheader(curbuf, FALSE, e)))
                        break;
                        break;
+
+               /*
+               **  If the buffer was dynamically allocated, free it.
+               */
+
+               if (curbuf != buf && curbuf != buf2)
+                       free(curbuf);
        }
 
        if (tTd(30, 1))
        }
 
        if (tTd(30, 1))
@@ -199,7 +233,8 @@ collect(sayok)
        if (*workbuf == '\0')
        {
                /* throw away a blank line */
        if (*workbuf == '\0')
        {
                /* throw away a blank line */
-               if (sfgets(buf, MAXFIELD, InChannel) == NULL)
+               if (sfgets(buf, MAXLINE, InChannel, TimeOuts.to_datablock,
+                               "message separator read") == NULL)
                        goto readerr;
        }
        else if (workbuf == buf2)       /* guarantee `buf' contains data */
                        goto readerr;
        }
        else if (workbuf == buf2)       /* guarantee `buf' contains data */
@@ -216,11 +251,11 @@ collect(sayok)
                fixcrlf(buf, TRUE);
 
                /* check for end-of-message */
                fixcrlf(buf, TRUE);
 
                /* check for end-of-message */
-               if (!IgnrDot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0'))
+               if (!ignrdot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0'))
                        break;
 
                /* check for transparent dot */
                        break;
 
                /* check for transparent dot */
-               if (OpMode == MD_SMTP && !IgnrDot && bp[0] == '.' && bp[1] == '.')
+               if (OpMode == MD_SMTP && bp[0] == '.' && bp[1] == '.')
                        bp++;
 
                /*
                        bp++;
 
                /*
@@ -228,34 +263,42 @@ collect(sayok)
                **  file, and insert a newline if missing.
                */
 
                **  file, and insert a newline if missing.
                */
 
-               CurEnv->e_msgsize += strlen(bp) + 1;
+               e->e_msgsize += strlen(bp) + 1;
                fputs(bp, tf);
                fputs("\n", tf);
                if (ferror(tf))
                fputs(bp, tf);
                fputs("\n", tf);
                if (ferror(tf))
-                       tferror(tf);
-       } while (sfgets(buf, MAXFIELD, InChannel) != NULL);
+                       tferror(tf, e);
+       } while (sfgets(buf, MAXLINE, InChannel, TimeOuts.to_datablock,
+                       "message body read") != NULL);
 
 readerr:
        if (fflush(tf) != 0)
 
 readerr:
        if (fflush(tf) != 0)
-               tferror(tf);
+               tferror(tf, e);
+       (void) fsync(fileno(tf));
        (void) fclose(tf);
 
        /* An EOF when running SMTP is an error */
        if ((feof(InChannel) || ferror(InChannel)) && OpMode == MD_SMTP)
        {
        (void) fclose(tf);
 
        /* An EOF when running SMTP is an error */
        if ((feof(InChannel) || ferror(InChannel)) && OpMode == MD_SMTP)
        {
-               int usrerr(), syserr();
+               char *host;
+
+               host = RealHostName;
+               if (host == NULL)
+                       host = "localhost";
+
 # ifdef LOG
 # ifdef LOG
-               if (RealHostName != NULL && LogLevel > 0)
+               if (LogLevel > 0 && feof(InChannel))
                        syslog(LOG_NOTICE,
                        syslog(LOG_NOTICE,
-                           "collect: unexpected close on connection from %s: %m\n",
-                           CurEnv->e_from.q_paddr, RealHostName);
+                           "collect: unexpected close on connection from %s, sender=%s: %m\n",
+                           host, e->e_from.q_paddr);
 # endif
 # endif
-               (feof(InChannel) ? usrerr: syserr)
-                       ("collect: unexpected close, from=%s", CurEnv->e_from.q_paddr);
+               (feof(InChannel) ? usrerr : syserr)
+                       ("451 collect: unexpected close on connection from %s, from=%s",
+                               host, e->e_from.q_paddr);
 
                /* don't return an error indication */
 
                /* don't return an error indication */
-               CurEnv->e_to = NULL;
-               CurEnv->e_flags &= ~EF_FATALERRS;
+               e->e_to = NULL;
+               e->e_flags &= ~EF_FATALERRS;
 
                /* and don't try to deliver the partial message either */
                finis();
 
                /* and don't try to deliver the partial message either */
                finis();
@@ -266,31 +309,42 @@ readerr:
        **      Examples are who is the from person & the date.
        */
 
        **      Examples are who is the from person & the date.
        */
 
-       eatheader(CurEnv);
+       eatheader(e, !requeueflag);
 
        /*
        **  Add an Apparently-To: line if we have no recipient lines.
        */
 
 
        /*
        **  Add an Apparently-To: line if we have no recipient lines.
        */
 
-       if (hvalue("to") == NULL && hvalue("cc") == NULL &&
-           hvalue("bcc") == NULL && hvalue("apparently-to") == NULL)
+       if (hvalue("to", e) == NULL && hvalue("cc", e) == NULL &&
+           hvalue("bcc", e) == NULL && hvalue("apparently-to", e) == NULL)
        {
                register ADDRESS *q;
 
                /* create an Apparently-To: field */
                /*    that or reject the message.... */
        {
                register ADDRESS *q;
 
                /* create an Apparently-To: field */
                /*    that or reject the message.... */
-               for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next)
+               for (q = e->e_sendqueue; q != NULL; q = q->q_next)
                {
                        if (q->q_alias != NULL)
                                continue;
                        if (tTd(30, 3))
                                printf("Adding Apparently-To: %s\n", q->q_paddr);
                {
                        if (q->q_alias != NULL)
                                continue;
                        if (tTd(30, 3))
                                printf("Adding Apparently-To: %s\n", q->q_paddr);
-                       addheader("apparently-to", q->q_paddr, CurEnv);
+                       addheader("Apparently-To", q->q_paddr, e);
                }
        }
 
                }
        }
 
-       if ((CurEnv->e_dfp = fopen(CurEnv->e_df, "r")) == NULL)
-               syserr("Cannot reopen %s", CurEnv->e_df);
+       /* check for message too large */
+       if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize)
+       {
+               usrerr("552 Message exceeds maximum fixed size (%ld)",
+                       MaxMessageSize);
+       }
+
+       if ((e->e_dfp = fopen(e->e_df, "r")) == NULL)
+       {
+               /* we haven't acked receipt yet, so just chuck this */
+               syserr("Cannot reopen %s", e->e_df);
+               finis();
+       }
 }
 \f/*
 **  FLUSHEOL -- if not at EOL, throw away rest of input line.
 }
 \f/*
 **  FLUSHEOL -- if not at EOL, throw away rest of input line.
@@ -311,16 +365,22 @@ flusheol(buf, fp)
        char *buf;
        FILE *fp;
 {
        char *buf;
        FILE *fp;
 {
-       char junkbuf[MAXLINE], *sfgets();
        register char *p = buf;
        register char *p = buf;
+       bool printmsg = TRUE;
+       char junkbuf[MAXLINE];
 
 
-       while (index(p, '\n') == NULL) {
-               if (sfgets(junkbuf,MAXLINE,fp) == NULL)
-                       return(FALSE);
+       while (strchr(p, '\n') == NULL)
+       {
+               if (printmsg)
+                       usrerr("553 header line too long");
+               printmsg = FALSE;
+               if (sfgets(junkbuf, MAXLINE, fp, TimeOuts.to_datablock,
+                               "long line flush") == NULL)
+                       return (FALSE);
                p = junkbuf;
        }
 
                p = junkbuf;
        }
 
-       return(TRUE);
+       return (TRUE);
 }
 \f/*
 **  TFERROR -- signal error on writing the temporary file.
 }
 \f/*
 **  TFERROR -- signal error on writing the temporary file.
@@ -336,17 +396,18 @@ flusheol(buf, fp)
 **             Arranges for following output to go elsewhere.
 */
 
 **             Arranges for following output to go elsewhere.
 */
 
-tferror(tf)
+tferror(tf, e)
        FILE *tf;
        FILE *tf;
+       register ENVELOPE *e;
 {
        if (errno == ENOSPC)
        {
 {
        if (errno == ENOSPC)
        {
-               (void) freopen(CurEnv->e_df, "w", tf);
+               (void) freopen(e->e_df, "w", tf);
                fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf);
                usrerr("452 Out of disk space for temp file");
        }
        else
                fputs("\nMAIL DELETED BECAUSE OF LACK OF DISK SPACE\n\n", tf);
                usrerr("452 Out of disk space for temp file");
        }
        else
-               syserr("collect: Cannot write %s", CurEnv->e_df);
+               syserr("collect: Cannot write %s", e->e_df);
        (void) freopen("/dev/null", "w", tf);
 }
 \f/*
        (void) freopen("/dev/null", "w", tf);
 }
 \f/*
@@ -380,8 +441,9 @@ char        *MonthList[] =
        NULL
 };
 
        NULL
 };
 
-eatfrom(fm)
+eatfrom(fm, e)
        char *fm;
        char *fm;
+       register ENVELOPE *e;
 {
        register char *p;
        register char **dt;
 {
        register char *p;
        register char **dt;
@@ -398,7 +460,8 @@ eatfrom(fm)
                        p++;
                while (*p == ' ')
                        p++;
                        p++;
                while (*p == ' ')
                        p++;
-               if (!isupper(*p) || p[3] != ' ' || p[13] != ':' || p[16] != ':')
+               if (!(isascii(*p) && isupper(*p)) ||
+                   p[3] != ' ' || p[13] != ':' || p[16] != ':')
                        continue;
 
                /* we have a possible date */
                        continue;
 
                /* we have a possible date */
@@ -415,7 +478,7 @@ eatfrom(fm)
                        break;
        }
 
                        break;
        }
 
-       if (*p != NULL)
+       if (*p != '\0')
        {
                char *q;
                extern char *arpadate();
        {
                char *q;
                extern char *arpadate();
@@ -424,10 +487,9 @@ eatfrom(fm)
                q = xalloc(25);
                (void) strncpy(q, p, 25);
                q[24] = '\0';
                q = xalloc(25);
                (void) strncpy(q, p, 25);
                q[24] = '\0';
-               define('d', q, CurEnv);
                q = arpadate(q);
                q = arpadate(q);
-               define('a', newstr(q), CurEnv);
+               define('a', newstr(q), e);
        }
 }
 
        }
 }
 
-# endif NOTUNIX
+# endif /* NOTUNIX */
index 292a127..be4ff27 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)conf.c     5.28 (Berkeley) 3/12/91";
+static char sccsid[] = "@(#)conf.c     8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 # include <sys/ioctl.h>
 # include <sys/param.h>
 #endif /* not lint */
 
 # include <sys/ioctl.h>
 # include <sys/param.h>
+# include <signal.h>
 # include <pwd.h>
 # include "sendmail.h"
 # include "pathnames.h"
 # include <pwd.h>
 # include "sendmail.h"
 # include "pathnames.h"
@@ -47,9 +48,6 @@ static char sccsid[] = "@(#)conf.c    5.28 (Berkeley) 3/12/91";
 **
 **     Defines the configuration of this installation.
 **
 **
 **     Defines the configuration of this installation.
 **
-**     Compilation Flags:
-**             VMUNIX -- running on a Berkeley UNIX system.
-**
 **     Configuration Variables:
 **             HdrInfo -- a table describing well-known header fields.
 **                     Each entry has the field name and some flags,
 **     Configuration Variables:
 **             HdrInfo -- a table describing well-known header fields.
 **                     Each entry has the field name and some flags,
@@ -89,8 +87,9 @@ struct hdrinfo        HdrInfo[] =
        "from",                 H_FROM,
        "reply-to",             H_FROM,
        "full-name",            H_ACHECK,
        "from",                 H_FROM,
        "reply-to",             H_FROM,
        "full-name",            H_ACHECK,
-       "return-receipt-to",    H_FROM,
-       "errors-to",            H_FROM,
+       "return-receipt-to",    H_FROM /* |H_RECEIPTTO */,
+       "errors-to",            H_FROM|H_ERRORSTO,
+
                /* destination fields */
        "to",                   H_RCPT,
        "resent-to",            H_RCPT|H_RESENT,
                /* destination fields */
        "to",                   H_RCPT,
        "resent-to",            H_RCPT|H_RESENT,
@@ -98,40 +97,60 @@ struct hdrinfo      HdrInfo[] =
        "resent-cc",            H_RCPT|H_RESENT,
        "bcc",                  H_RCPT|H_ACHECK,
        "resent-bcc",           H_RCPT|H_ACHECK|H_RESENT,
        "resent-cc",            H_RCPT|H_RESENT,
        "bcc",                  H_RCPT|H_ACHECK,
        "resent-bcc",           H_RCPT|H_ACHECK|H_RESENT,
+       "apparently-to",        H_RCPT,
+
                /* message identification and control */
        "message-id",           0,
        "resent-message-id",    H_RESENT,
        "message",              H_EOH,
        "text",                 H_EOH,
                /* message identification and control */
        "message-id",           0,
        "resent-message-id",    H_RESENT,
        "message",              H_EOH,
        "text",                 H_EOH,
+
                /* date fields */
        "date",                 0,
        "resent-date",          H_RESENT,
                /* date fields */
        "date",                 0,
        "resent-date",          H_RESENT,
+
                /* trace fields */
        "received",             H_TRACE|H_FORCE,
                /* trace fields */
        "received",             H_TRACE|H_FORCE,
+       "x400-received",        H_TRACE|H_FORCE,
        "via",                  H_TRACE|H_FORCE,
        "mail-from",            H_TRACE|H_FORCE,
 
        "via",                  H_TRACE|H_FORCE,
        "mail-from",            H_TRACE|H_FORCE,
 
+               /* miscellaneous fields */
+       "comments",             H_FORCE,
+       "return-path",          H_ACHECK,
+
        NULL,                   0,
 };
 
 
        NULL,                   0,
 };
 
 
+
 /*
 /*
-**  ARPANET error message numbers.
+**  Location of system files/databases/etc.
 */
 
 */
 
-char   Arpa_Info[] =           "050";  /* arbitrary info */
-char   Arpa_TSyserr[] =        "451";  /* some (transient) system error */
-char   Arpa_PSyserr[] =        "554";  /* some (permanent) system error */
-char   Arpa_Usrerr[] =         "554";  /* some (fatal) user error */
+char   *ConfFile =     _PATH_SENDMAILCF;       /* runtime configuration */
+char   *FreezeFile =   _PATH_SENDMAILFC;       /* frozen version of above */
+char   *PidFile =      _PATH_SENDMAILPID;      /* stores daemon proc id */
 
 
 
 /*
 
 
 
 /*
-**  Location of system files/databases/etc.
+**  Privacy values
 */
 
 */
 
-char   *ConfFile =     _PATH_SENDMAILCF;       /* runtime configuration */
-char   *FreezeFile =   _PATH_SENDMAILFC;       /* frozen version of above */
+struct prival PrivacyValues[] =
+{
+       "public",               PRIV_PUBLIC,
+       "needmailhelo",         PRIV_NEEDMAILHELO,
+       "needexpnhelo",         PRIV_NEEDEXPNHELO,
+       "needvrfyhelo",         PRIV_NEEDVRFYHELO,
+       "noexpn",               PRIV_NOEXPN,
+       "novrfy",               PRIV_NOVRFY,
+       "restrictmailq",        PRIV_RESTRMAILQ,
+       "authwarnings",         PRIV_AUTHWARNINGS,
+       "goaway",               PRIV_GOAWAY,
+       NULL,                   0,
+};
 
 
 
 
 
 
@@ -140,7 +159,6 @@ char        *FreezeFile =   _PATH_SENDMAILFC;       /* frozen version of above */
 */
 
 int    DtableSize =    50;             /* max open files; reset in 4.2bsd */
 */
 
 int    DtableSize =    50;             /* max open files; reset in 4.2bsd */
-extern int la;                         /* load average */
 \f/*
 **  SETDEFAULTS -- set default values
 **
 \f/*
 **  SETDEFAULTS -- set default values
 **
@@ -148,7 +166,7 @@ extern int la;                              /* load average */
 **     using direct code.
 **
 **     Parameters:
 **     using direct code.
 **
 **     Parameters:
-**             none.
+**             e -- the default envelope.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -158,20 +176,37 @@ extern int la;                            /* load average */
 **             default values.
 */
 
 **             default values.
 */
 
-setdefaults()
+#define DAYS           * 24 * 60 * 60
+
+setdefaults(e)
+       register ENVELOPE *e;
 {
 {
-       QueueLA = 8;
-       QueueFactor = 10000;
-       RefuseLA = 12;
-       SpaceSub = ' ';
-       WkRecipFact = 1000;
-       WkClassFact = 1800;
-       WkTimeFact = 9000;
-       FileMode = 0644;
-       DefUid = 1;
-       DefGid = 1;
-       CheckpointInterval = 10;
+       SpaceSub = ' ';                         /* option B */
+       QueueLA = 8;                            /* option x */
+       RefuseLA = 12;                          /* option X */
+       WkRecipFact = 30000L;                   /* option y */
+       WkClassFact = 1800L;                    /* option z */
+       WkTimeFact = 90000L;                    /* option Z */
+       QueueFactor = WkRecipFact * 20;         /* option q */
+       FileMode = (getuid() != geteuid()) ? 0644 : 0600;
+                                               /* option F */
+       DefUid = 1;                             /* option u */
+       DefGid = 1;                             /* option g */
+       CheckpointInterval = 10;                /* option C */
+       MaxHopCount = 25;                       /* option h */
+       e->e_sendmode = SM_FORK;                /* option d */
+       e->e_errormode = EM_PRINT;              /* option e */
+       SevenBit = FALSE;                       /* option 7 */
+       MaxMciCache = 1;                        /* option k */
+       MciCacheTimeout = 300;                  /* option K */
+       LogLevel = 9;                           /* option L */
+       settimeouts(NULL);                      /* option r */
+       TimeOuts.to_q_return = 5 DAYS;          /* option T */
+       TimeOuts.to_q_warning = 0;              /* option T */
+       PrivacyFlags = 0;                       /* option p */
        setdefuser();
        setdefuser();
+       setupmaps();
+       setupmailers();
 }
 
 
 }
 
 
@@ -182,17 +217,140 @@ setdefaults()
 setdefuser()
 {
        struct passwd *defpwent;
 setdefuser()
 {
        struct passwd *defpwent;
+       static char defuserbuf[40];
 
 
-       if (DefUser != NULL)
-               free(DefUser);
+       DefUser = defuserbuf;
        if ((defpwent = getpwuid(DefUid)) != NULL)
        if ((defpwent = getpwuid(DefUid)) != NULL)
-               DefUser = newstr(defpwent->pw_name);
+               strcpy(defuserbuf, defpwent->pw_name);
        else
        else
-               DefUser = newstr("nobody");
+               strcpy(defuserbuf, "nobody");
+}
+\f/*
+**  HOST_MAP_INIT -- initialize host class structures
+*/
+
+bool
+host_map_init(map, args)
+       MAP *map;
+       char *args;
+{
+       register char *p = args;
+
+       for (;;)
+       {
+               while (isascii(*p) && isspace(*p))
+                       p++;
+               if (*p != '-')
+                       break;
+               switch (*++p)
+               {
+                 case 'a':
+                       map->map_app = ++p;
+                       break;
+               }
+               while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+                       p++;
+               if (*p != '\0')
+                       *p++ = '\0';
+       }
+       if (map->map_app != NULL)
+               map->map_app = newstr(map->map_app);
+       return TRUE;
 }
 }
+\f/*
+**  SETUPMAILERS -- initialize default mailers
+*/
 
 
+setupmailers()
+{
+       char buf[100];
 
 
-/*
+       strcpy(buf, "prog, P=/bin/sh, F=lsD, A=sh -c $u");
+       makemailer(buf);
+
+       strcpy(buf, "*file*, P=/dev/null, F=lsDFMPEu, A=FILE");
+       makemailer(buf);
+
+       strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE");
+       makemailer(buf);
+}
+\f/*
+**  SETUPMAPS -- set up map classes
+*/
+
+#define MAPDEF(name, ext, flags, parse, open, close, lookup, store) \
+       { \
+               extern bool parse __P((MAP *, char *)); \
+               extern bool open __P((MAP *, int)); \
+               extern void close __P((MAP *)); \
+               extern char *lookup __P((MAP *, char *, char **, int *)); \
+               extern void store __P((MAP *, char *, char *)); \
+               s = stab(name, ST_MAPCLASS, ST_ENTER); \
+               s->s_mapclass.map_cname = name; \
+               s->s_mapclass.map_ext = ext; \
+               s->s_mapclass.map_cflags = flags; \
+               s->s_mapclass.map_parse = parse; \
+               s->s_mapclass.map_open = open; \
+               s->s_mapclass.map_close = close; \
+               s->s_mapclass.map_lookup = lookup; \
+               s->s_mapclass.map_store = store; \
+       }
+
+setupmaps()
+{
+       register STAB *s;
+
+#ifdef NEWDB
+       MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
+               map_parseargs, hash_map_open, db_map_close,
+               db_map_lookup, db_map_store);
+       MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
+               map_parseargs, bt_map_open, db_map_close,
+               db_map_lookup, db_map_store);
+#endif
+
+#ifdef NDBM
+       MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE,
+               map_parseargs, ndbm_map_open, ndbm_map_close,
+               ndbm_map_lookup, ndbm_map_store);
+#endif
+
+#ifdef NIS
+       MAPDEF("nis", NULL, MCF_ALIASOK,
+               map_parseargs, nis_map_open, nis_map_close,
+               nis_map_lookup, nis_map_store);
+#endif
+
+       MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY,
+               map_parseargs, stab_map_open, stab_map_close,
+               stab_map_lookup, stab_map_store);
+
+       MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_ALIASONLY|MCF_REBUILDABLE,
+               map_parseargs, impl_map_open, impl_map_close,
+               impl_map_lookup, impl_map_store);
+
+       /* host DNS lookup */
+       MAPDEF("host", NULL, 0,
+               host_map_init, null_map_open, null_map_close,
+               host_map_lookup, null_map_store);
+
+       /* dequote map */
+       MAPDEF("dequote", NULL, 0,
+               dequote_init, null_map_open, null_map_close,
+               dequote_map, null_map_store);
+
+#if 0
+# ifdef USERDB
+       /* user database */
+       MAPDEF("udb", ".db", 0,
+               udb_map_parse, null_map_open, null_map_close,
+               udb_map_lookup, null_map_store);
+# endif
+#endif
+}
+
+#undef MAPDEF
+\f/*
 **  GETRUID -- get real user id (V7)
 */
 
 **  GETRUID -- get real user id (V7)
 */
 
@@ -216,8 +374,7 @@ getrgid()
        else
                return (getgid());
 }
        else
                return (getgid());
 }
-
-/*
+\f/*
 **  USERNAME -- return the user id of the logged in user.
 **
 **     Parameters:
 **  USERNAME -- return the user id of the logged in user.
 **
 **     Parameters:
@@ -246,26 +403,26 @@ username()
                myname = getlogin();
                if (myname == NULL || myname[0] == '\0')
                {
                myname = getlogin();
                if (myname == NULL || myname[0] == '\0')
                {
-
                        pw = getpwuid(getruid());
                        if (pw != NULL)
                                myname = newstr(pw->pw_name);
                }
                else
                {
                        pw = getpwuid(getruid());
                        if (pw != NULL)
                                myname = newstr(pw->pw_name);
                }
                else
                {
+                       uid_t uid = getuid();
 
                        myname = newstr(myname);
                        if ((pw = getpwnam(myname)) == NULL ||
 
                        myname = newstr(myname);
                        if ((pw = getpwnam(myname)) == NULL ||
-                             getuid() != pw->pw_uid)
+                             (uid != 0 && uid != pw->pw_uid))
                        {
                        {
-                               pw = getpwuid(getuid());
+                               pw = getpwuid(uid);
                                if (pw != NULL)
                                        myname = newstr(pw->pw_name);
                        }
                }
                if (myname == NULL || myname[0] == '\0')
                {
                                if (pw != NULL)
                                        myname = newstr(pw->pw_name);
                        }
                }
                if (myname == NULL || myname[0] == '\0')
                {
-                       syserr("Who are you?");
+                       syserr("554 Who are you?");
                        myname = "postmaster";
                }
        }
                        myname = "postmaster";
                }
        }
@@ -296,8 +453,6 @@ username()
 **             savemail
 */
 
 **             savemail
 */
 
-# include <sys/stat.h>
-
 char *
 ttypath()
 {
 char *
 ttypath()
 {
@@ -337,7 +492,7 @@ ttypath()
 **     forwarding or registration of users.
 **
 **     If the hosts are found to be incompatible, an error
 **     forwarding or registration of users.
 **
 **     If the hosts are found to be incompatible, an error
-**     message should be given using "usrerr" and FALSE should
+**     message should be given using "usrerr" and 0 should
 **     be returned.
 **
 **     'NoReturn' can be set to suppress the return-to-sender
 **     be returned.
 **
 **     'NoReturn' can be set to suppress the return-to-sender
@@ -347,16 +502,15 @@ ttypath()
 **             to -- the person being sent to.
 **
 **     Returns:
 **             to -- the person being sent to.
 **
 **     Returns:
-**             TRUE -- ok to send.
-**             FALSE -- not ok.
+**             an exit status
 **
 **     Side Effects:
 **             none (unless you include the usrerr stuff)
 */
 
 **
 **     Side Effects:
 **             none (unless you include the usrerr stuff)
 */
 
-bool
-checkcompat(to)
+checkcompat(to, e)
        register ADDRESS *to;
        register ADDRESS *to;
+       register ENVELOPE *e;
 {
 # ifdef lint
        if (to == NULL)
 {
 # ifdef lint
        if (to == NULL)
@@ -367,15 +521,15 @@ checkcompat(to)
        register STAB *s;
 
        s = stab("arpa", ST_MAILER, ST_FIND);
        register STAB *s;
 
        s = stab("arpa", ST_MAILER, ST_FIND);
-       if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
+       if (s != NULL && e->e_from.q_mailer != LocalMailer &&
            to->q_mailer == s->s_mailer)
        {
            to->q_mailer == s->s_mailer)
        {
-               usrerr("No ARPA mail through this machine: see your system administration");
+               usrerr("553 No ARPA mail through this machine: see your system administration");
                /* NoReturn = TRUE; to supress return copy */
                /* NoReturn = TRUE; to supress return copy */
-               return (FALSE);
+               return (EX_UNAVAILABLE);
        }
        }
-# endif EXAMPLE_CODE
-       return (TRUE);
+# endif /* EXAMPLE_CODE */
+       return (EX_OK);
 }
 \f/*
 **  HOLDSIGS -- arrange to hold all signals
 }
 \f/*
 **  HOLDSIGS -- arrange to hold all signals
@@ -426,61 +580,194 @@ rlsesigs()
 **             none.
 */
 
 **             none.
 */
 
-#ifndef sun
-
-getla()
-{
-       double avenrun[3];
-
-#ifdef notyet
-       if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
-               return (0);
-       return ((int) (avenrun[0] + 0.5));
-#else
-       return (1);
+/* try to guess what style of load average we have */
+#define LA_ZERO                1       /* always return load average as zero */
+#define LA_INT         2       /* read kmem for avenrun; interpret as int */
+#define LA_FLOAT       3       /* read kmem for avenrun; interpret as float */
+#define LA_SUBR                4       /* call getloadavg */
+
+#ifndef LA_TYPE
+#  if defined(sun) && !defined(BSD)
+#    define LA_TYPE            LA_INT
+#  endif
+#  if defined(mips) || defined(__alpha)
+     /* Ultrix or OSF/1 or RISC/os */
+#    define LA_TYPE            LA_INT
+#    define LA_AVENRUN         "avenrun"
+#  endif
+#  if defined(__hpux)
+#    define LA_TYPE            LA_FLOAT
+#    define LA_AVENRUN         "avenrun"
+#  endif
+
+/* now do the guesses based on general OS type */
+#  ifndef LA_TYPE
+#   if defined(SYSTEM5)
+#    define LA_TYPE            LA_INT
+#    define LA_AVENRUN         "avenrun"
+#   else
+#    if defined(BSD)
+#     define LA_TYPE           LA_SUBR
+#    else
+#     define LA_TYPE           LA_ZERO
+#    endif
+#   endif
+#  endif
 #endif
 #endif
-}
 
 
-#else /* sun */
+#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT)
 
 #include <nlist.h>
 
 
 #include <nlist.h>
 
+#ifndef LA_AVENRUN
+#define LA_AVENRUN     "_avenrun"
+#endif
+
+/* _PATH_UNIX should be defined in <paths.h> */
+#ifndef _PATH_UNIX
+#  if defined(__hpux)
+#    define _PATH_UNIX         "/hp-ux"
+#  endif
+#  if defined(mips) && !defined(ultrix)
+     /* powerful RISC/os */
+#    define _PATH_UNIX         "/unix"
+#  endif
+#  if defined(SYSTEM5)
+#    ifndef _PATH_UNIX
+#      define _PATH_UNIX       "/unix"
+#    endif
+#  endif
+#  ifndef _PATH_UNIX
+#    define _PATH_UNIX         "/vmunix"
+#  endif
+#endif
+
 struct nlist Nl[] =
 {
 struct nlist Nl[] =
 {
-       { "_avenrun" },
+       { LA_AVENRUN },
 #define        X_AVENRUN       0
        { 0 },
 };
 
 #define        X_AVENRUN       0
        { 0 },
 };
 
+#ifndef FSHIFT
+# if defined(unixpc)
+#  define FSHIFT       5
+# endif
 
 
-extern int la;
+# if defined(__alpha)
+#  define FSHIFT       10
+# endif
+
+# if (LA_TYPE == LA_INT)
+#  define FSHIFT       8
+# endif
+#endif
+
+#if (LA_TYPE == LA_INT) && !defined(FSCALE)
+#  define FSCALE       (1 << FSHIFT)
+#endif
 
 getla()
 {
        static int kmem = -1;
 
 getla()
 {
        static int kmem = -1;
+#if LA_TYPE == LA_INT
        long avenrun[3];
        long avenrun[3];
+#else
+       double avenrun[3];
+#endif
        extern off_t lseek();
        extern off_t lseek();
+       extern int errno;
 
        if (kmem < 0)
        {
                kmem = open("/dev/kmem", 0, 0);
                if (kmem < 0)
 
        if (kmem < 0)
        {
                kmem = open("/dev/kmem", 0, 0);
                if (kmem < 0)
+               {
+                       if (tTd(3, 1))
+                               printf("getla: open(/dev/kmem): %s\n",
+                                       errstring(errno));
                        return (-1);
                        return (-1);
-               (void) ioctl(kmem, (int) FIOCLEX, (char *) 0);
-               nlist("/vmunix", Nl);
-               if (Nl[0].n_type == 0)
+               }
+               (void) fcntl(kmem, F_SETFD, 1);
+               if (nlist(_PATH_UNIX, Nl) < 0)
+               {
+                       if (tTd(3, 1))
+                               printf("getla: nlist(%s): %s\n", _PATH_UNIX,
+                                       errstring(errno));
                        return (-1);
                        return (-1);
+               }
+               if (Nl[X_AVENRUN].n_value == 0)
+               {
+                       if (tTd(3, 1))
+                               printf("getla: nlist(%s, %s) ==> 0\n",
+                                       _PATH_UNIX, LA_AVENRUN);
+                       return (-1);
+               }
        }
        }
+       if (tTd(3, 20))
+               printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value);
        if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
            read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
        {
                /* thank you Ian */
        if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
            read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
        {
                /* thank you Ian */
+               if (tTd(3, 1))
+                       printf("getla: lseek or read: %s\n", errstring(errno));
                return (-1);
        }
                return (-1);
        }
+#if LA_TYPE == LA_INT
+       if (tTd(3, 5))
+       {
+               printf("getla: avenrun = %d", avenrun[0]);
+               if (tTd(3, 15))
+                       printf(", %d, %d", avenrun[1], avenrun[2]);
+               printf("\n");
+       }
+       if (tTd(3, 1))
+               printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
        return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
        return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
+#else
+       if (tTd(3, 5))
+       {
+               printf("getla: avenrun = %g", avenrun[0]);
+               if (tTd(3, 15))
+                       printf(", %g, %g", avenrun[1], avenrun[2]);
+               printf("\n");
+       }
+       if (tTd(3, 1))
+               printf("getla: %d\n", (int) (avenrun[0] +0.5));
+       return ((int) (avenrun[0] + 0.5));
+#endif
+}
+
+#else
+#if LA_TYPE == LA_SUBR
+
+getla()
+{
+       double avenrun[3];
+
+       if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
+       {
+               if (tTd(3, 1))
+                       perror("getla: getloadavg failed:");
+               return (-1);
+       }
+       if (tTd(3, 1))
+               printf("getla: %d\n", (int) (avenrun[0] +0.5));
+       return ((int) (avenrun[0] + 0.5));
+}
+
+#else
+
+getla()
+{
+       if (tTd(3, 1))
+               printf("getla: ZERO\n");
+       return (0);
 }
 
 }
 
-#endif /* sun */
+#endif
+#endif
 \f/*
 **  SHOULDQUEUE -- should this message be queued or sent?
 **
 \f/*
 **  SHOULDQUEUE -- should this message be queued or sent?
 **
@@ -488,6 +775,7 @@ getla()
 **
 **     Parameters:
 **             pri -- the priority of the message in question.
 **
 **     Parameters:
 **             pri -- the priority of the message in question.
+**             ctime -- the message creation time.
 **
 **     Returns:
 **             TRUE -- if this message should be queued up for the
 **
 **     Returns:
 **             TRUE -- if this message should be queued up for the
@@ -499,12 +787,41 @@ getla()
 */
 
 bool
 */
 
 bool
-shouldqueue(pri)
+shouldqueue(pri, ctime)
        long pri;
        long pri;
+       time_t ctime;
 {
 {
-       if (la < QueueLA)
+       if (CurrentLA < QueueLA)
                return (FALSE);
                return (FALSE);
-       return (pri > (QueueFactor / (la - QueueLA + 1)));
+       if (CurrentLA >= RefuseLA)
+               return (TRUE);
+       return (pri > (QueueFactor / (CurrentLA - QueueLA + 1)));
+}
+\f/*
+**  REFUSECONNECTIONS -- decide if connections should be refused
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             TRUE if incoming SMTP connections should be refused
+**                     (for now).
+**             FALSE if we should accept new work.
+**
+**     Side Effects:
+**             none.
+*/
+
+bool
+refuseconnections()
+{
+#ifdef XLA
+       if (!xla_smtp_ok())
+               return TRUE;
+#endif
+
+       /* this is probably too simplistic */
+       return (CurrentLA >= RefuseLA);
 }
 \f/*
 **  SETPROCTITLE -- set process title for ps
 }
 \f/*
 **  SETPROCTITLE -- set process title for ps
@@ -521,34 +838,75 @@ shouldqueue(pri)
 **             display the title.
 */
 
 **             display the title.
 */
 
+#ifdef SETPROCTITLE
+# ifdef __hpux
+#  include <sys/pstat.h>
+# endif
+# ifdef BSD4_4
+#  include <machine/vmparam.h>
+#  include <sys/exec.h>
+#  ifdef PS_STRINGS
+#   define SETPROC_STATIC static
+#  endif
+# endif
+# ifndef SETPROC_STATIC
+#  define SETPROC_STATIC
+# endif
+#endif
+
 /*VARARGS1*/
 /*VARARGS1*/
-setproctitle(fmt, a, b, c)
+#ifdef __STDC__
+setproctitle(char *fmt, ...)
+#else
+setproctitle(fmt, va_alist)
        char *fmt;
        char *fmt;
+       va_dcl
+#endif
 {
 # ifdef SETPROCTITLE
        register char *p;
        register int i;
 {
 # ifdef SETPROCTITLE
        register char *p;
        register int i;
+       SETPROC_STATIC char buf[MAXLINE];
+       VA_LOCAL_DECL
+#  ifdef __hpux
+       union pstun pst;
+#  endif
        extern char **Argv;
        extern char *LastArgv;
        extern char **Argv;
        extern char *LastArgv;
-       char buf[MAXLINE];
 
 
-       (void) sprintf(buf, fmt, a, b, c);
+       p = buf;
 
 
-       /* make ps print "(sendmail)" */
-       p = Argv[0];
-       *p++ = '-';
+       /* print sendmail: heading for grep */
+       (void) strcpy(p, "sendmail: ");
+       p += strlen(p);
+
+       /* print the argument string */
+       VA_START(fmt);
+       (void) vsprintf(p, fmt, ap);
+       VA_END;
 
        i = strlen(buf);
 
        i = strlen(buf);
-       if (i > LastArgv - p - 2)
+
+#  ifdef __hpux
+       pst.pst_command = buf;
+       pstat(PSTAT_SETCMD, pst, i, 0, 0);
+#  else
+#   ifdef PS_STRINGS
+       PS_STRINGS->ps_nargvstr = 1;
+       PS_STRINGS->ps_argvstr = buf;
+#   else
+       if (i > LastArgv - Argv[0] - 2)
        {
        {
-               i = LastArgv - p - 2;
+               i = LastArgv - Argv[0] - 2;
                buf[i] = '\0';
        }
                buf[i] = '\0';
        }
-       (void) strcpy(p, buf);
-       p += i;
+       (void) strcpy(Argv[0], buf);
+       p = &Argv[0][i];
        while (p < LastArgv)
                *p++ = ' ';
        while (p < LastArgv)
                *p++ = ' ';
-# endif SETPROCTITLE
+#   endif
+#  endif
+# endif /* SETPROCTITLE */
 }
 \f/*
 **  REAPCHILD -- pick up the body of my child, lest it become a zombie
 }
 \f/*
 **  REAPCHILD -- pick up the body of my child, lest it become a zombie
@@ -563,22 +921,469 @@ setproctitle(fmt, a, b, c)
 **             Picks up extant zombies.
 */
 
 **             Picks up extant zombies.
 */
 
-# ifdef VMUNIX
 # include <sys/wait.h>
 # include <sys/wait.h>
-# endif VMUNIX
 
 void
 reapchild()
 {
 
 void
 reapchild()
 {
+# ifdef WIFEXITED
+       auto int status;
+       int count;
+       int pid;
+
+       count = 0;
+       while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
+       {
+               if (count++ > 1000)
+               {
+                       syslog(LOG_ALERT, "reapchild: waitpid loop: pid=%d, status=%x",
+                               pid, status);
+                       break;
+               }
+       }
+# else
 # ifdef WNOHANG
        union wait status;
 
        while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0)
                continue;
 # ifdef WNOHANG
        union wait status;
 
        while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0)
                continue;
-# else WNOHANG
+# else /* WNOHANG */
        auto int status;
 
        auto int status;
 
-       while (wait((int *)&status) > 0)
+       while (wait(&status) > 0)
                continue;
                continue;
-# endif WNOHANG
+# endif /* WNOHANG */
+# endif
+# ifdef SYSTEM5
+       (void) signal(SIGCHLD, reapchild);
+# endif
+}
+\f/*
+**  UNSETENV -- remove a variable from the environment
+**
+**     Not needed on newer systems.
+**
+**     Parameters:
+**             name -- the string name of the environment variable to be
+**                     deleted from the current environment.
+**
+**     Returns:
+**             none.
+**
+**     Globals:
+**             environ -- a pointer to the current environment.
+**
+**     Side Effects:
+**             Modifies environ.
+*/
+
+#ifdef UNSETENV
+
+void
+unsetenv(name)
+       char *name;
+{
+       extern char **environ;
+       register char **pp;
+       int len = strlen(name);
+
+       for (pp = environ; *pp != NULL; pp++)
+       {
+               if (strncmp(name, *pp, len) == 0 &&
+                   ((*pp)[len] == '=' || (*pp)[len] == '\0'))
+                       break;
+       }
+
+       for (; *pp != NULL; pp++)
+               *pp = pp[1];
+}
+
+#endif /* UNSETENV */
+\f/*
+**  GETDTABLESIZE -- return number of file descriptors
+**
+**     Only on non-BSD systems
+**
+**     Parameters:
+**             none
+**
+**     Returns:
+**             size of file descriptor table
+**
+**     Side Effects:
+**             none
+*/
+
+#ifdef SYSTEM5
+
+int
+getdtablesize()
+{
+# ifdef _SC_OPEN_MAX
+       return sysconf(_SC_OPEN_MAX);
+# else
+       return NOFILE;
+# endif
+}
+
+#endif
+\f/*
+**  UNAME -- get the UUCP name of this system.
+*/
+
+#ifndef HASUNAME
+
+int
+uname(name)
+       struct utsname *name;
+{
+       FILE *file;
+       char *n;
+
+       name->nodename[0] = '\0';
+
+       /* try /etc/whoami -- one line with the node name */
+       if ((file = fopen("/etc/whoami", "r")) != NULL)
+       {
+               (void) fgets(name->nodename, NODE_LENGTH + 1, file);
+               (void) fclose(file);
+               n = strchr(name->nodename, '\n');
+               if (n != NULL)
+                       *n = '\0';
+               if (name->nodename[0] != '\0')
+                       return (0);
+       }
+
+       /* try /usr/include/whoami.h -- has a #define somewhere */
+       if ((file = fopen("/usr/include/whoami.h", "r")) != NULL)
+       {
+               char buf[MAXLINE];
+
+               while (fgets(buf, MAXLINE, file) != NULL)
+                       if (sscanf(buf, "#define sysname \"%*[^\"]\"",
+                                       NODE_LENGTH, name->nodename) > 0)
+                               break;
+               (void) fclose(file);
+               if (name->nodename[0] != '\0')
+                       return (0);
+       }
+
+#ifdef TRUST_POPEN
+       /*
+       **  Popen is known to have security holes.
+       */
+
+       /* try uuname -l to return local name */
+       if ((file = popen("uuname -l", "r")) != NULL)
+       {
+               (void) fgets(name, NODE_LENGTH + 1, file);
+               (void) pclose(file);
+               n = strchr(name, '\n');
+               if (n != NULL)
+                       *n = '\0';
+               if (name->nodename[0] != '\0')
+                       return (0);
+       }
+#endif
+       
+       return (-1);
+}
+#endif /* HASUNAME */
+\f/*
+**  INITGROUPS -- initialize groups
+**
+**     Stub implementation for System V style systems
+*/
+
+#ifndef HASINITGROUPS
+# if !defined(SYSTEM5) || defined(__hpux)
+#  define HASINITGROUPS
+# endif
+#endif
+
+#ifndef HASINITGROUPS
+
+initgroups(name, basegid)
+       char *name;
+       int basegid;
+{
+       return 0;
+}
+
+#endif
+\f/*
+**  SETSID -- set session id (for non-POSIX systems)
+*/
+
+#ifndef HASSETSID
+
+setsid()
+{
+# ifdef SYSTEM5
+       setpgrp();
+# endif
+}
+
+#endif
+\f/*
+**  ENOUGHSPACE -- check to see if there is enough free space on the queue fs
+**
+**     Only implemented if you have statfs.
+**
+**     Parameters:
+**             msize -- the size to check against.  If zero, we don't yet
+**                     know how big the message will be, so just check for
+**                     a "reasonable" amount.
+**
+**     Returns:
+**             TRUE if there is enough space.
+**             FALSE otherwise.
+*/
+
+#ifndef HASSTATFS
+# if defined(BSD4_4) || defined(__osf__)
+#  define HASSTATFS
+# endif
+#endif
+
+#ifdef HASSTATFS
+# undef HASUSTAT
+#endif
+
+#if defined(HASUSTAT)
+# include <ustat.h>
+#endif
+
+#ifdef HASSTATFS
+# if defined(sgi) || defined(apollo)
+#  include <sys/statfs.h>
+# else
+#  if (defined(sun) && !defined(BSD)) || defined(__hpux)
+#   include <sys/vfs.h>
+#  else
+#   include <sys/mount.h>
+#  endif
+# endif
+#endif
+
+bool
+enoughspace(msize)
+       long msize;
+{
+#if defined(HASSTATFS) || defined(HASUSTAT)
+# if defined(HASUSTAT)
+       struct ustat fs;
+       struct stat statbuf;
+#  define FSBLOCKSIZE  DEV_BSIZE
+#  define f_bavail     f_tfree
+# else
+#  if defined(ultrix)
+       struct fs_data fs;
+#   define f_bavail    fd_bfreen
+#   define FSBLOCKSIZE fs.fd_bsize
+#  else
+       struct statfs fs;
+#   define FSBLOCKSIZE fs.f_bsize
+#  endif
+# endif
+       extern int errno;
+
+       if (MinBlocksFree <= 0 && msize <= 0)
+       {
+               if (tTd(4, 80))
+                       printf("enoughspace: no threshold\n");
+               return TRUE;
+       }
+
+# if defined(HASUSTAT)
+       if (stat(QueueDir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
+# else
+#  if defined(sgi) || defined(apollo)
+       if (statfs(QueueDir, &fs, sizeof fs, 0) == 0)
+#  else
+#   if defined(ultrix)
+       if (statfs(QueueDir, &fs) > 0)
+#   else
+       if (statfs(QueueDir, &fs) == 0)
+#   endif
+#  endif
+# endif
+       {
+               if (tTd(4, 80))
+                       printf("enoughspace: bavail=%ld, need=%ld\n",
+                               fs.f_bavail, msize);
+
+               /* convert msize to block count */
+               msize = msize / FSBLOCKSIZE + 1;
+               if (MinBlocksFree >= 0)
+                       msize += MinBlocksFree;
+
+               if (fs.f_bavail < msize)
+               {
+#ifdef LOG
+                       if (LogLevel > 0)
+                               syslog(LOG_ALERT, "%s: low on space (have %ld, need %ld)",
+                                       QueueDir, fs.f_bavail, msize);
+#endif
+                       return FALSE;
+               }
+       }
+       else if (tTd(4, 80))
+               printf("enoughspace failure: min=%ld, need=%ld: %s\n",
+                       MinBlocksFree, msize, errstring(errno));
+#endif
+       return TRUE;
+}
+\f/*
+**  TRANSIENTERROR -- tell if an error code indicates a transient failure
+**
+**     This looks at an errno value and tells if this is likely to
+**     go away if retried later.
+**
+**     Parameters:
+**             err -- the errno code to classify.
+**
+**     Returns:
+**             TRUE if this is probably transient.
+**             FALSE otherwise.
+*/
+
+bool
+transienterror(err)
+       int err;
+{
+       switch (err)
+       {
+         case EIO:                     /* I/O error */
+         case ENXIO:                   /* Device not configured */
+         case EAGAIN:                  /* Resource temporarily unavailable */
+         case ENOMEM:                  /* Cannot allocate memory */
+         case ENODEV:                  /* Operation not supported by device */
+         case ENFILE:                  /* Too many open files in system */
+         case EMFILE:                  /* Too many open files */
+         case ENOSPC:                  /* No space left on device */
+#ifdef ETIMEDOUT
+         case ETIMEDOUT:               /* Connection timed out */
+#endif
+#ifdef ESTALE
+         case ESTALE:                  /* Stale NFS file handle */
+#endif
+#ifdef ENETDOWN
+         case ENETDOWN:                /* Network is down */
+#endif
+#ifdef ENETUNREACH
+         case ENETUNREACH:             /* Network is unreachable */
+#endif
+#ifdef ENETRESET
+         case ENETRESET:               /* Network dropped connection on reset */
+#endif
+#ifdef ECONNABORTED
+         case ECONNABORTED:            /* Software caused connection abort */
+#endif
+#ifdef ECONNRESET
+         case ECONNRESET:              /* Connection reset by peer */
+#endif
+#ifdef ENOBUFS
+         case ENOBUFS:                 /* No buffer space available */
+#endif
+#ifdef ESHUTDOWN
+         case ESHUTDOWN:               /* Can't send after socket shutdown */
+#endif
+#ifdef ECONNREFUSED
+         case ECONNREFUSED:            /* Connection refused */
+#endif
+#ifdef EHOSTDOWN
+         case EHOSTDOWN:               /* Host is down */
+#endif
+#ifdef EHOSTUNREACH
+         case EHOSTUNREACH:            /* No route to host */
+#endif
+#ifdef EDQUOT
+         case EDQUOT:                  /* Disc quota exceeded */
+#endif
+#ifdef EPROCLIM
+         case EPROCLIM:                /* Too many processes */
+#endif
+#ifdef EUSERS
+         case EUSERS:                  /* Too many users */
+#endif
+#ifdef EDEADLK
+         case EDEADLK:                 /* Resource deadlock avoided */
+#endif
+#ifdef EISCONN
+         case EISCONN:                 /* Socket already connected */
+#endif
+#ifdef EINPROGRESS
+         case EINPROGRESS:             /* Operation now in progress */
+#endif
+#ifdef EALREADY
+         case EALREADY:                /* Operation already in progress */
+#endif
+#ifdef EADDRINUSE
+         case EADDRINUSE:              /* Address already in use */
+#endif
+#ifdef EADDRNOTAVAIL
+         case EADDRNOTAVAIL:           /* Can't assign requested address */
+#endif
+#ifdef ENOSR
+         case ENOSR:                   /* Out of streams resources */
+#endif
+               return TRUE;
+       }
+
+       /* nope, must be permanent */
+       return FALSE;
+}
+\f/*
+**  LOCKFILE -- lock a file using flock or (shudder) lockf
+**
+**     Parameters:
+**             fd -- the file descriptor of the file.
+**             filename -- the file name (for error messages).
+**             type -- type of the lock.  Bits can be:
+**                     LOCK_EX -- exclusive lock.
+**                     LOCK_NB -- non-blocking.
+**
+**     Returns:
+**             TRUE if the lock was acquired.
+**             FALSE otherwise.
+*/
+
+bool
+lockfile(fd, filename, type)
+       int fd;
+       char *filename;
+       int type;
+{
+# ifdef LOCKF
+       int action;
+       struct flock lfd;
+
+       if (bitset(LOCK_UN, type))
+               lfd.l_type = F_UNLCK;
+       else if (bitset(LOCK_EX, type))
+               lfd.l_type = F_WRLCK;
+       else
+               lfd.l_type = F_RDLCK;
+
+       if (bitset(LOCK_NB, type))
+               action = F_SETLK;
+       else
+               action = F_SETLKW;
+
+       lfd.l_whence = lfd.l_start = lfd.l_len = 0;
+
+       if (fcntl(fd, action, &lfd) >= 0)
+               return TRUE;
+
+       if (!bitset(LOCK_NB, type) || (errno != EACCES && errno != EAGAIN))
+               syserr("cannot lockf(%s, %o)", filename, type);
+# else
+       if (flock(fd, type) >= 0)
+               return TRUE;
+
+       if (!bitset(LOCK_NB, type) || errno != EWOULDBLOCK)
+               syserr("cannot flock(%s, %o)", filename, type);
+# endif
+       return FALSE;
 }
 }
index caf66fe..57e27b0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)conf.h      5.17 (Berkeley) 6/1/90
+ *     @(#)conf.h      8.1 (Berkeley) 6/7/93
  */
 
 /*
 **  CONF.H -- All user-configurable parameters for sendmail
 */
 
  */
 
 /*
 **  CONF.H -- All user-configurable parameters for sendmail
 */
 
+# include <sys/param.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+
 /*
 **  Table sizes, etc....
 **     There shouldn't be much need to change these....
 */
 
 /*
 **  Table sizes, etc....
 **     There shouldn't be much need to change these....
 */
 
-# define MAXLINE       1024            /* max line length */
+# define MAXLINE       2048            /* max line length */
 # define MAXNAME       256             /* max length of a name */
 # define MAXNAME       256             /* max length of a name */
-# define MAXFIELD      4096            /* max total length of a hdr field */
 # define MAXPV         40              /* max # of parms to mailers */
 # define MAXPV         40              /* max # of parms to mailers */
-# define MAXHOP                17              /* max value of HopCount */
-# define MAXATOM       100             /* max atoms per address */
+# define MAXATOM       200             /* max atoms per address */
 # define MAXMAILERS    25              /* maximum mailers known to system */
 # define MAXMAILERS    25              /* maximum mailers known to system */
-# define MAXRWSETS     30              /* max # of sets of rewriting rules */
+# define MAXRWSETS     100             /* max # of sets of rewriting rules */
 # define MAXPRIORITIES 25              /* max values for Precedence: field */
 # define MAXPRIORITIES 25              /* max values for Precedence: field */
-# define MAXTRUST      30              /* maximum number of trusted users */
-# define MAXUSERENVIRON        40              /* max # of items in user environ */
-# define QUEUESIZE     600             /* max # of jobs per queue run */
-# define MAXMXHOSTS    10              /* max # of MX records */
+# define MAXMXHOSTS    20              /* max # of MX records */
+# define SMTPLINELIM   990             /* maximum SMTP line length */
+# define MAXKEY                128             /* maximum size of a database key */
+# define MEMCHUNKSIZE  1024            /* chunk size for memory allocation */
+# define MAXUSERENVIRON        100             /* max envars saved, must be >= 3 */
+# define MAXIPADDR     16              /* max # of IP addrs for this host */
+# define MAXALIASDB    12              /* max # of alias databases */
+# define PSBUFSIZE     (MAXLINE + MAXATOM)     /* size of prescan buffer */
+
+# ifndef QUEUESIZE
+# define QUEUESIZE     1000            /* max # of jobs per queue run */
+# endif
 
 /*
 **  Compilation options.
 
 /*
 **  Compilation options.
 **     #define these if they are available; comment them out otherwise.
 */
 
 **     #define these if they are available; comment them out otherwise.
 */
 
-/* # define DBM                1       /* use DBM library (requires -ldbm) */
-/* # define NDBM       1       /* new DBM library available (requires DBM) */
 # define LOG           1       /* enable logging */
 # define LOG           1       /* enable logging */
-# define SMTP          1       /* enable user and server SMTP */
-# define QUEUE         1       /* enable queueing */
 # define UGLYUUCP      1       /* output ugly UUCP From lines */
 # define UGLYUUCP      1       /* output ugly UUCP From lines */
-# define DAEMON                1       /* include the daemon (requires IPC & SMTP) */
+# define NETINET       1       /* include internet support */
 # define SETPROCTITLE  1       /* munge argv to display current status */
 # define NAMED_BIND    1       /* use Berkeley Internet Domain Server */
 # define SETPROCTITLE  1       /* munge argv to display current status */
 # define NAMED_BIND    1       /* use Berkeley Internet Domain Server */
+# define MATCHGECOS    1       /* match user names from gecos field */
+
+# ifdef NEWDB
+# define USERDB                1       /* look in user database (requires NEWDB) */
+# endif
+
+/*
+**  Operating system configuration.
+**
+**     Unless you are porting to a new OS, you shouldn't have to
+**     change these.
+*/
+
+/* HP-UX -- tested for 8.07 */
+# ifdef __hpux
+# define SYSTEM5       1
+# define UNSETENV      1       /* need unsetenv(3) support */
+# endif
+
+/* IBM AIX 3.x -- actually tested for 3.2.3 */
+# ifdef _AIX3
+# define LOCKF         1       /* use System V lockf instead of flock */
+# define FORK          fork    /* no vfork primitive available */
+# define UNSETENV      1       /* need unsetenv(3) support */
+# endif
+
+/* general System V defines */
+# ifdef SYSTEM5
+# define LOCKF         1       /* use System V lockf instead of flock */
+# define SYS5TZ                1       /* use System V style timezones */
+# define HASUNAME      1       /* use System V uname system call */
+# endif
+
+#if defined(sun) && !defined(BSD)
+# define UNSETENV      1       /* need unsetenv(3) support */
+
+# ifdef SOLARIS
+#  define LOCKF                1       /* use System V lockf instead of flock */
+#  define UNSETENV     1       /* need unsetenv(3) support */
+#  define HASUSTAT     1       /* has the ustat(2) syscall */
+# else
+#  define HASSTATFS    1       /* has the statfs(2) syscall */
+#  include <vfork.h>
+# endif
+
+#endif
+
+#ifdef ultrix
+# define HASSTATFS     1       /* has the statfs(2) syscall */
+#endif
+
+#ifdef _POSIX_VERSION
+# define HASSETSID     1       /* has setsid(2) call */
+#endif
+
+#ifdef NeXT
+# define       sleep   sleepX
+#endif
+
+#ifdef BSD4_4
+# include <sys/cdefs.h>
+#endif
+
+/*
+**  Due to a "feature" in some operating systems such as Ultrix 4.3 and
+**  HPUX 8.0, if you receive a "No route to host" message (ICMP message
+**  ICMP_UNREACH_HOST) on _any_ connection, all connections to that host
+**  are closed.  Some firewalls return this error if you try to connect
+**  to the IDENT port (113), so you can't receive email from these hosts
+**  on these systems.  The firewall really should use a more specific
+**  message such as ICMP_UNREACH_PROTOCOL or _PORT or _NET_PROHIB.
+*/
+
+#if !defined(ultrix) && !defined(__hpux)
+# define IDENTPROTO    1       /* use IDENT proto (RFC 1413) */
+#endif
+
+/*
+**  Remaining definitions should never have to be changed.  They are
+**  primarily to provide back compatibility for older systems -- for
+**  example, it includes some POSIX compatibility definitions
+*/
+
+/* System 5 compatibility */
+#ifndef S_ISREG
+#define S_ISREG(foo)   ((foo & S_IFREG) == S_IFREG)
+#endif
+#ifndef S_IWGRP
+#define S_IWGRP                020
+#endif
+#ifndef S_IWOTH
+#define S_IWOTH                002
+#endif
+
+/*
+**  Older systems don't have this error code -- it should be in
+**  /usr/include/sysexits.h.
+*/
+
+# ifndef EX_CONFIG
+# define EX_CONFIG     78      /* configuration error */
+# endif
+
+#ifndef __P
+# include "cdefs.h"
+#endif
+
+/*
+**  Do some required dependencies
+*/
+
+#if defined(NETINET) || defined(NETISO)
+# define SMTP          1       /* enable user and server SMTP */
+# define QUEUE         1       /* enable queueing */
+# define DAEMON                1       /* include the daemon (requires IPC & SMTP) */
+#endif
+
+
+/*
+**  Arrange to use either varargs or stdargs
+*/
+
+# ifdef __STDC__
+
+# include <stdarg.h>
+
+# define VA_LOCAL_DECL va_list ap;
+# define VA_START(f)   va_start(ap, f)
+# define VA_END                va_end(ap)
+
+# else
+
+# include <varargs.h>
+
+# define VA_LOCAL_DECL va_list ap;
+# define VA_START(f)   va_start(ap)
+# define VA_END                va_end(ap)
+
+# endif
+
+#ifdef HASUNAME
+# include <sys/utsname.h>
+# ifdef newstr
+#  undef newstr
+# endif
+#else /* ! HASUNAME */
+# define NODE_LENGTH 32
+struct utsname
+{
+       char nodename[NODE_LENGTH+1];
+};
+#endif /* HASUNAME */
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+
+#if !defined(SIGCHLD) && defined(SIGCLD)
+# define SIGCHLD       SIGCLD
+#endif
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO   0
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO  1
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO  2
+#endif
+
+#ifdef LOCKF
+#define LOCK_SH                0x01    /* shared lock */
+#define LOCK_EX                0x02    /* exclusive lock */
+#define LOCK_NB                0x04    /* non-blocking lock */
+#define LOCK_UN                0x08    /* unlock */
+
+#else
+
+# include <sys/file.h>
+
+#endif
+
+/*
+**  Size of tobuf (deliver.c)
+**     Tweak this to match your syslog implementation.  It will have to
+**     allow for the extra information printed.
+*/
+
+#ifndef TOBUFSIZE
+# define TOBUFSIZE (1024 - 256)
+#endif
 
 
-       /*
-        * Use query type of ANY if possible (NO_WILDCARD_MX), which will
-        * find types CNAME, A, and MX, and will cause all existing records
-        * to be cached by our local server.  If there is (might be) a
-        * wildcard MX record in the local domain or its parents that are
-        * searched, we can't use ANY; it would cause fully-qualified names
-        * to match as names in a local domain.
-        */
-/* # define NO_WILDCARD_MX     1 */
+/* fork routine -- set above using #ifdef _osname_ or in Makefile */
+# ifndef FORK
+# define FORK          vfork           /* function to call to fork mailer */
+# endif
index 499421b..5cb5e49 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)convtime.c 5.4 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)convtime.c 8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 # include <ctype.h>
 #endif /* not lint */
 
 # include <ctype.h>
@@ -53,6 +53,7 @@ static char sccsid[] = "@(#)convtime.c        5.4 (Berkeley) 6/1/90";
 **
 **     Parameters:
 **             p -- pointer to ascii time.
 **
 **     Parameters:
 **             p -- pointer to ascii time.
+**             units -- default units if none specified.
 **
 **     Returns:
 **             time in seconds.
 **
 **     Returns:
 **             time in seconds.
@@ -62,8 +63,9 @@ static char sccsid[] = "@(#)convtime.c        5.4 (Berkeley) 6/1/90";
 */
 
 time_t
 */
 
 time_t
-convtime(p)
+convtime(p, units)
        char *p;
        char *p;
+       char units;
 {
        register time_t t, r;
        register char c;
 {
        register time_t t, r;
        register char c;
@@ -72,10 +74,13 @@ convtime(p)
        while (*p != '\0')
        {
                t = 0;
        while (*p != '\0')
        {
                t = 0;
-               while (isdigit(c = *p++))
+               while ((c = *p++) != '\0' && isascii(c) && isdigit(c))
                        t = t * 10 + (c - '0');
                if (c == '\0')
                        t = t * 10 + (c - '0');
                if (c == '\0')
+               {
+                       c = units;
                        p--;
                        p--;
+               }
                switch (c)
                {
                  case 'w':             /* weeks */
                switch (c)
                {
                  case 'w':             /* weeks */
index dd1b4bf..becb2b8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #include <errno.h>
  */
 
 #include <errno.h>
+#include <signal.h>
 #include "sendmail.h"
 
 #ifndef lint
 #ifdef DAEMON
 #include "sendmail.h"
 
 #ifndef lint
 #ifdef DAEMON
-static char sccsid[] = "@(#)daemon.c   5.37 (Berkeley) 3/2/91 (with daemon mode)";
+static char sccsid[] = "@(#)daemon.c   8.1 (Berkeley) 6/7/93 (with daemon mode)";
 #else
 #else
-static char sccsid[] = "@(#)daemon.c   5.37 (Berkeley) 3/2/91 (without daemon mode)";
+static char sccsid[] = "@(#)daemon.c   8.1 (Berkeley) 6/7/93 (without daemon mode)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
-int la;        /* load average */
-
 #ifdef DAEMON
 
 # include <netdb.h>
 #ifdef DAEMON
 
 # include <netdb.h>
-# include <sys/signal.h>
 # include <sys/wait.h>
 # include <sys/time.h>
 # include <sys/wait.h>
 # include <sys/time.h>
-# include <sys/resource.h>
+
+#ifdef NAMED_BIND
+# include <arpa/nameser.h>
+# include <resolv.h>
+#endif
 
 /*
 **  DAEMON.C -- routines to use when running as a daemon.
 
 /*
 **  DAEMON.C -- routines to use when running as a daemon.
@@ -73,15 +75,14 @@ int la;     /* load average */
 **             etc., to avoid having extra file descriptors during
 **             the queue run and to avoid confusing the network
 **             code (if it cares).
 **             etc., to avoid having extra file descriptors during
 **             the queue run and to avoid confusing the network
 **             code (if it cares).
-**     makeconnection(host, port, outfile, infile)
+**     makeconnection(host, port, outfile, infile, usesecureport)
 **             Make a connection to the named host on the given
 **             port.  Set *outfile and *infile to the files
 **             appropriate for communication.  Returns zero on
 **             success, else an exit status describing the
 **             error.
 **             Make a connection to the named host on the given
 **             port.  Set *outfile and *infile to the files
 **             appropriate for communication.  Returns zero on
 **             success, else an exit status describing the
 **             error.
-**     maphostname(hbuf, hbufsize)
-**             Convert the entry in hbuf into a canonical form.  It
-**             may not be larger than hbufsize.
+**     host_map_lookup(map, hbuf, avp, pstat)
+**             Convert the entry in hbuf into a canonical form.
 */
 \f/*
 **  GETREQUESTS -- open mail IPC port and get requests.
 */
 \f/*
 **  GETREQUESTS -- open mail IPC port and get requests.
@@ -101,41 +102,47 @@ int la;   /* load average */
 **             to the communication channel.
 */
 
 **             to the communication channel.
 */
 
-struct sockaddr_in     SendmailAddress;/* internet address of sendmail */
-
-int    DaemonSocket    = -1;           /* fd describing socket */
-char   *NetName;                       /* name of home (local?) network */
+int            DaemonSocket    = -1;           /* fd describing socket */
+SOCKADDR       DaemonAddr;                     /* socket for incoming */
+int            ListenQueueSize = 10;           /* size of listen queue */
 
 getrequests()
 {
        int t;
        register struct servent *sp;
        int on = 1;
 
 getrequests()
 {
        int t;
        register struct servent *sp;
        int on = 1;
+       bool refusingconnections = TRUE;
+       FILE *pidf;
        extern void reapchild();
 
        /*
        **  Set up the address for the mailer.
        */
 
        extern void reapchild();
 
        /*
        **  Set up the address for the mailer.
        */
 
-       sp = getservbyname("smtp", "tcp");
-       if (sp == NULL)
+       if (DaemonAddr.sin.sin_family == 0)
+               DaemonAddr.sin.sin_family = AF_INET;
+       if (DaemonAddr.sin.sin_addr.s_addr == 0)
+               DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY;
+       if (DaemonAddr.sin.sin_port == 0)
        {
        {
-               syserr("server \"smtp\" unknown");
-               goto severe;
+               sp = getservbyname("smtp", "tcp");
+               if (sp == NULL)
+               {
+                       syserr("554 service \"smtp\" unknown");
+                       goto severe;
+               }
+               DaemonAddr.sin.sin_port = sp->s_port;
        }
        }
-       SendmailAddress.sin_family = AF_INET;
-       SendmailAddress.sin_addr.s_addr = INADDR_ANY;
-       SendmailAddress.sin_port = sp->s_port;
 
        /*
        **  Try to actually open the connection.
        */
 
        if (tTd(15, 1))
 
        /*
        **  Try to actually open the connection.
        */
 
        if (tTd(15, 1))
-               printf("getrequests: port 0x%x\n", SendmailAddress.sin_port);
+               printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port);
 
        /* get a socket for the SMTP connection */
 
        /* get a socket for the SMTP connection */
-       DaemonSocket = socket(AF_INET, SOCK_STREAM, 0);
+       DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0);
        if (DaemonSocket < 0)
        {
                /* probably another daemon already */
        if (DaemonSocket < 0)
        {
                /* probably another daemon already */
@@ -143,34 +150,55 @@ getrequests()
          severe:
 # ifdef LOG
                if (LogLevel > 0)
          severe:
 # ifdef LOG
                if (LogLevel > 0)
-                       syslog(LOG_ALERT, "cannot get connection");
-# endif LOG
+                       syslog(LOG_ALERT, "problem creating SMTP socket");
+# endif /* LOG */
                finis();
        }
 
        /* turn on network debugging? */
                finis();
        }
 
        /* turn on network debugging? */
-       if (tTd(15, 15))
+       if (tTd(15, 101))
                (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);
 
        (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);
        (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on);
 
                (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);
 
        (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);
        (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on);
 
-       if (bind(DaemonSocket,
-           (struct sockaddr *)&SendmailAddress, sizeof SendmailAddress) < 0)
+       switch (DaemonAddr.sa.sa_family)
        {
        {
-               syserr("getrequests: cannot bind");
-               (void) close(DaemonSocket);
-               goto severe;
+# ifdef NETINET
+         case AF_INET:
+               t = sizeof DaemonAddr.sin;
+               break;
+# endif
+
+# ifdef NETISO
+         case AF_ISO:
+               t = sizeof DaemonAddr.siso;
+               break;
+# endif
+
+         default:
+               t = sizeof DaemonAddr;
+               break;
        }
        }
-       if (listen(DaemonSocket, 10) < 0)
+
+       if (bind(DaemonSocket, &DaemonAddr.sa, t) < 0)
        {
        {
-               syserr("getrequests: cannot listen");
+               syserr("getrequests: cannot bind");
                (void) close(DaemonSocket);
                goto severe;
        }
 
        (void) signal(SIGCHLD, reapchild);
 
                (void) close(DaemonSocket);
                goto severe;
        }
 
        (void) signal(SIGCHLD, reapchild);
 
+       /* write the pid to the log file for posterity */
+       pidf = fopen(PidFile, "w");
+       if (pidf != NULL)
+       {
+               fprintf(pidf, "%d\n", getpid());
+               fclose(pidf);
+       }
+
+
        if (tTd(15, 1))
                printf("getrequests: %d\n", DaemonSocket);
 
        if (tTd(15, 1))
                printf("getrequests: %d\n", DaemonSocket);
 
@@ -178,17 +206,38 @@ getrequests()
        {
                register int pid;
                auto int lotherend;
        {
                register int pid;
                auto int lotherend;
-               extern int RefuseLA;
+               extern bool refuseconnections();
 
                /* see if we are rejecting connections */
 
                /* see if we are rejecting connections */
-               while ((la = getla()) > RefuseLA)
+               CurrentLA = getla();
+               if (refuseconnections())
                {
                {
-                       setproctitle("rejecting connections: load average: %.2f", (double)la);
+                       if (!refusingconnections)
+                       {
+                               /* don't queue so peer will fail quickly */
+                               (void) listen(DaemonSocket, 0);
+                               refusingconnections = TRUE;
+                       }
+                       setproctitle("rejecting connections: load average: %d",
+                               CurrentLA);
                        sleep(5);
                        sleep(5);
+                       continue;
+               }
+
+               if (refusingconnections)
+               {
+                       /* start listening again */
+                       if (listen(DaemonSocket, ListenQueueSize) < 0)
+                       {
+                               syserr("getrequests: cannot listen");
+                               (void) close(DaemonSocket);
+                               goto severe;
+                       }
+                       setproctitle("accepting connections");
+                       refusingconnections = FALSE;
                }
 
                /* wait for a connection */
                }
 
                /* wait for a connection */
-               setproctitle("accepting connections");
                do
                {
                        errno = 0;
                do
                {
                        errno = 0;
@@ -221,9 +270,7 @@ getrequests()
 
                if (pid == 0)
                {
 
                if (pid == 0)
                {
-                       extern struct hostent *gethostbyaddr();
-                       register struct hostent *hp;
-                       char buf[MAXNAME];
+                       extern char *hostnamebyanyaddr();
 
                        /*
                        **  CHILD -- return to caller.
 
                        /*
                        **  CHILD -- return to caller.
@@ -232,33 +279,35 @@ getrequests()
                        */
 
                        (void) signal(SIGCHLD, SIG_DFL);
                        */
 
                        (void) signal(SIGCHLD, SIG_DFL);
+                       OpMode = MD_SMTP;
 
                        /* determine host name */
 
                        /* determine host name */
-                       hp = gethostbyaddr((char *) &RealHostAddr.sin_addr, sizeof RealHostAddr.sin_addr, AF_INET);
-                       if (hp != NULL)
-                               (void) strcpy(buf, hp->h_name);
-                       else
-                       {
-                               extern char *inet_ntoa();
+                       RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
 
 
-                               /* produce a dotted quad */
-                               (void) sprintf(buf, "[%s]",
-                                       inet_ntoa(RealHostAddr.sin_addr));
+#ifdef LOG
+                       if (LogLevel > 10)
+                       {
+                               /* log connection information */
+                               syslog(LOG_INFO, "connect from %s (%s)",
+                                       RealHostName, anynet_ntoa(&RealHostAddr));
                        }
                        }
-
-                       /* should we check for illegal connection here? XXX */
-
-                       RealHostName = newstr(buf);
+#endif
 
                        (void) close(DaemonSocket);
                        InChannel = fdopen(t, "r");
                        OutChannel = fdopen(dup(t), "w");
 
                        (void) close(DaemonSocket);
                        InChannel = fdopen(t, "r");
                        OutChannel = fdopen(dup(t), "w");
+
+                       /* should we check for illegal connection here? XXX */
+#ifdef XLA
+                       if (!xla_host_ok(RealHostName))
+                       {
+                               message("421 Too many SMTP sessions for this host");
+                               exit(0);
+                       }
+#endif
+
                        if (tTd(15, 2))
                                printf("getreq: returning\n");
                        if (tTd(15, 2))
                                printf("getreq: returning\n");
-# ifdef LOG
-                       if (LogLevel > 11)
-                               syslog(LOG_DEBUG, "connected, pid=%d", getpid());
-# endif LOG
                        return;
                }
 
                        return;
                }
 
@@ -287,14 +336,156 @@ clrdaemon()
        DaemonSocket = -1;
 }
 \f/*
        DaemonSocket = -1;
 }
 \f/*
+**  SETDAEMONOPTIONS -- set options for running the daemon
+**
+**     Parameters:
+**             p -- the options line.
+**
+**     Returns:
+**             none.
+*/
+
+setdaemonoptions(p)
+       register char *p;
+{
+       if (DaemonAddr.sa.sa_family == AF_UNSPEC)
+               DaemonAddr.sa.sa_family = AF_INET;
+
+       while (p != NULL)
+       {
+               register char *f;
+               register char *v;
+
+               while (isascii(*p) && isspace(*p))
+                       p++;
+               if (*p == '\0')
+                       break;
+               f = p;
+               p = strchr(p, ',');
+               if (p != NULL)
+                       *p++ = '\0';
+               v = strchr(f, '=');
+               if (v == NULL)
+                       continue;
+               while (isascii(*++v) && isspace(*v))
+                       continue;
+
+               switch (*f)
+               {
+                 case 'F':             /* address family */
+                       if (isascii(*v) && isdigit(*v))
+                               DaemonAddr.sa.sa_family = atoi(v);
+#ifdef NETINET
+                       else if (strcasecmp(v, "inet") == 0)
+                               DaemonAddr.sa.sa_family = AF_INET;
+#endif
+#ifdef NETISO
+                       else if (strcasecmp(v, "iso") == 0)
+                               DaemonAddr.sa.sa_family = AF_ISO;
+#endif
+#ifdef NETNS
+                       else if (strcasecmp(v, "ns") == 0)
+                               DaemonAddr.sa.sa_family = AF_NS;
+#endif
+#ifdef NETX25
+                       else if (strcasecmp(v, "x.25") == 0)
+                               DaemonAddr.sa.sa_family = AF_CCITT;
+#endif
+                       else
+                               syserr("554 Unknown address family %s in Family=option", v);
+                       break;
+
+                 case 'A':             /* address */
+                       switch (DaemonAddr.sa.sa_family)
+                       {
+#ifdef NETINET
+                         case AF_INET:
+                               if (isascii(*v) && isdigit(*v))
+                                       DaemonAddr.sin.sin_addr.s_addr = inet_network(v);
+                               else
+                               {
+                                       register struct netent *np;
+
+                                       np = getnetbyname(v);
+                                       if (np == NULL)
+                                               syserr("554 network \"%s\" unknown", v);
+                                       else
+                                               DaemonAddr.sin.sin_addr.s_addr = np->n_net;
+                               }
+                               break;
+#endif
+
+                         default:
+                               syserr("554 Address= option unsupported for family %d",
+                                       DaemonAddr.sa.sa_family);
+                               break;
+                       }
+                       break;
+
+                 case 'P':             /* port */
+                       switch (DaemonAddr.sa.sa_family)
+                       {
+                               short port;
+
+#ifdef NETINET
+                         case AF_INET:
+                               if (isascii(*v) && isdigit(*v))
+                                       DaemonAddr.sin.sin_port = atoi(v);
+                               else
+                               {
+                                       register struct servent *sp;
+
+                                       sp = getservbyname(v, "tcp");
+                                       if (sp == NULL)
+                                               syserr("554 service \"%s\" unknown", v);
+                                       else
+                                               DaemonAddr.sin.sin_port = sp->s_port;
+                               }
+                               break;
+#endif
+
+#ifdef NETISO
+                         case AF_ISO:
+                               /* assume two byte transport selector */
+                               if (isascii(*v) && isdigit(*v))
+                                       port = atoi(v);
+                               else
+                               {
+                                       register struct servent *sp;
+
+                                       sp = getservbyname(v, "tcp");
+                                       if (sp == NULL)
+                                               syserr("554 service \"%s\" unknown", v);
+                                       else
+                                               port = sp->s_port;
+                               }
+                               bcopy((char *) &port, TSEL(&DaemonAddr.siso), 2);
+                               break;
+#endif
+
+                         default:
+                               syserr("554 Port= option unsupported for family %d",
+                                       DaemonAddr.sa.sa_family);
+                               break;
+                       }
+                       break;
+
+                 case 'L':             /* listen queue size */
+                       ListenQueueSize = atoi(v);
+                       break;
+               }
+       }
+}
+\f/*
 **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
 **
 **     Parameters:
 **             host -- the name of the host.
 **             port -- the port number to connect to.
 **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
 **
 **     Parameters:
 **             host -- the name of the host.
 **             port -- the port number to connect to.
-**             outfile -- a pointer to a place to put the outfile
-**                     descriptor.
-**             infile -- ditto for infile.
+**             mci -- a pointer to the mail connection information
+**                     structure to be filled in.
+**             usesecureport -- if set, use a low numbered (reserved)
+**                     port to provide some rudimentary authentication.
 **
 **     Returns:
 **             An exit code telling whether the connection could be
 **
 **     Returns:
 **             An exit code telling whether the connection could be
@@ -304,16 +495,20 @@ clrdaemon()
 **             none.
 */
 
 **             none.
 */
 
-makeconnection(host, port, outfile, infile)
+SOCKADDR       CurHostAddr;            /* address of current host */
+
+int
+makeconnection(host, port, mci, usesecureport)
        char *host;
        u_short port;
        char *host;
        u_short port;
-       FILE **outfile;
-       FILE **infile;
+       register MCI *mci;
+       bool usesecureport;
 {
        register int i, s;
        register struct hostent *hp = (struct hostent *)NULL;
 {
        register int i, s;
        register struct hostent *hp = (struct hostent *)NULL;
-       extern char *inet_ntoa();
+       SOCKADDR addr;
        int sav_errno;
        int sav_errno;
+       int addrlen;
 #ifdef NAMED_BIND
        extern int h_errno;
 #endif
 #ifdef NAMED_BIND
        extern int h_errno;
 #endif
@@ -327,28 +522,43 @@ makeconnection(host, port, outfile, infile)
        h_errno = 0;
 #endif
        errno = 0;
        h_errno = 0;
 #endif
        errno = 0;
+       bzero(&CurHostAddr, sizeof CurHostAddr);
+       CurHostName = host;
 
        if (host[0] == '[')
        {
                long hid;
 
        if (host[0] == '[')
        {
                long hid;
-               register char *p = index(host, ']');
+               register char *p = strchr(host, ']');
 
                if (p != NULL)
                {
                        *p = '\0';
 
                if (p != NULL)
                {
                        *p = '\0';
+#ifdef NETINET
                        hid = inet_addr(&host[1]);
                        hid = inet_addr(&host[1]);
+                       if (hid == -1)
+#endif
+                       {
+                               /* try it as a host name (avoid MX lookup) */
+                               hp = gethostbyname(&host[1]);
+                               *p = ']';
+                               goto gothostent;
+                       }
                        *p = ']';
                }
                        *p = ']';
                }
-               if (p == NULL || hid == -1)
+               if (p == NULL)
                {
                {
-                       usrerr("Invalid numeric domain spec \"%s\"", host);
+                       usrerr("553 Invalid numeric domain spec \"%s\"", host);
                        return (EX_NOHOST);
                }
                        return (EX_NOHOST);
                }
-               SendmailAddress.sin_addr.s_addr = hid;
+#ifdef NETINET
+               addr.sin.sin_family = AF_INET;          /*XXX*/
+               addr.sin.sin_addr.s_addr = hid;
+#endif
        }
        else
        {
                hp = gethostbyname(host);
        }
        else
        {
                hp = gethostbyname(host);
+gothostent:
                if (hp == NULL)
                {
 #ifdef NAMED_BIND
                if (hp == NULL)
                {
 #ifdef NAMED_BIND
@@ -359,15 +569,25 @@ makeconnection(host, port, outfile, infile)
                        if (errno == ECONNREFUSED && UseNameServer)
                                return (EX_TEMPFAIL);
 #endif
                        if (errno == ECONNREFUSED && UseNameServer)
                                return (EX_TEMPFAIL);
 #endif
-
-                       /*
-                       **  XXX Should look for mail forwarder record here
-                       **  XXX if (h_errno == NO_ADDRESS).
-                       */
-
                        return (EX_NOHOST);
                }
                        return (EX_NOHOST);
                }
-               bcopy(hp->h_addr, (char *) &SendmailAddress.sin_addr, hp->h_length);
+               addr.sa.sa_family = hp->h_addrtype;
+               switch (hp->h_addrtype)
+               {
+#ifdef NETINET
+                 case AF_INET:
+                       bcopy(hp->h_addr,
+                               &addr.sin.sin_addr,
+                               hp->h_length);
+                       break;
+#endif
+
+                 default:
+                       bcopy(hp->h_addr,
+                               addr.sa.sa_data,
+                               hp->h_length);
+                       break;
+               }
                i = 1;
        }
 
                i = 1;
        }
 
@@ -376,100 +596,137 @@ makeconnection(host, port, outfile, infile)
        */
 
        if (port != 0)
        */
 
        if (port != 0)
-               SendmailAddress.sin_port = htons(port);
+               port = htons(port);
        else
        {
                register struct servent *sp = getservbyname("smtp", "tcp");
 
                if (sp == NULL)
                {
        else
        {
                register struct servent *sp = getservbyname("smtp", "tcp");
 
                if (sp == NULL)
                {
-                       syserr("makeconnection: server \"smtp\" unknown");
-                       return (EX_OSFILE);
+                       syserr("554 makeconnection: service \"smtp\" unknown");
+                       return (EX_OSERR);
                }
                }
-               SendmailAddress.sin_port = sp->s_port;
+               port = sp->s_port;
+       }
+
+       switch (addr.sa.sa_family)
+       {
+#ifdef NETINET
+         case AF_INET:
+               addr.sin.sin_port = port;
+               addrlen = sizeof (struct sockaddr_in);
+               break;
+#endif
+
+#ifdef NETISO
+         case AF_ISO:
+               /* assume two byte transport selector */
+               bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2);
+               addrlen = sizeof (struct sockaddr_iso);
+               break;
+#endif
+
+         default:
+               syserr("Can't connect to address family %d", addr.sa.sa_family);
+               return (EX_NOHOST);
        }
 
        /*
        **  Try to actually open the connection.
        */
 
        }
 
        /*
        **  Try to actually open the connection.
        */
 
-again:
-       if (tTd(16, 1))
-               printf("makeconnection (%s [%s])\n", host,
-                   inet_ntoa(SendmailAddress.sin_addr.s_addr));
+#ifdef XLA
+       /* if too many connections, don't bother trying */
+       if (!xla_noqueue_ok(host))
+               return EX_TEMPFAIL;
+#endif
 
 
-       s = socket(AF_INET, SOCK_STREAM, 0);
-       if (s < 0)
+       for (;;)
        {
        {
-               syserr("makeconnection: no socket");
-               sav_errno = errno;
-               goto failure;
-       }
+               if (tTd(16, 1))
+                       printf("makeconnection (%s [%s])\n",
+                               host, anynet_ntoa(&addr));
 
 
-       if (tTd(16, 1))
-               printf("makeconnection: %d\n", s);
+               /* save for logging */
+               CurHostAddr = addr;
 
 
-       /* turn on network debugging? */
-       if (tTd(16, 14))
-       {
-               int on = 1;
-               (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);
-       }
-       if (CurEnv->e_xfp != NULL)
-               (void) fflush(CurEnv->e_xfp);           /* for debugging */
-       errno = 0;                                      /* for debugging */
-       SendmailAddress.sin_family = AF_INET;
-       if (connect(s,
-           (struct sockaddr *)&SendmailAddress, sizeof SendmailAddress) < 0)
-       {
+               if (usesecureport)
+               {
+                       int rport = IPPORT_RESERVED - 1;
+
+                       s = rresvport(&rport);
+               }
+               else
+               {
+                       s = socket(AF_INET, SOCK_STREAM, 0);
+               }
+               if (s < 0)
+               {
+                       sav_errno = errno;
+                       syserr("makeconnection: no socket");
+                       goto failure;
+               }
+
+               if (tTd(16, 1))
+                       printf("makeconnection: fd=%d\n", s);
+
+               /* turn on network debugging? */
+               if (tTd(16, 101))
+               {
+                       int on = 1;
+                       (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG,
+                                         (char *)&on, sizeof on);
+               }
+               if (CurEnv->e_xfp != NULL)
+                       (void) fflush(CurEnv->e_xfp);           /* for debugging */
+               errno = 0;                                      /* for debugging */
+               if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0)
+                       break;
+
+               /* couldn't connect.... figure out why */
                sav_errno = errno;
                (void) close(s);
                if (hp && hp->h_addr_list[i])
                {
                sav_errno = errno;
                (void) close(s);
                if (hp && hp->h_addr_list[i])
                {
-                       bcopy(hp->h_addr_list[i++],
-                           (char *)&SendmailAddress.sin_addr, hp->h_length);
-                       goto again;
+                       if (tTd(16, 1))
+                               printf("Connect failed (%s); trying new address....\n",
+                                       errstring(sav_errno));
+                       switch (addr.sa.sa_family)
+                       {
+#ifdef NETINET
+                         case AF_INET:
+                               bcopy(hp->h_addr_list[i++],
+                                     &addr.sin.sin_addr,
+                                     hp->h_length);
+                               break;
+#endif
+
+                         default:
+                               bcopy(hp->h_addr_list[i++],
+                                       addr.sa.sa_data,
+                                       hp->h_length);
+                               break;
+                       }
+                       continue;
                }
 
                /* failure, decide if temporary or not */
        failure:
                }
 
                /* failure, decide if temporary or not */
        failure:
-               switch (sav_errno)
+#ifdef XLA
+               xla_host_end(host);
+#endif
+               if (transienterror(sav_errno))
+                       return EX_TEMPFAIL;
+               else
                {
                {
-                 case EISCONN:
-                 case ETIMEDOUT:
-                 case EINPROGRESS:
-                 case EALREADY:
-                 case EADDRINUSE:
-                 case EHOSTDOWN:
-                 case ENETDOWN:
-                 case ENETRESET:
-                 case ENOBUFS:
-                 case ECONNREFUSED:
-                 case ECONNRESET:
-                 case EHOSTUNREACH:
-                 case ENETUNREACH:
-                       /* there are others, I'm sure..... */
-                       return (EX_TEMPFAIL);
-
-                 case EPERM:
-                       /* why is this happening? */
-                       syserr("makeconnection: funny failure, addr=%lx, port=%x",
-                               SendmailAddress.sin_addr.s_addr, SendmailAddress.sin_port);
-                       return (EX_TEMPFAIL);
-
-                 default:
-                       {
-                               extern char *errstring();
-
-                               message(Arpa_Info, "%s", errstring(sav_errno));
-                               return (EX_UNAVAILABLE);
-                       }
+                       message("%s", errstring(sav_errno));
+                       return (EX_UNAVAILABLE);
                }
        }
 
        /* connection ok, put it into canonical form */
                }
        }
 
        /* connection ok, put it into canonical form */
-       *outfile = fdopen(s, "w");
-       *infile = fdopen(dup(s), "r");
+       mci->mci_out = fdopen(s, "w");
+       mci->mci_in = fdopen(dup(s), "r");
 
        return (EX_OK);
 }
 
        return (EX_OK);
 }
@@ -484,16 +741,18 @@ again:
 **             A list of aliases for this host.
 **
 **     Side Effects:
 **             A list of aliases for this host.
 **
 **     Side Effects:
-**             none.
+**             Sets the MyIpAddrs buffer to a list of my IP addresses.
 */
 
 */
 
+struct in_addr MyIpAddrs[MAXIPADDR + 1];
+
 char **
 myhostname(hostbuf, size)
        char hostbuf[];
        int size;
 {
 char **
 myhostname(hostbuf, size)
        char hostbuf[];
        int size;
 {
+       register struct hostent *hp;
        extern struct hostent *gethostbyname();
        extern struct hostent *gethostbyname();
-       struct hostent *hp;
 
        if (gethostname(hostbuf, size) < 0)
        {
 
        if (gethostname(hostbuf, size) < 0)
        {
@@ -502,61 +761,489 @@ myhostname(hostbuf, size)
        hp = gethostbyname(hostbuf);
        if (hp != NULL)
        {
        hp = gethostbyname(hostbuf);
        if (hp != NULL)
        {
-               (void) strcpy(hostbuf, hp->h_name);
+               (void) strncpy(hostbuf, hp->h_name, size - 1);
+               hostbuf[size - 1] = '\0';
+
+               if (hp->h_addrtype == AF_INET && hp->h_length == 4)
+               {
+                       register int i;
+
+                       for (i = 0; i < MAXIPADDR; i++)
+                       {
+                               if (hp->h_addr_list[i] == NULL)
+                                       break;
+                               MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i];
+                       }
+                       MyIpAddrs[i].s_addr = 0;
+               }
+
                return (hp->h_aliases);
        }
        else
                return (NULL);
 }
                return (hp->h_aliases);
        }
        else
                return (NULL);
 }
+\f/*
+**  GETAUTHINFO -- get the real host name asociated with a file descriptor
+**
+**     Uses RFC1413 protocol to try to get info from the other end.
+**
+**     Parameters:
+**             fd -- the descriptor
+**
+**     Returns:
+**             The user@host information associated with this descriptor.
+**
+**     Side Effects:
+**             Sets RealHostName to the name of the host at the other end.
+*/
 
 
-/*
- *  MAPHOSTNAME -- turn a hostname into canonical form
- *
- *     Parameters:
- *             hbuf -- a buffer containing a hostname.
- *             hbsize -- the size of hbuf.
- *
- *     Returns:
- *             none.
- *
- *     Side Effects:
- *             Looks up the host specified in hbuf.  If it is not
- *             the canonical name for that host, replace it with
- *             the canonical name.  If the name is unknown, or it
- *             is already the canonical name, leave it unchanged.
- */
-maphostname(hbuf, hbsize)
-       char *hbuf;
-       int hbsize;
+#ifdef IDENTPROTO
+
+static jmp_buf CtxAuthTimeout;
+
+static
+authtimeout()
+{
+       longjmp(CtxAuthTimeout, 1);
+}
+
+#endif
+
+char *
+getauthinfo(fd)
+       int fd;
+{
+       SOCKADDR fa;
+       int falen;
+       register char *p;
+#ifdef IDENTPROTO
+       SOCKADDR la;
+       int lalen;
+       register struct servent *sp;
+       int s;
+       int i;
+       EVENT *ev;
+#endif
+       static char hbuf[MAXNAME * 2 + 2];
+       extern char *hostnamebyanyaddr();
+       extern char RealUserName[];                     /* main.c */
+
+       falen = sizeof fa;
+       if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0)
+       {
+               RealHostName = "localhost";
+               (void) sprintf(hbuf, "%s@localhost", RealUserName);
+               if (tTd(9, 1))
+                       printf("getauthinfo: %s\n", hbuf);
+               return hbuf;
+       }
+
+       RealHostName = newstr(hostnamebyanyaddr(&fa));
+       RealHostAddr = fa;
+
+#ifdef IDENTPROTO
+       lalen = sizeof la;
+       if (fa.sa.sa_family != AF_INET ||
+           getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 ||
+           la.sa.sa_family != AF_INET)
+       {
+               /* no ident info */
+               goto noident;
+       }
+
+       /* create ident query */
+       (void) sprintf(hbuf, "%d,%d\r\n",
+               ntohs(fa.sin.sin_port), ntohs(la.sin.sin_port));
+
+       /* create local address */
+       bzero(&la, sizeof la);
+
+       /* create foreign address */
+       sp = getservbyname("auth", "tcp");
+       if (sp != NULL)
+               fa.sin.sin_port = sp->s_port;
+       else
+               fa.sin.sin_port = htons(113);
+
+       s = -1;
+       if (setjmp(CtxAuthTimeout) != 0)
+       {
+               if (s >= 0)
+                       (void) close(s);
+               goto noident;
+       }
+
+       /* put a timeout around the whole thing */
+       ev = setevent((time_t) 30, authtimeout, 0);
+
+       /* connect to foreign IDENT server */
+       s = socket(AF_INET, SOCK_STREAM, 0);
+       if (s < 0)
+       {
+               clrevent(ev);
+               goto noident;
+       }
+       if (connect(s, &fa.sa, sizeof fa.sin) < 0)
+       {
+closeident:
+               (void) close(s);
+               clrevent(ev);
+               goto noident;
+       }
+
+       if (tTd(9, 10))
+               printf("getauthinfo: sent %s", hbuf);
+
+       /* send query */
+       if (write(s, hbuf, strlen(hbuf)) < 0)
+               goto closeident;
+
+       /* get result */
+       i = read(s, hbuf, sizeof hbuf);
+       (void) close(s);
+       clrevent(ev);
+       if (i <= 0)
+               goto noident;
+       if (hbuf[--i] == '\n' && hbuf[--i] == '\r')
+               i--;
+       hbuf[++i] = '\0';
+
+       if (tTd(9, 3))
+               printf("getauthinfo:  got %s\n", hbuf);
+
+       /* parse result */
+       p = strchr(hbuf, ':');
+       if (p == NULL)
+       {
+               /* malformed response */
+               goto noident;
+       }
+       while (isascii(*++p) && isspace(*p))
+               continue;
+       if (strncasecmp(p, "userid", 6) != 0)
+       {
+               /* presumably an error string */
+               goto noident;
+       }
+       p += 6;
+       while (isascii(*p) && isspace(*p))
+               p++;
+       if (*p++ != ':')
+       {
+               /* either useridxx or malformed response */
+               goto noident;
+       }
+
+       /* p now points to the OSTYPE field */
+       p = strchr(p, ':');
+       if (p == NULL)
+       {
+               /* malformed response */
+               goto noident;
+       }
+
+       /* 1413 says don't do this -- but it's broken otherwise */
+       while (isascii(*++p) && isspace(*p))
+               continue;
+
+       /* p now points to the authenticated name */
+       (void) sprintf(hbuf, "%s@%s", p, RealHostName);
+       goto finish;
+
+#endif /* IDENTPROTO */
+
+noident:
+       (void) strcpy(hbuf, RealHostName);
+
+finish:
+       if (RealHostName[0] != '[')
+       {
+               p = &hbuf[strlen(hbuf)];
+               (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr));
+       }
+       if (tTd(9, 1))
+               printf("getauthinfo: %s\n", hbuf);
+       return hbuf;
+}
+\f/*
+**  HOST_MAP_LOOKUP -- turn a hostname into canonical form
+**
+**     Parameters:
+**             map -- a pointer to this map (unused).
+**             name -- the (presumably unqualified) hostname.
+**             av -- unused -- for compatibility with other mapping
+**                     functions.
+**             statp -- an exit status (out parameter) -- set to
+**                     EX_TEMPFAIL if the name server is unavailable.
+**
+**     Returns:
+**             The mapping, if found.
+**             NULL if no mapping found.
+**
+**     Side Effects:
+**             Looks up the host specified in hbuf.  If it is not
+**             the canonical name for that host, return the canonical
+**             name.
+*/
+
+char *
+host_map_lookup(map, name, av, statp)
+       MAP *map;
+       char *name;
+       char **av;
+       int *statp;
 {
        register struct hostent *hp;
        u_long in_addr;
 {
        register struct hostent *hp;
        u_long in_addr;
-       char ptr[256], *cp;
-       struct hostent *gethostbyaddr();
+       char *cp;
+       int i;
+       register STAB *s;
+       char hbuf[MAXNAME];
+       extern struct hostent *gethostbyaddr();
+       extern int h_errno;
+
+       /*
+       **  See if we have already looked up this name.  If so, just
+       **  return it.
+       */
+
+       s = stab(name, ST_NAMECANON, ST_ENTER);
+       if (bitset(NCF_VALID, s->s_namecanon.nc_flags))
+       {
+               if (tTd(9, 1))
+                       printf("host_map_lookup(%s) => CACHE %s\n",
+                               name, s->s_namecanon.nc_cname);
+               errno = s->s_namecanon.nc_errno;
+               h_errno = s->s_namecanon.nc_herrno;
+               *statp = s->s_namecanon.nc_stat;
+               return s->s_namecanon.nc_cname;
+       }
 
        /*
 
        /*
-        * If first character is a bracket, then it is an address
-        * lookup.  Address is copied into a temporary buffer to
-        * strip the brackets and to preserve hbuf if address is
-        * unknown.
-        */
-       if (*hbuf != '[') {
-               getcanonname(hbuf, hbsize);
-               return;
-       }
-       if ((cp = index(strcpy(ptr, hbuf), ']')) == NULL)
-               return;
+       **  If first character is a bracket, then it is an address
+       **  lookup.  Address is copied into a temporary buffer to
+       **  strip the brackets and to preserve name if address is
+       **  unknown.
+       */
+
+       if (*name != '[')
+       {
+               extern bool getcanonname();
+
+               if (tTd(9, 1))
+                       printf("host_map_lookup(%s) => ", name);
+               s->s_namecanon.nc_flags |= NCF_VALID;           /* will be soon */
+               (void) strcpy(hbuf, name);
+               if (getcanonname(hbuf, sizeof hbuf - 1))
+               {
+                       if (tTd(9, 1))
+                               printf("%s\n", hbuf);
+                       cp = map_rewrite(map, hbuf, strlen(hbuf), av);
+                       s->s_namecanon.nc_cname = newstr(cp);
+                       return cp;
+               }
+               else
+               {
+                       register struct hostent *hp;
+
+                       if (tTd(9, 1))
+                               printf("FAIL (%d)\n", h_errno);
+                       s->s_namecanon.nc_errno = errno;
+                       s->s_namecanon.nc_herrno = h_errno;
+                       switch (h_errno)
+                       {
+                         case TRY_AGAIN:
+                               if (UseNameServer)
+                               {
+                                       char *msg = "Recipient domain nameserver timed out";
+
+                                       message(msg);
+                                       if (CurEnv->e_message == NULL)
+                                               CurEnv->e_message = newstr(msg);
+                               }
+                               *statp = EX_TEMPFAIL;
+                               break;
+
+                         case HOST_NOT_FOUND:
+                               *statp = EX_NOHOST;
+                               break;
+
+                         case NO_RECOVERY:
+                               *statp = EX_SOFTWARE;
+                               break;
+
+                         default:
+                               *statp = EX_UNAVAILABLE;
+                               break;
+                       }
+                       s->s_namecanon.nc_stat = *statp;
+                       if (*statp != EX_TEMPFAIL || UseNameServer)
+                               return NULL;
+
+                       /*
+                       **  Try to look it up in /etc/hosts
+                       */
+
+                       hp = gethostbyname(name);
+                       if (hp == NULL)
+                       {
+                               /* no dice there either */
+                               s->s_namecanon.nc_stat = *statp = EX_NOHOST;
+                               return NULL;
+                       }
+
+                       s->s_namecanon.nc_stat = *statp = EX_OK;
+                       cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av);
+                       s->s_namecanon.nc_cname = newstr(cp);
+                       return cp;
+               }
+       }
+       if ((cp = strchr(name, ']')) == NULL)
+               return (NULL);
        *cp = '\0';
        *cp = '\0';
-       in_addr = inet_addr(&ptr[1]);
+       in_addr = inet_addr(&name[1]);
+
+       /* check to see if this is one of our addresses */
+       for (i = 0; MyIpAddrs[i].s_addr != 0; i++)
+       {
+               if (MyIpAddrs[i].s_addr == in_addr)
+               {
+                       return map_rewrite(map, MyHostName, strlen(MyHostName), av);
+               }
+       }
+
+       /* nope -- ask the name server */
        hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET);
        hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET);
+       s->s_namecanon.nc_errno = errno;
+       s->s_namecanon.nc_herrno = h_errno;
+       s->s_namecanon.nc_flags |= NCF_VALID;           /* will be soon */
        if (hp == NULL)
        if (hp == NULL)
-               return;
-       if (strlen(hp->h_name) >= hbsize)
-               hp->h_name[hbsize - 1] = '\0';
-       (void)strcpy(hbuf, hp->h_name);
+       {
+               s->s_namecanon.nc_stat = *statp = EX_NOHOST;
+               return (NULL);
+       }
+
+       /* found a match -- copy out */
+       cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av);
+       s->s_namecanon.nc_stat = *statp = EX_OK;
+       s->s_namecanon.nc_cname = newstr(cp);
+       return cp;
 }
 }
+\f/*
+**  ANYNET_NTOA -- convert a network address to printable form.
+**
+**     Parameters:
+**             sap -- a pointer to a sockaddr structure.
+**
+**     Returns:
+**             A printable version of that sockaddr.
+*/
+
+char *
+anynet_ntoa(sap)
+       register SOCKADDR *sap;
+{
+       register char *bp;
+       register char *ap;
+       int l;
+       static char buf[80];
+
+       /* check for null/zero family */
+       if (sap == NULL)
+               return "NULLADDR";
+       if (sap->sa.sa_family == 0)
+               return "0";
+
+#ifdef NETINET
+       if (sap->sa.sa_family == AF_INET)
+       {
+               extern char *inet_ntoa();
 
 
-# else DAEMON
+               return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr);
+       }
+#endif
+
+       /* unknown family -- just dump bytes */
+       (void) sprintf(buf, "Family %d: ", sap->sa.sa_family);
+       bp = &buf[strlen(buf)];
+       ap = sap->sa.sa_data;
+       for (l = sizeof sap->sa.sa_data; --l >= 0; )
+       {
+               (void) sprintf(bp, "%02x:", *ap++ & 0377);
+               bp += 3;
+       }
+       *--bp = '\0';
+       return buf;
+}
+\f/*
+**  HOSTNAMEBYANYADDR -- return name of host based on address
+**
+**     Parameters:
+**             sap -- SOCKADDR pointer
+**
+**     Returns:
+**             text representation of host name.
+**
+**     Side Effects:
+**             none.
+*/
+
+char *
+hostnamebyanyaddr(sap)
+       register SOCKADDR *sap;
+{
+       register struct hostent *hp;
+
+#ifdef NAMED_BIND
+       int saveretry;
+
+       /* shorten name server timeout to avoid higher level timeouts */
+       saveretry = _res.retry;
+       _res.retry = 3;
+#endif /* NAMED_BIND */
+
+       switch (sap->sa.sa_family)
+       {
+#ifdef NETINET
+         case AF_INET:
+               hp = gethostbyaddr((char *) &sap->sin.sin_addr,
+                       sizeof sap->sin.sin_addr,
+                       AF_INET);
+               break;
+#endif
+
+#ifdef NETISO
+         case AF_ISO:
+               hp = gethostbyaddr((char *) &sap->siso.siso_addr,
+                       sizeof sap->siso.siso_addr,
+                       AF_ISO);
+               break;
+#endif
+
+         default:
+               hp = gethostbyaddr(sap->sa.sa_data,
+                          sizeof sap->sa.sa_data,
+                          sap->sa.sa_family);
+               break;
+       }
+
+#ifdef NAMED_BIND
+       _res.retry = saveretry;
+#endif /* NAMED_BIND */
+
+       if (hp != NULL)
+               return hp->h_name;
+       else
+       {
+               /* produce a dotted quad */
+               static char buf[512];
+
+               (void) sprintf(buf, "[%s]", anynet_ntoa(sap));
+               return buf;
+       }
+}
+
+# else /* DAEMON */
 /* code for systems without sophisticated networking */
 
 /*
 /* code for systems without sophisticated networking */
 
 /*
@@ -585,28 +1272,61 @@ myhostname(hostbuf, size)
        return (NULL);
 }
 \f/*
        return (NULL);
 }
 \f/*
+**  GETAUTHINFO -- get the real host name asociated with a file descriptor
+**
+**     Parameters:
+**             fd -- the descriptor
+**
+**     Returns:
+**             The host name associated with this descriptor, if it can
+**                     be determined.
+**             NULL otherwise.
+**
+**     Side Effects:
+**             none
+*/
+
+char *
+getauthinfo(fd)
+       int fd;
+{
+       return NULL;
+}
+\f/*
 **  MAPHOSTNAME -- turn a hostname into canonical form
 **
 **     Parameters:
 **  MAPHOSTNAME -- turn a hostname into canonical form
 **
 **     Parameters:
-**             hbuf -- a buffer containing a hostname.
-**             hbsize -- the size of hbuf.
+**             map -- a pointer to the database map.
+**             name -- a buffer containing a hostname.
+**             avp -- a pointer to a (cf file defined) argument vector.
+**             statp -- an exit status (out parameter).
 **
 **     Returns:
 **
 **     Returns:
-**             none.
+**             mapped host name
+**             FALSE otherwise.
 **
 **     Side Effects:
 **
 **     Side Effects:
-**             Looks up the host specified in hbuf.  If it is not
+**             Looks up the host specified in name.  If it is not
 **             the canonical name for that host, replace it with
 **             the canonical name.  If the name is unknown, or it
 **             is already the canonical name, leave it unchanged.
 */
 
 /*ARGSUSED*/
 **             the canonical name for that host, replace it with
 **             the canonical name.  If the name is unknown, or it
 **             is already the canonical name, leave it unchanged.
 */
 
 /*ARGSUSED*/
-maphostname(hbuf, hbsize)
-       char *hbuf;
-       int hbsize;
+char *
+host_map_lookup(map, name, avp, statp)
+       MAP *map;
+       char *name;
+       char **avp;
+       char *statp;
 {
 {
-       return;
+       register struct hostent *hp;
+
+       hp = gethostbyname(name);
+       if (hp != NULL)
+               return hp->h_name;
+       *statp = EX_NOHOST;
+       return NULL;
 }
 
 }
 
-#endif DAEMON
+#endif /* DAEMON */
index c8e05f1..4ee4490 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)deliver.c  5.41 (Berkeley) 3/21/91";
+static char sccsid[] = "@(#)deliver.c  8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #include "sendmail.h"
 #endif /* not lint */
 
 #include "sendmail.h"
-#include <sys/signal.h>
-#include <sys/stat.h>
+#include <signal.h>
 #include <netdb.h>
 #include <netdb.h>
-#include <fcntl.h>
 #include <errno.h>
 #ifdef NAMED_BIND
 #include <errno.h>
 #ifdef NAMED_BIND
-#include <sys/param.h>
 #include <arpa/nameser.h>
 #include <resolv.h>
 #endif
 
 /*
 #include <arpa/nameser.h>
 #include <resolv.h>
 #endif
 
 /*
+**  SENDALL -- actually send all the messages.
+**
+**     Parameters:
+**             e -- the envelope to send.
+**             mode -- the delivery mode to use.  If SM_DEFAULT, use
+**                     the current e->e_sendmode.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Scans the send lists and sends everything it finds.
+**             Delivers any appropriate error messages.
+**             If we are running in a non-interactive mode, takes the
+**                     appropriate action.
+*/
+
+sendall(e, mode)
+       ENVELOPE *e;
+       char mode;
+{
+       register ADDRESS *q;
+       char *owner;
+       int otherowners;
+       register ENVELOPE *ee;
+       ENVELOPE *splitenv = NULL;
+       bool announcequeueup;
+
+       if (bitset(EF_FATALERRS, e->e_flags))
+       {
+               /* this will get a return message -- so don't send it */
+               e->e_flags |= EF_CLRQUEUE;
+               return;
+       }
+
+       /* determine actual delivery mode */
+       if (mode == SM_DEFAULT)
+       {
+               mode = e->e_sendmode;
+               if (mode != SM_VERIFY &&
+                   shouldqueue(e->e_msgpriority, e->e_ctime))
+                       mode = SM_QUEUE;
+               announcequeueup = mode == SM_QUEUE;
+       }
+       else
+               announcequeueup = FALSE;
+
+       if (tTd(13, 1))
+       {
+               printf("\nSENDALL: mode %c, e_from ", mode);
+               printaddr(&e->e_from, FALSE);
+               printf("sendqueue:\n");
+               printaddr(e->e_sendqueue, TRUE);
+       }
+
+       /*
+       **  Do any preprocessing necessary for the mode we are running.
+       **      Check to make sure the hop count is reasonable.
+       **      Delete sends to the sender in mailing lists.
+       */
+
+       CurEnv = e;
+
+       if (e->e_hopcount > MaxHopCount)
+       {
+               errno = 0;
+               syserr("554 too many hops %d (%d max): from %s, to %s",
+                       e->e_hopcount, MaxHopCount, e->e_from.q_paddr,
+                       e->e_sendqueue->q_paddr);
+               return;
+       }
+
+       /*
+       **  Do sender deletion.
+       **
+       **      If the sender has the QQUEUEUP flag set, skip this.
+       **      This can happen if the name server is hosed when you
+       **      are trying to send mail.  The result is that the sender
+       **      is instantiated in the queue as a recipient.
+       */
+
+       if (!MeToo && !bitset(QQUEUEUP, e->e_from.q_flags))
+       {
+               if (tTd(13, 5))
+               {
+                       printf("sendall: QDONTSEND ");
+                       printaddr(&e->e_from, FALSE);
+               }
+               e->e_from.q_flags |= QDONTSEND;
+               (void) recipient(&e->e_from, &e->e_sendqueue, e);
+       }
+
+       /*
+       **  Handle alias owners.
+       **
+       **      We scan up the q_alias chain looking for owners.
+       **      We discard owners that are the same as the return path.
+       */
+
+       for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+       {
+               register struct address *a;
+
+               for (a = q; a != NULL && a->q_owner == NULL; a = a->q_alias)
+                       continue;
+               if (a != NULL)
+                       q->q_owner = a->q_owner;
+                               
+               if (q->q_owner != NULL &&
+                   !bitset(QDONTSEND, q->q_flags) &&
+                   strcmp(q->q_owner, e->e_from.q_paddr) == 0)
+                       q->q_owner = NULL;
+       }
+               
+       owner = "";
+       otherowners = 1;
+       while (owner != NULL && otherowners > 0)
+       {
+               owner = NULL;
+               otherowners = 0;
+
+               for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+               {
+                       if (bitset(QDONTSEND, q->q_flags))
+                               continue;
+
+                       if (q->q_owner != NULL)
+                       {
+                               if (owner == NULL)
+                                       owner = q->q_owner;
+                               else if (owner != q->q_owner)
+                               {
+                                       if (strcmp(owner, q->q_owner) == 0)
+                                       {
+                                               /* make future comparisons cheap */
+                                               q->q_owner = owner;
+                                       }
+                                       else
+                                       {
+                                               otherowners++;
+                                       }
+                                       owner = q->q_owner;
+                               }
+                       }
+                       else
+                       {
+                               otherowners++;
+                       }
+               }
+
+               if (owner != NULL && otherowners > 0)
+               {
+                       extern HDR *copyheader();
+                       extern ADDRESS *copyqueue();
+
+                       /*
+                       **  Split this envelope into two.
+                       */
+
+                       ee = (ENVELOPE *) xalloc(sizeof(ENVELOPE));
+                       *ee = *e;
+                       ee->e_id = NULL;
+                       (void) queuename(ee, '\0');
+
+                       if (tTd(13, 1))
+                               printf("sendall: split %s into %s\n",
+                                       e->e_id, ee->e_id);
+
+                       ee->e_header = copyheader(e->e_header);
+                       ee->e_sendqueue = copyqueue(e->e_sendqueue);
+                       ee->e_errorqueue = copyqueue(e->e_errorqueue);
+                       ee->e_flags = e->e_flags & ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS);
+                       setsender(owner, ee, NULL, TRUE);
+                       if (tTd(13, 5))
+                       {
+                               printf("sendall(split): QDONTSEND ");
+                               printaddr(&ee->e_from, FALSE);
+                       }
+                       ee->e_from.q_flags |= QDONTSEND;
+                       ee->e_dfp = NULL;
+                       ee->e_xfp = NULL;
+                       ee->e_lockfp = NULL;
+                       ee->e_df = NULL;
+                       ee->e_errormode = EM_MAIL;
+                       ee->e_sibling = splitenv;
+                       splitenv = ee;
+                       
+                       for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+                               if (q->q_owner == owner)
+                                       q->q_flags |= QDONTSEND;
+                       for (q = ee->e_sendqueue; q != NULL; q = q->q_next)
+                               if (q->q_owner != owner)
+                                       q->q_flags |= QDONTSEND;
+
+                       if (e->e_df != NULL && mode != SM_VERIFY)
+                       {
+                               ee->e_dfp = NULL;
+                               ee->e_df = newstr(queuename(ee, 'd'));
+                               if (link(e->e_df, ee->e_df) < 0)
+                               {
+                                       syserr("sendall: link(%s, %s)",
+                                               e->e_df, ee->e_df);
+                               }
+                       }
+
+                       if (mode != SM_VERIFY)
+                               openxscript(ee);
+#ifdef LOG
+                       if (LogLevel > 4)
+                               syslog(LOG_INFO, "%s: clone %s",
+                                       ee->e_id, e->e_id);
+#endif
+               }
+       }
+
+       if (owner != NULL)
+       {
+               setsender(owner, e, NULL, TRUE);
+               if (tTd(13, 5))
+               {
+                       printf("sendall(owner): QDONTSEND ");
+                       printaddr(&e->e_from, FALSE);
+               }
+               e->e_from.q_flags |= QDONTSEND;
+               e->e_errormode = EM_MAIL;
+       }
+
+# ifdef QUEUE
+       if ((mode == SM_QUEUE || mode == SM_FORK ||
+            (mode != SM_VERIFY && SuperSafe)) &&
+           !bitset(EF_INQUEUE, e->e_flags))
+       {
+               /* be sure everything is instantiated in the queue */
+               queueup(e, TRUE, announcequeueup);
+               for (ee = splitenv; ee != NULL; ee = ee->e_sibling)
+                       queueup(ee, TRUE, announcequeueup);
+       }
+#endif /* QUEUE */
+
+       if (splitenv != NULL)
+       {
+               if (tTd(13, 1))
+               {
+                       printf("\nsendall: Split queue; remaining queue:\n");
+                       printaddr(e->e_sendqueue, TRUE);
+               }
+
+               for (ee = splitenv; ee != NULL; ee = ee->e_sibling)
+               {
+                       CurEnv = ee;
+                       sendenvelope(ee, mode);
+               }
+
+               CurEnv = e;
+       }
+       sendenvelope(e, mode);
+
+       for (; splitenv != NULL; splitenv = splitenv->e_sibling)
+               dropenvelope(splitenv);
+}
+
+sendenvelope(e, mode)
+       register ENVELOPE *e;
+       char mode;
+{
+       bool oldverbose;
+       int pid;
+       register ADDRESS *q;
+#ifdef LOCKF
+       struct flock lfd;
+#endif
+
+       oldverbose = Verbose;
+       switch (mode)
+       {
+         case SM_VERIFY:
+               Verbose = TRUE;
+               break;
+
+         case SM_QUEUE:
+  queueonly:
+               e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE;
+               return;
+
+         case SM_FORK:
+               if (e->e_xfp != NULL)
+                       (void) fflush(e->e_xfp);
+
+# ifdef LOCKF
+               /*
+               **  Since lockf has the interesting semantic that the
+               **  lock is lost when we fork, we have to risk losing
+               **  the lock here by closing before the fork, and then
+               **  trying to get it back in the child.
+               */
+
+               if (e->e_lockfp != NULL)
+               {
+                       (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp");
+                       e->e_lockfp = NULL;
+               }
+# endif /* LOCKF */
+
+               pid = fork();
+               if (pid < 0)
+               {
+                       goto queueonly;
+               }
+               else if (pid > 0)
+               {
+                       /* be sure we leave the temp files to our child */
+                       e->e_id = e->e_df = NULL;
+# ifndef LOCKF
+                       if (e->e_lockfp != NULL)
+                       {
+                               (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp");
+                               e->e_lockfp = NULL;
+                       }
+# endif
+
+                       /* close any random open files in the envelope */
+                       if (e->e_dfp != NULL)
+                       {
+                               (void) xfclose(e->e_dfp, "sendenvelope", "dfp");
+                               e->e_dfp = NULL;
+                       }
+                       if (e->e_xfp != NULL)
+                       {
+                               (void) xfclose(e->e_xfp, "sendenvelope", "xfp");
+                               e->e_xfp = NULL;
+                       }
+                       return;
+               }
+
+               /* double fork to avoid zombies */
+               if (fork() > 0)
+                       exit(EX_OK);
+
+               /* be sure we are immune from the terminal */
+               disconnect(FALSE, e);
+
+# ifdef LOCKF
+               /*
+               **  Now try to get our lock back.
+               */
+
+               lfd.l_type = F_WRLCK;
+               lfd.l_whence = lfd.l_start = lfd.l_len = 0;
+               e->e_lockfp = fopen(queuename(e, 'q'), "r+");
+               if (e->e_lockfp == NULL ||
+                   fcntl(fileno(e->e_lockfp), F_SETLK, &lfd) < 0)
+               {
+                       /* oops....  lost it */
+                       if (tTd(13, 1))
+                               printf("sendenvelope: %s lost lock: lockfp=%x, %s\n",
+                                       e->e_id, e->e_lockfp, errstring(errno));
+
+# ifdef LOG
+                       if (LogLevel > 29)
+                               syslog(LOG_NOTICE, "%s: lost lock: %m",
+                                       e->e_id);
+# endif /* LOG */
+                       exit(EX_OK);
+               }
+# endif /* LOCKF */
+
+               /*
+               **  Close any cached connections.
+               **
+               **      We don't send the QUIT protocol because the parent
+               **      still knows about the connection.
+               **
+               **      This should only happen when delivering an error
+               **      message.
+               */
+
+               mci_flush(FALSE, NULL);
+
+               break;
+       }
+
+       /*
+       **  Run through the list and send everything.
+       */
+
+       e->e_nsent = 0;
+       for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+       {
+               if (mode == SM_VERIFY)
+               {
+                       e->e_to = q->q_paddr;
+                       if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
+                       {
+                               message("deliverable: mailer %s, host %s, user %s",
+                                       q->q_mailer->m_name,
+                                       q->q_host,
+                                       q->q_user);
+                       }
+               }
+               else if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
+               {
+# ifdef QUEUE
+                       /*
+                       **  Checkpoint the send list every few addresses
+                       */
+
+                       if (e->e_nsent >= CheckpointInterval)
+                       {
+                               queueup(e, TRUE, FALSE);
+                               e->e_nsent = 0;
+                       }
+# endif /* QUEUE */
+                       (void) deliver(e, q);
+               }
+       }
+       Verbose = oldverbose;
+
+       /*
+       **  Now run through and check for errors.
+       */
+
+       if (mode == SM_VERIFY)
+       {
+               return;
+       }
+
+       for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+       {
+               if (tTd(13, 3))
+               {
+                       printf("Checking ");
+                       printaddr(q, FALSE);
+               }
+
+               /* only send errors if the message failed */
+               if (!bitset(QBADADDR, q->q_flags) ||
+                   bitset(QDONTSEND, q->q_flags))
+                       continue;
+
+               e->e_flags |= EF_FATALERRS;
+
+               if (q->q_owner == NULL && strcmp(e->e_from.q_paddr, "<>") != 0)
+                       (void) sendtolist(e->e_from.q_paddr, NULL,
+                                         &e->e_errorqueue, e);
+       }
+
+       if (mode == SM_FORK)
+               finis();
+}
+\f/*
+**  DOFORK -- do a fork, retrying a couple of times on failure.
+**
+**     This MUST be a macro, since after a vfork we are running
+**     two processes on the same stack!!!
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             From a macro???  You've got to be kidding!
+**
+**     Side Effects:
+**             Modifies the ==> LOCAL <== variable 'pid', leaving:
+**                     pid of child in parent, zero in child.
+**                     -1 on unrecoverable error.
+**
+**     Notes:
+**             I'm awfully sorry this looks so awful.  That's
+**             vfork for you.....
+*/
+
+# define NFORKTRIES    5
+
+# ifndef FORK
+# define FORK  fork
+# endif
+
+# define DOFORK(fORKfN) \
+{\
+       register int i;\
+\
+       for (i = NFORKTRIES; --i >= 0; )\
+       {\
+               pid = fORKfN();\
+               if (pid >= 0)\
+                       break;\
+               if (i > 0)\
+                       sleep((unsigned) NFORKTRIES - i);\
+       }\
+}
+\f/*
+**  DOFORK -- simple fork interface to DOFORK.
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             pid of child in parent.
+**             zero in child.
+**             -1 on error.
+**
+**     Side Effects:
+**             returns twice, once in parent and once in child.
+*/
+
+dofork()
+{
+       register int pid;
+
+       DOFORK(fork);
+       return (pid);
+}
+\f/*
 **  DELIVER -- Deliver a message to a list of addresses.
 **
 **     This routine delivers to everyone on the same host as the
 **  DELIVER -- Deliver a message to a list of addresses.
 **
 **     This routine delivers to everyone on the same host as the
@@ -81,20 +591,25 @@ deliver(e, firstto)
        register char *p;
        register MAILER *m;             /* mailer for this recipient */
        ADDRESS *ctladdr;
        register char *p;
        register MAILER *m;             /* mailer for this recipient */
        ADDRESS *ctladdr;
+       register MCI *mci;
        register ADDRESS *to = firstto;
        bool clever = FALSE;            /* running user smtp to this mailer */
        ADDRESS *tochain = NULL;        /* chain of users in this mailer call */
        register ADDRESS *to = firstto;
        bool clever = FALSE;            /* running user smtp to this mailer */
        ADDRESS *tochain = NULL;        /* chain of users in this mailer call */
-       int rcode;              /* response code */
+       int rcode;                      /* response code */
+       char *firstsig;                 /* signature of firstto */
+       int pid;
+       char *curhost;
+       int mpvect[2];
+       int rpvect[2];
        char *pv[MAXPV+1];
        char *pv[MAXPV+1];
-       char tobuf[MAXLINE-50];         /* text line of to people */
+       char tobuf[TOBUFSIZE];          /* text line of to people */
        char buf[MAXNAME];
        char buf[MAXNAME];
-       char tfrombuf[MAXNAME];         /* translated from person */
-       extern bool checkcompat();
-       extern ADDRESS *getctladdr();
-       extern char *remotename();
+       char rpathbuf[MAXNAME];         /* translated return path */
+       extern int checkcompat();
+       extern FILE *fdopen();
 
        errno = 0;
 
        errno = 0;
-       if (bitset(QDONTSEND, to->q_flags))
+       if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags))
                return (0);
 
 #ifdef NAMED_BIND
                return (0);
 
 #ifdef NAMED_BIND
@@ -107,6 +622,8 @@ deliver(e, firstto)
 
        m = to->q_mailer;
        host = to->q_host;
 
        m = to->q_mailer;
        host = to->q_host;
+       CurEnv = e;                     /* just in case */
+       e->e_statmsg = NULL;
 
        if (tTd(10, 1))
                printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n",
 
        if (tTd(10, 1))
                printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n",
@@ -122,18 +639,19 @@ deliver(e, firstto)
        **              This should be on a per-mailer basis.
        */
 
        **              This should be on a per-mailer basis.
        */
 
-       if (NoConnect && !QueueRun && bitnset(M_EXPENSIVE, m->m_flags) &&
-           !Verbose)
+       if (NoConnect && !bitset(EF_QUEUERUN, e->e_flags) &&
+           bitnset(M_EXPENSIVE, m->m_flags) && !Verbose)
        {
                for (; to != NULL; to = to->q_next)
                {
        {
                for (; to != NULL; to = to->q_next)
                {
-                       if (bitset(QDONTSEND, to->q_flags) || to->q_mailer != m)
+                       if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) ||
+                           to->q_mailer != m)
                                continue;
                        to->q_flags |= QQUEUEUP|QDONTSEND;
                        e->e_to = to->q_paddr;
                                continue;
                        to->q_flags |= QQUEUEUP|QDONTSEND;
                        e->e_to = to->q_paddr;
-                       message(Arpa_Info, "queued");
-                       if (LogLevel > 4)
-                               logdelivery("queued");
+                       message("queued");
+                       if (LogLevel > 8)
+                               logdelivery(m, NULL, "queued", e);
                }
                e->e_to = NULL;
                return (0);
                }
                e->e_to = NULL;
                return (0);
@@ -151,10 +669,11 @@ deliver(e, firstto)
        */
 
        /* rewrite from address, using rewriting rules */
        */
 
        /* rewrite from address, using rewriting rules */
-       expand("\001f", buf, &buf[sizeof buf - 1], e);
-       (void) strcpy(tfrombuf, remotename(buf, m, TRUE, TRUE));
-
-       define('g', tfrombuf, e);               /* translated sender address */
+       rcode = EX_OK;
+       (void) strcpy(rpathbuf, remotename(e->e_from.q_paddr, m,
+                                          RF_SENDERADDR|RF_CANONICAL,
+                                          &rcode, e));
+       define('g', rpathbuf, e);               /* translated return path */
        define('h', host, e);                   /* to host */
        Errors = 0;
        pvp = pv;
        define('h', host, e);                   /* to host */
        Errors = 0;
        pvp = pv;
@@ -167,8 +686,7 @@ deliver(e, firstto)
                        *pvp++ = "-f";
                else
                        *pvp++ = "-r";
                        *pvp++ = "-f";
                else
                        *pvp++ = "-r";
-               expand("\001g", buf, &buf[sizeof buf - 1], e);
-               *pvp++ = newstr(buf);
+               *pvp++ = newstr(rpathbuf);
        }
 
        /*
        }
 
        /*
@@ -180,10 +698,17 @@ deliver(e, firstto)
 
        for (mvp = m->m_argv; (p = *++mvp) != NULL; )
        {
 
        for (mvp = m->m_argv; (p = *++mvp) != NULL; )
        {
-               while ((p = index(p, '\001')) != NULL)
-                       if (*++p == 'u')
-                               break;
-               if (p != NULL)
+               /* can't use strchr here because of sign extension problems */
+               while (*p != '\0')
+               {
+                       if ((*p++ & 0377) == MACROEXPAND)
+                       {
+                               if (*p == 'u')
+                                       break;
+                       }
+               }
+
+               if (*p != '\0')
                        break;
 
                /* this entry is safe -- go ahead and process it */
                        break;
 
                /* this entry is safe -- go ahead and process it */
@@ -191,7 +716,7 @@ deliver(e, firstto)
                *pvp++ = newstr(buf);
                if (pvp >= &pv[MAXPV - 3])
                {
                *pvp++ = newstr(buf);
                if (pvp >= &pv[MAXPV - 3])
                {
-                       syserr("Too many parameters to %s before $u", pv[0]);
+                       syserr("554 Too many parameters to %s before $u", pv[0]);
                        return (-1);
                }
        }
                        return (-1);
                }
        }
@@ -208,11 +733,11 @@ deliver(e, firstto)
 # ifdef SMTP
                clever = TRUE;
                *pvp = NULL;
 # ifdef SMTP
                clever = TRUE;
                *pvp = NULL;
-# else SMTP
+# else /* SMTP */
                /* oops!  we don't implement SMTP */
                /* oops!  we don't implement SMTP */
-               syserr("SMTP style mailer");
+               syserr("554 SMTP style mailer");
                return (EX_SOFTWARE);
                return (EX_SOFTWARE);
-# endif SMTP
+# endif /* SMTP */
        }
 
        /*
        }
 
        /*
@@ -225,6 +750,7 @@ deliver(e, firstto)
        tobuf[0] = '\0';
        e->e_to = tobuf;
        ctladdr = NULL;
        tobuf[0] = '\0';
        e->e_to = tobuf;
        ctladdr = NULL;
+       firstsig = hostsignature(firstto->q_mailer, firstto->q_host, e);
        for (; to != NULL; to = to->q_next)
        {
                /* avoid sending multiple recipients to dumb mailers */
        for (; to != NULL; to = to->q_next)
        {
                /* avoid sending multiple recipients to dumb mailers */
@@ -232,9 +758,9 @@ deliver(e, firstto)
                        break;
 
                /* if already sent or not for this host, don't send */
                        break;
 
                /* if already sent or not for this host, don't send */
-               if (bitset(QDONTSEND, to->q_flags) ||
-                   strcmp(to->q_host, host) != 0 ||
-                   to->q_mailer != firstto->q_mailer)
+               if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) ||
+                   to->q_mailer != firstto->q_mailer ||
+                   strcmp(hostsignature(to->q_mailer, to->q_host, e), firstsig) != 0)
                        continue;
 
                /* avoid overflowing tobuf */
                        continue;
 
                /* avoid overflowing tobuf */
@@ -253,6 +779,11 @@ deliver(e, firstto)
 
                user = to->q_user;
                e->e_to = to->q_paddr;
 
                user = to->q_user;
                e->e_to = to->q_paddr;
+               if (tTd(10, 5))
+               {
+                       printf("deliver: QDONTSEND ");
+                       printaddr(to, FALSE);
+               }
                to->q_flags |= QDONTSEND;
 
                /*
                to->q_flags |= QDONTSEND;
 
                /*
@@ -263,13 +794,14 @@ deliver(e, firstto)
                if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize)
                {
                        NoReturn = TRUE;
                if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize)
                {
                        NoReturn = TRUE;
-                       usrerr("Message is too large; %ld bytes max", m->m_maxsize);
-                       giveresponse(EX_UNAVAILABLE, m, e);
+                       usrerr("552 Message is too large; %ld bytes max", m->m_maxsize);
+                       giveresponse(EX_UNAVAILABLE, m, NULL, e);
                        continue;
                }
                        continue;
                }
-               if (!checkcompat(to))
+               rcode = checkcompat(to, e);
+               if (rcode != EX_OK)
                {
                {
-                       giveresponse(EX_UNAVAILABLE, m, e);
+                       giveresponse(rcode, m, NULL, e);
                        continue;
                }
 
                        continue;
                }
 
@@ -280,13 +812,8 @@ deliver(e, firstto)
 
                if (bitnset(M_STRIPQ, m->m_flags))
                {
 
                if (bitnset(M_STRIPQ, m->m_flags))
                {
-                       stripquotes(user, TRUE);
-                       stripquotes(host, TRUE);
-               }
-               else
-               {
-                       stripquotes(user, FALSE);
-                       stripquotes(host, FALSE);
+                       stripquotes(user);
+                       stripquotes(host);
                }
 
                /* hack attack -- delivermail compatibility */
                }
 
                /* hack attack -- delivermail compatibility */
@@ -316,16 +843,13 @@ deliver(e, firstto)
                **      with the others, so we fudge on the To person.
                */
 
                **      with the others, so we fudge on the To person.
                */
 
-               if (m == LocalMailer)
+               if (m == FileMailer)
                {
                {
-                       if (user[0] == '/')
-                       {
-                               rcode = mailfile(user, getctladdr(to));
-                               giveresponse(rcode, m, e);
-                               if (rcode == EX_OK)
-                                       to->q_flags |= QSENT;
-                               continue;
-                       }
+                       rcode = mailfile(user, getctladdr(to), e);
+                       giveresponse(rcode, m, NULL, e);
+                       if (rcode == EX_OK)
+                               to->q_flags |= QSENT;
+                       continue;
                }
 
                /*
                }
 
                /*
@@ -378,86 +902,496 @@ deliver(e, firstto)
                expand(*mvp, buf, &buf[sizeof buf - 1], e);
                *pvp++ = newstr(buf);
                if (pvp >= &pv[MAXPV])
                expand(*mvp, buf, &buf[sizeof buf - 1], e);
                *pvp++ = newstr(buf);
                if (pvp >= &pv[MAXPV])
-                       syserr("deliver: pv overflow after $u for %s", pv[0]);
+                       syserr("554 deliver: pv overflow after $u for %s", pv[0]);
+       }
+       *pvp++ = NULL;
+
+       /*
+       **  Call the mailer.
+       **      The argument vector gets built, pipes
+       **      are created as necessary, and we fork & exec as
+       **      appropriate.
+       **      If we are running SMTP, we just need to clean up.
+       */
+
+       if (ctladdr == NULL && m != ProgMailer)
+               ctladdr = &e->e_from;
+#ifdef NAMED_BIND
+       if (ConfigLevel < 2)
+               _res.options &= ~(RES_DEFNAMES | RES_DNSRCH);   /* XXX */
+#endif
+
+       if (tTd(11, 1))
+       {
+               printf("openmailer:");
+               printav(pv);
+       }
+       errno = 0;
+
+       CurHostName = m->m_mailer;
+
+       /*
+       **  Deal with the special case of mail handled through an IPC
+       **  connection.
+       **      In this case we don't actually fork.  We must be
+       **      running SMTP for this to work.  We will return a
+       **      zero pid to indicate that we are running IPC.
+       **  We also handle a debug version that just talks to stdin/out.
+       */
+
+       curhost = NULL;
+
+       /* check for Local Person Communication -- not for mortals!!! */
+       if (strcmp(m->m_mailer, "[LPC]") == 0)
+       {
+               mci = (MCI *) xalloc(sizeof *mci);
+               bzero((char *) mci, sizeof *mci);
+               mci->mci_in = stdin;
+               mci->mci_out = stdout;
+               mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN;
+               mci->mci_mailer = m;
+       }
+       else if (strcmp(m->m_mailer, "[IPC]") == 0 ||
+                strcmp(m->m_mailer, "[TCP]") == 0)
+       {
+#ifdef DAEMON
+               register int i;
+               register u_short port;
+
+               CurHostName = pv[1];
+               curhost = hostsignature(m, pv[1], e);
+
+               if (curhost == NULL || curhost[0] == '\0')
+               {
+                       syserr("null signature");
+                       rcode = EX_OSERR;
+                       goto give_up;
+               }
+
+               if (!clever)
+               {
+                       syserr("554 non-clever IPC");
+                       rcode = EX_OSERR;
+                       goto give_up;
+               }
+               if (pv[2] != NULL)
+                       port = atoi(pv[2]);
+               else
+                       port = 0;
+tryhost:
+               mci = NULL;
+               while (*curhost != '\0')
+               {
+                       register char *p;
+                       static char hostbuf[MAXNAME];
+
+                       mci = NULL;
+
+                       /* pull the next host from the signature */
+                       p = strchr(curhost, ':');
+                       if (p == NULL)
+                               p = &curhost[strlen(curhost)];
+                       strncpy(hostbuf, curhost, p - curhost);
+                       hostbuf[p - curhost] = '\0';
+                       if (*p != '\0')
+                               p++;
+                       curhost = p;
+
+                       /* see if we already know that this host is fried */
+                       CurHostName = hostbuf;
+                       mci = mci_get(hostbuf, m);
+                       if (mci->mci_state != MCIS_CLOSED)
+                       {
+                               if (tTd(11, 1))
+                               {
+                                       printf("openmailer: ");
+                                       mci_dump(mci);
+                               }
+                               CurHostName = mci->mci_host;
+                               break;
+                       }
+                       mci->mci_mailer = m;
+                       if (mci->mci_exitstat != EX_OK)
+                               continue;
+
+                       /* try the connection */
+                       setproctitle("%s %s: %s", e->e_id, hostbuf, "user open");
+                       message("Connecting to %s (%s)...",
+                               hostbuf, m->m_name);
+                       i = makeconnection(hostbuf, port, mci,
+                               bitnset(M_SECURE_PORT, m->m_flags));
+                       mci->mci_exitstat = i;
+                       mci->mci_errno = errno;
+                       if (i == EX_OK)
+                       {
+                               mci->mci_state = MCIS_OPENING;
+                               mci_cache(mci);
+                               break;
+                       }
+                       else if (tTd(11, 1))
+                               printf("openmailer: makeconnection => stat=%d, errno=%d\n",
+                                       i, errno);
+
+
+                       /* enter status of this host */
+                       setstat(i);
+               }
+               mci->mci_pid = 0;
+#else /* no DAEMON */
+               syserr("554 openmailer: no IPC");
+               if (tTd(11, 1))
+                       printf("openmailer: NULL\n");
+               return NULL;
+#endif /* DAEMON */
+       }
+       else
+       {
+               int i;
+               struct stat stbuf;
+
+               /* make absolutely certain 0, 1, and 2 are in use */
+               for (i = 0; i < 3; i++)
+               {
+                       if (fstat(i, &stbuf) < 0)
+                       {
+                               /* oops.... */
+                               int fd;
+
+                               syserr("%s... openmailer(%s): fd %d not open",
+                                       e->e_to, m->m_name, i);
+                               fd = open("/dev/null", O_RDONLY, 0666);
+                               if (fd != i)
+                               {
+                                       (void) dup2(fd, i);
+                                       (void) close(fd);
+                               }
+                       }
+               }
+
+               /* create a pipe to shove the mail through */
+               if (pipe(mpvect) < 0)
+               {
+                       syserr("%s... openmailer(%s): pipe (to mailer)",
+                               e->e_to, m->m_name);
+                       if (tTd(11, 1))
+                               printf("openmailer: NULL\n");
+                       rcode = EX_OSERR;
+                       goto give_up;
+               }
+
+               /* if this mailer speaks smtp, create a return pipe */
+               if (clever && pipe(rpvect) < 0)
+               {
+                       syserr("%s... openmailer(%s): pipe (from mailer)",
+                               e->e_to, m->m_name);
+                       (void) close(mpvect[0]);
+                       (void) close(mpvect[1]);
+                       if (tTd(11, 1))
+                               printf("openmailer: NULL\n");
+                       rcode = EX_OSERR;
+                       goto give_up;
+               }
+
+               /*
+               **  Actually fork the mailer process.
+               **      DOFORK is clever about retrying.
+               **
+               **      Dispose of SIGCHLD signal catchers that may be laying
+               **      around so that endmail will get it.
+               */
+
+               if (e->e_xfp != NULL)
+                       (void) fflush(e->e_xfp);                /* for debugging */
+               (void) fflush(stdout);
+# ifdef SIGCHLD
+               (void) signal(SIGCHLD, SIG_DFL);
+# endif /* SIGCHLD */
+               DOFORK(FORK);
+               /* pid is set by DOFORK */
+               if (pid < 0)
+               {
+                       /* failure */
+                       syserr("%s... openmailer(%s): cannot fork",
+                               e->e_to, m->m_name);
+                       (void) close(mpvect[0]);
+                       (void) close(mpvect[1]);
+                       if (clever)
+                       {
+                               (void) close(rpvect[0]);
+                               (void) close(rpvect[1]);
+                       }
+                       if (tTd(11, 1))
+                               printf("openmailer: NULL\n");
+                       rcode = EX_OSERR;
+                       goto give_up;
+               }
+               else if (pid == 0)
+               {
+                       int i;
+                       int saveerrno;
+                       char **ep;
+                       char *env[MAXUSERENVIRON];
+                       extern char **environ;
+                       extern int DtableSize;
+
+                       /* child -- set up input & exec mailer */
+                       /* make diagnostic output be standard output */
+                       (void) signal(SIGINT, SIG_IGN);
+                       (void) signal(SIGHUP, SIG_IGN);
+                       (void) signal(SIGTERM, SIG_DFL);
+
+                       /* close any other cached connections */
+                       mci_flush(FALSE, mci);
+
+                       /* move into some "safe" directory */
+                       if (m->m_execdir != NULL)
+                       {
+                               char *p, *q;
+                               char buf[MAXLINE];
+
+                               for (p = m->m_execdir; p != NULL; p = q)
+                               {
+                                       q = strchr(p, ':');
+                                       if (q != NULL)
+                                               *q = '\0';
+                                       expand(p, buf, &buf[sizeof buf] - 1, e);
+                                       if (q != NULL)
+                                               *q++ = ':';
+                                       if (tTd(11, 20))
+                                               printf("openmailer: trydir %s\n",
+                                                       buf);
+                                       if (buf[0] != '\0' && chdir(buf) >= 0)
+                                               break;
+                               }
+                       }
+
+                       /* arrange to filter std & diag output of command */
+                       if (clever)
+                       {
+                               (void) close(rpvect[0]);
+                               if (dup2(rpvect[1], STDOUT_FILENO) < 0)
+                               {
+                                       syserr("%s... openmailer(%s): cannot dup pipe %d for stdout",
+                                               e->e_to, m->m_name, rpvect[1]);
+                                       _exit(EX_OSERR);
+                               }
+                               (void) close(rpvect[1]);
+                       }
+                       else if (OpMode == MD_SMTP || HoldErrs)
+                       {
+                               /* put mailer output in transcript */
+                               if (dup2(fileno(e->e_xfp), STDOUT_FILENO) < 0)
+                               {
+                                       syserr("%s... openmailer(%s): cannot dup xscript %d for stdout",
+                                               e->e_to, m->m_name,
+                                               fileno(e->e_xfp));
+                                       _exit(EX_OSERR);
+                               }
+                       }
+                       if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0)
+                       {
+                               syserr("%s... openmailer(%s): cannot dup stdout for stderr",
+                                       e->e_to, m->m_name);
+                               _exit(EX_OSERR);
+                       }
+
+                       /* arrange to get standard input */
+                       (void) close(mpvect[1]);
+                       if (dup2(mpvect[0], STDIN_FILENO) < 0)
+                       {
+                               syserr("%s... openmailer(%s): cannot dup pipe %d for stdin",
+                                       e->e_to, m->m_name, mpvect[0]);
+                               _exit(EX_OSERR);
+                       }
+                       (void) close(mpvect[0]);
+                       if (!bitnset(M_RESTR, m->m_flags))
+                       {
+                               if (ctladdr == NULL || ctladdr->q_uid == 0)
+                               {
+                                       (void) setgid(DefGid);
+                                       (void) initgroups(DefUser, DefGid);
+                                       (void) setuid(DefUid);
+                               }
+                               else
+                               {
+                                       (void) setgid(ctladdr->q_gid);
+                                       (void) initgroups(ctladdr->q_ruser?
+                                               ctladdr->q_ruser: ctladdr->q_user,
+                                               ctladdr->q_gid);
+                                       (void) setuid(ctladdr->q_uid);
+                               }
+                       }
+
+                       /* arrange for all the files to be closed */
+                       for (i = 3; i < DtableSize; i++)
+                       {
+                               register int j;
+                               if ((j = fcntl(i, F_GETFD, 0)) != -1)
+                                       (void)fcntl(i, F_SETFD, j|1);
+                       }
+
+                       /* set up the mailer environment */
+                       i = 0;
+                       env[i++] = "AGENT=sendmail";
+                       for (ep = environ; *ep != NULL; ep++)
+                       {
+                               if (strncmp(*ep, "TZ=", 3) == 0)
+                                       env[i++] = *ep;
+                       }
+                       env[i++] = NULL;
+
+                       /* try to execute the mailer */
+                       execve(m->m_mailer, pv, env);
+                       saveerrno = errno;
+                       syserr("Cannot exec %s", m->m_mailer);
+                       if (m == LocalMailer || transienterror(saveerrno))
+                               _exit(EX_OSERR);
+                       _exit(EX_UNAVAILABLE);
+               }
+
+               /*
+               **  Set up return value.
+               */
+
+               mci = (MCI *) xalloc(sizeof *mci);
+               bzero((char *) mci, sizeof *mci);
+               mci->mci_mailer = m;
+               mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN;
+               mci->mci_pid = pid;
+               (void) close(mpvect[0]);
+               mci->mci_out = fdopen(mpvect[1], "w");
+               if (clever)
+               {
+                       (void) close(rpvect[1]);
+                       mci->mci_in = fdopen(rpvect[0], "r");
+               }
+               else
+               {
+                       mci->mci_flags |= MCIF_TEMP;
+                       mci->mci_in = NULL;
+               }
        }
        }
-       *pvp++ = NULL;
 
        /*
 
        /*
-       **  Call the mailer.
-       **      The argument vector gets built, pipes
-       **      are created as necessary, and we fork & exec as
-       **      appropriate.
-       **      If we are running SMTP, we just need to clean up.
+       **  If we are in SMTP opening state, send initial protocol.
        */
 
        */
 
-       if (ctladdr == NULL)
-               ctladdr = &e->e_from;
-#ifdef NAMED_BIND
-       _res.options &= ~(RES_DEFNAMES | RES_DNSRCH);           /* XXX */
-#endif
-#ifdef SMTP
-       if (clever)
+       if (clever && mci->mci_state != MCIS_CLOSED)
        {
        {
-               rcode = EX_OK;
-#ifdef NAMED_BIND
-               if (host[0] && host[0] != '[')
+               smtpinit(m, mci, e);
+       }
+       if (tTd(11, 1))
+       {
+               printf("openmailer: ");
+               mci_dump(mci);
+       }
+
+       if (mci->mci_state != MCIS_OPEN)
+       {
+               /* couldn't open the mailer */
+               rcode = mci->mci_exitstat;
+               errno = mci->mci_errno;
+               if (rcode == EX_OK)
                {
                {
-                       expand("\001w", buf, &buf[sizeof(buf) - 1], e);
-                       Nmx = getmxrr(host, MxHosts, buf, &rcode);
+                       /* shouldn't happen */
+                       syserr("554 deliver: rcode=%d, mci_state=%d, sig=%s",
+                               rcode, mci->mci_state, firstsig);
+                       rcode = EX_SOFTWARE;
                }
                }
-               else
-#endif
+               else if (rcode == EX_TEMPFAIL && *curhost != '\0')
                {
                {
-                       Nmx = 1;
-                       MxHosts[0] = host;
+                       /* try next MX site */
+                       goto tryhost;
                }
                }
-               if (Nmx >= 0)
+       }
+       else if (!clever)
+       {
+               /*
+               **  Format and send message.
+               */
+
+               putfromline(mci->mci_out, m, e);
+               (*e->e_puthdr)(mci->mci_out, m, e);
+               putline("\n", mci->mci_out, m);
+               (*e->e_putbody)(mci->mci_out, m, e, NULL);
+
+               /* get the exit status */
+               rcode = endmailer(mci, e, pv);
+       }
+       else
+#ifdef SMTP
+       {
+               /*
+               **  Send the MAIL FROM: protocol
+               */
+
+               rcode = smtpmailfrom(m, mci, e);
+               if (rcode == EX_OK)
                {
                {
-                       message(Arpa_Info, "Connecting to %s (%s)...",
-                           MxHosts[0], m->m_name);
-                       if ((rcode = smtpinit(m, pv)) == EX_OK) {
-                               register char *t = tobuf;
-                               register int i;
-
-                               /* send the recipient list */
-                               tobuf[0] = '\0';
-                               for (to = tochain; to; to = to->q_tchain) {
-                                       e->e_to = to->q_paddr;
-                                       if ((i = smtprcpt(to, m)) != EX_OK) {
-                                               markfailure(e, to, i);
-                                               giveresponse(i, m, e);
-                                       }
-                                       else {
-                                               *t++ = ',';
-                                               for (p = to->q_paddr; *p; *t++ = *p++);
-                                       }
-                               }
+                       register char *t = tobuf;
+                       register int i;
 
 
-                               /* now send the data */
-                               if (tobuf[0] == '\0')
-                                       e->e_to = NULL;
-                               else {
-                                       e->e_to = tobuf + 1;
-                                       rcode = smtpdata(m, e);
+                       /* send the recipient list */
+                       tobuf[0] = '\0';
+                       for (to = tochain; to != NULL; to = to->q_tchain)
+                       {
+                               e->e_to = to->q_paddr;
+                               if ((i = smtprcpt(to, m, mci, e)) != EX_OK)
+                               {
+                                       markfailure(e, to, i);
+                                       giveresponse(i, m, mci, e);
                                }
                                }
+                               else
+                               {
+                                       *t++ = ',';
+                                       for (p = to->q_paddr; *p; *t++ = *p++)
+                                               continue;
+                               }
+                       }
 
 
-                               /* now close the connection */
-                               smtpquit(m);
+                       /* now send the data */
+                       if (tobuf[0] == '\0')
+                       {
+                               rcode = EX_OK;
+                               e->e_to = NULL;
+                               if (bitset(MCIF_CACHED, mci->mci_flags))
+                                       smtprset(m, mci, e);
+                       }
+                       else
+                       {
+                               e->e_to = tobuf + 1;
+                               rcode = smtpdata(m, mci, e);
                        }
                        }
+
+                       /* now close the connection */
+                       if (!bitset(MCIF_CACHED, mci->mci_flags))
+                               smtpquit(m, mci, e);
+               }
+               if (rcode != EX_OK && *curhost != '\0')
+               {
+                       /* try next MX site */
+                       goto tryhost;
                }
        }
                }
        }
-       else
-#endif /* SMTP */
+#else /* not SMTP */
        {
        {
-               static int sendoff();
-
-               message(Arpa_Info, "Connecting to %s (%s)...", host, m->m_name);
-               rcode = sendoff(e, m, pv, ctladdr);
+               syserr("554 deliver: need SMTP compiled to use clever mailer");
+               rcode = EX_CONFIG;
+               goto give_up;
        }
        }
+#endif /* SMTP */
 #ifdef NAMED_BIND
 #ifdef NAMED_BIND
-       _res.options |= RES_DEFNAMES | RES_DNSRCH;      /* XXX */
+       if (ConfigLevel < 2)
+               _res.options |= RES_DEFNAMES | RES_DNSRCH;      /* XXX */
 #endif
 
 #endif
 
+       /* arrange a return receipt if requested */
+       if (e->e_receiptto != NULL && bitnset(M_LOCALMAILER, m->m_flags))
+       {
+               e->e_flags |= EF_SENDRECEIPT;
+               /* do we want to send back more info? */
+       }
+
        /*
        **  Do final status disposal.
        **      We check for something in tobuf for the SMTP case.
        /*
        **  Do final status disposal.
        **      We check for something in tobuf for the SMTP case.
@@ -465,13 +1399,23 @@ deliver(e, firstto)
        **              addressees.
        */
 
        **              addressees.
        */
 
+  give_up:
        if (tobuf[0] != '\0')
        if (tobuf[0] != '\0')
-               giveresponse(rcode, m, e);
+               giveresponse(rcode, m, mci, e);
        for (to = tochain; to != NULL; to = to->q_tchain)
        for (to = tochain; to != NULL; to = to->q_tchain)
+       {
                if (rcode != EX_OK)
                        markfailure(e, to, rcode);
                else
                if (rcode != EX_OK)
                        markfailure(e, to, rcode);
                else
+               {
                        to->q_flags |= QSENT;
                        to->q_flags |= QSENT;
+                       e->e_nsent++;
+               }
+       }
+
+       /*
+       **  Restore state and return.
+       */
 
        errno = 0;
        define('g', (char *) NULL, e);
 
        errno = 0;
        define('g', (char *) NULL, e);
@@ -499,152 +1443,53 @@ markfailure(e, q, rcode)
        register ADDRESS *q;
        int rcode;
 {
        register ADDRESS *q;
        int rcode;
 {
+       char buf[MAXLINE];
+
        if (rcode == EX_OK)
                return;
        else if (rcode != EX_TEMPFAIL && rcode != EX_IOERR && rcode != EX_OSERR)
                q->q_flags |= QBADADDR;
        if (rcode == EX_OK)
                return;
        else if (rcode != EX_TEMPFAIL && rcode != EX_IOERR && rcode != EX_OSERR)
                q->q_flags |= QBADADDR;
-       else if (curtime() > e->e_ctime + TimeOut)
+       else if (curtime() > e->e_ctime + TimeOuts.to_q_return)
        {
        {
-               extern char *pintvl();
-               char buf[MAXLINE];
-
                if (!bitset(EF_TIMEOUT, e->e_flags))
                {
                        (void) sprintf(buf, "Cannot send message for %s",
                if (!bitset(EF_TIMEOUT, e->e_flags))
                {
                        (void) sprintf(buf, "Cannot send message for %s",
-                               pintvl(TimeOut, FALSE));
+                               pintvl(TimeOuts.to_q_return, FALSE));
                        if (e->e_message != NULL)
                                free(e->e_message);
                        e->e_message = newstr(buf);
                        if (e->e_message != NULL)
                                free(e->e_message);
                        e->e_message = newstr(buf);
-                       message(Arpa_Info, buf);
+                       message(buf);
                }
                q->q_flags |= QBADADDR;
                e->e_flags |= EF_TIMEOUT;
                }
                q->q_flags |= QBADADDR;
                e->e_flags |= EF_TIMEOUT;
+               fprintf(e->e_xfp, "421 %s... Message timed out\n", q->q_paddr);
        }
        else
        }
        else
-               q->q_flags |= QQUEUEUP;
-}
-\f/*
-**  DOFORK -- do a fork, retrying a couple of times on failure.
-**
-**     This MUST be a macro, since after a vfork we are running
-**     two processes on the same stack!!!
-**
-**     Parameters:
-**             none.
-**
-**     Returns:
-**             From a macro???  You've got to be kidding!
-**
-**     Side Effects:
-**             Modifies the ==> LOCAL <== variable 'pid', leaving:
-**                     pid of child in parent, zero in child.
-**                     -1 on unrecoverable error.
-**
-**     Notes:
-**             I'm awfully sorry this looks so awful.  That's
-**             vfork for you.....
-*/
-
-# define NFORKTRIES    5
-# ifdef VMUNIX
-# define XFORK vfork
-# else VMUNIX
-# define XFORK fork
-# endif VMUNIX
-
-# define DOFORK(fORKfN) \
-{\
-       register int i;\
-\
-       for (i = NFORKTRIES; --i >= 0; )\
-       {\
-               pid = fORKfN();\
-               if (pid >= 0)\
-                       break;\
-               if (i > 0)\
-                       sleep((unsigned) NFORKTRIES - i);\
-       }\
-}
-\f/*
-**  DOFORK -- simple fork interface to DOFORK.
-**
-**     Parameters:
-**             none.
-**
-**     Returns:
-**             pid of child in parent.
-**             zero in child.
-**             -1 on error.
-**
-**     Side Effects:
-**             returns twice, once in parent and once in child.
-*/
-
-dofork()
-{
-       register int pid;
-
-       DOFORK(fork);
-       return (pid);
-}
-\f/*
-**  SENDOFF -- send off call to mailer & collect response.
-**
-**     Parameters:
-**             e -- the envelope to mail.
-**             m -- mailer descriptor.
-**             pvp -- parameter vector to send to it.
-**             ctladdr -- an address pointer controlling the
-**                     user/groupid etc. of the mailer.
-**
-**     Returns:
-**             exit status of mailer.
-**
-**     Side Effects:
-**             none.
-*/
-static
-sendoff(e, m, pvp, ctladdr)
-       register ENVELOPE *e;
-       MAILER *m;
-       char **pvp;
-       ADDRESS *ctladdr;
-{
-       auto FILE *mfile;
-       auto FILE *rfile;
-       register int i;
-       int pid;
-
-       /*
-       **  Create connection to mailer.
-       */
-
-       pid = openmailer(m, pvp, ctladdr, FALSE, &mfile, &rfile);
-       if (pid < 0)
-               return (-1);
-
-       /*
-       **  Format and send message.
-       */
-
-       putfromline(mfile, m);
-       (*e->e_puthdr)(mfile, m, e);
-       putline("\n", mfile, m);
-       (*e->e_putbody)(mfile, m, e);
-       (void) fclose(mfile);
-       if (rfile != NULL)
-               (void) fclose(rfile);
-
-       i = endmailer(pid, pvp[0]);
-
-       /* arrange a return receipt if requested */
-       if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags))
        {
        {
-               e->e_flags |= EF_SENDRECEIPT;
-               /* do we want to send back more info? */
+               q->q_flags |= QQUEUEUP;
+               if (TimeOuts.to_q_warning > 0 &&
+                   curtime() > e->e_ctime + TimeOuts.to_q_warning)
+               {
+                       if (!bitset(EF_WARNING, e->e_flags) &&
+                           e->e_class >= 0 &&
+                           strcmp(e->e_from.q_paddr, "<>") != 0)
+                       {
+                               (void) sprintf(buf,
+                                       "warning: cannot send message for %s",
+                                       pintvl(TimeOuts.to_q_warning, FALSE));
+                               if (e->e_message != NULL)
+                                       free(e->e_message);
+                               e->e_message = newstr(buf);
+                               message(buf);
+                               e->e_flags |= EF_WARNING|EF_TIMEOUT;
+                       }
+                       fprintf(e->e_xfp,
+                               "%s... Warning: message still undelivered after %s\n",
+                               q->q_paddr, pintvl(TimeOuts.to_q_warning, FALSE));
+                       fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
+                               pintvl(TimeOuts.to_q_return, FALSE));
+               }
        }
        }
-
-       return (i);
 }
 \f/*
 **  ENDMAILER -- Wait for mailer to terminate.
 }
 \f/*
 **  ENDMAILER -- Wait for mailer to terminate.
@@ -656,7 +1501,9 @@ sendoff(e, m, pvp, ctladdr)
 **
 **     Parameters:
 **             pid -- pid of mailer.
 **
 **     Parameters:
 **             pid -- pid of mailer.
-**             name -- name of mailer (for error messages).
+**             e -- the current envelope.
+**             pv -- the parameter vector that invoked the mailer
+**                     (for error messages).
 **
 **     Returns:
 **             exit code of mailer.
 **
 **     Returns:
 **             exit code of mailer.
@@ -665,295 +1512,56 @@ sendoff(e, m, pvp, ctladdr)
 **             none.
 */
 
 **             none.
 */
 
-endmailer(pid, name)
-       int pid;
-       char *name;
+endmailer(mci, e, pv)
+       register MCI *mci;
+       register ENVELOPE *e;
+       char **pv;
 {
        int st;
 
 {
        int st;
 
-       /* in the IPC case there is nothing to wait for */
-       if (pid == 0)
-               return (EX_OK);
-
-       /* wait for the mailer process to die and collect status */
-       st = waitfor(pid);
-       if (st == -1)
-       {
-               syserr("endmailer %s: wait", name);
-               return (EX_SOFTWARE);
-       }
-
-       /* see if it died a horrid death */
-       if ((st & 0377) != 0)
-       {
-               syserr("mailer %s died with signal %o", name, st);
-               ExitStat = EX_TEMPFAIL;
-               return (EX_TEMPFAIL);
-       }
-
-       /* normal death -- return status */
-       st = (st >> 8) & 0377;
-       return (st);
-}
-\f/*
-**  OPENMAILER -- open connection to mailer.
-**
-**     Parameters:
-**             m -- mailer descriptor.
-**             pvp -- parameter vector to pass to mailer.
-**             ctladdr -- controlling address for user.
-**             clever -- create a full duplex connection.
-**             pmfile -- pointer to mfile (to mailer) connection.
-**             prfile -- pointer to rfile (from mailer) connection.
-**
-**     Returns:
-**             pid of mailer ( > 0 ).
-**             -1 on error.
-**             zero on an IPC connection.
-**
-**     Side Effects:
-**             creates a mailer in a subprocess.
-*/
-
-openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
-       MAILER *m;
-       char **pvp;
-       ADDRESS *ctladdr;
-       bool clever;
-       FILE **pmfile;
-       FILE **prfile;
-{
-       int pid;
-       int mpvect[2];
-       int rpvect[2];
-       FILE *mfile = NULL;
-       FILE *rfile = NULL;
-       extern FILE *fdopen();
-
-       if (tTd(11, 1))
-       {
-               printf("openmailer:");
-               printav(pvp);
-       }
-       errno = 0;
-
-       CurHostName = m->m_mailer;
-
-       /*
-       **  Deal with the special case of mail handled through an IPC
-       **  connection.
-       **      In this case we don't actually fork.  We must be
-       **      running SMTP for this to work.  We will return a
-       **      zero pid to indicate that we are running IPC.
-       **  We also handle a debug version that just talks to stdin/out.
-       */
-
-       /* check for Local Person Communication -- not for mortals!!! */
-       if (strcmp(m->m_mailer, "[LPC]") == 0)
-       {
-               *pmfile = stdout;
-               *prfile = stdin;
-               return (0);
-       }
-
-       if (strcmp(m->m_mailer, "[IPC]") == 0)
-       {
-#ifdef HOSTINFO
-               register STAB *st;
-               extern STAB *stab();
-#endif HOSTINFO
-#ifdef DAEMON
-               register int i, j;
-               register u_short port;
-
-               CurHostName = pvp[1];
-               if (!clever)
-                       syserr("non-clever IPC");
-               if (pvp[2] != NULL)
-                       port = atoi(pvp[2]);
-               else
-                       port = 0;
-               for (j = 0; j < Nmx; j++)
-               {
-                       CurHostName = MxHosts[j];
-#ifdef HOSTINFO
-               /* see if we have already determined that this host is fried */
-                       st = stab(MxHosts[j], ST_HOST, ST_FIND);
-                       if (st == NULL || st->s_host.ho_exitstat == EX_OK) {
-                               if (j > 1)
-                                       message(Arpa_Info,
-                                           "Connecting to %s (%s)...",
-                                           MxHosts[j], m->m_name);
-                               i = makeconnection(MxHosts[j], port, pmfile, prfile);
-                       }
-                       else
-                       {
-                               i = st->s_host.ho_exitstat;
-                               errno = st->s_host.ho_errno;
-                       }
-#else HOSTINFO
-                       i = makeconnection(MxHosts[j], port, pmfile, prfile);
-#endif HOSTINFO
-                       if (i != EX_OK)
-                       {
-#ifdef HOSTINFO
-                               /* enter status of this host */
-                               if (st == NULL)
-                                       st = stab(MxHosts[j], ST_HOST, ST_ENTER);
-                               st->s_host.ho_exitstat = i;
-                               st->s_host.ho_errno = errno;
-#endif HOSTINFO
-                               ExitStat = i;
-                               continue;
-                       }
-                       else
-                               return (0);
-               }
-               return (-1);
-#else DAEMON
-               syserr("openmailer: no IPC");
-               return (-1);
-#endif DAEMON
-       }
-
-       /* create a pipe to shove the mail through */
-       if (pipe(mpvect) < 0)
-       {
-               syserr("openmailer: pipe (to mailer)");
-               return (-1);
-       }
-
-#ifdef SMTP
-       /* if this mailer speaks smtp, create a return pipe */
-       if (clever && pipe(rpvect) < 0)
-       {
-               syserr("openmailer: pipe (from mailer)");
-               (void) close(mpvect[0]);
-               (void) close(mpvect[1]);
-               return (-1);
-       }
-#endif SMTP
+       /* close any connections */
+       if (mci->mci_in != NULL)
+               (void) xfclose(mci->mci_in, pv[0], "mci_in");
+       if (mci->mci_out != NULL)
+               (void) xfclose(mci->mci_out, pv[0], "mci_out");
+       mci->mci_in = mci->mci_out = NULL;
+       mci->mci_state = MCIS_CLOSED;
 
 
-       /*
-       **  Actually fork the mailer process.
-       **      DOFORK is clever about retrying.
-       **
-       **      Dispose of SIGCHLD signal catchers that may be laying
-       **      around so that endmail will get it.
-       */
+       /* in the IPC case there is nothing to wait for */
+       if (mci->mci_pid == 0)
+               return (EX_OK);
 
 
-       if (CurEnv->e_xfp != NULL)
-               (void) fflush(CurEnv->e_xfp);           /* for debugging */
-       (void) fflush(stdout);
-# ifdef SIGCHLD
-       (void) signal(SIGCHLD, SIG_DFL);
-# endif SIGCHLD
-       DOFORK(XFORK);
-       /* pid is set by DOFORK */
-       if (pid < 0)
+       /* wait for the mailer process to die and collect status */
+       st = waitfor(mci->mci_pid);
+       if (st == -1)
        {
        {
-               /* failure */
-               syserr("openmailer: cannot fork");
-               (void) close(mpvect[0]);
-               (void) close(mpvect[1]);
-#ifdef SMTP
-               if (clever)
-               {
-                       (void) close(rpvect[0]);
-                       (void) close(rpvect[1]);
-               }
-#endif SMTP
-               return (-1);
+               syserr("endmailer %s: wait", pv[0]);
+               return (EX_SOFTWARE);
        }
        }
-       else if (pid == 0)
-       {
-               int i;
-               extern int DtableSize;
-
-               /* child -- set up input & exec mailer */
-               /* make diagnostic output be standard output */
-               (void) signal(SIGINT, SIG_IGN);
-               (void) signal(SIGHUP, SIG_IGN);
-               (void) signal(SIGTERM, SIG_DFL);
 
 
-               /* arrange to filter standard & diag output of command */
-               if (clever)
-               {
-                       (void) close(rpvect[0]);
-                       (void) close(1);
-                       (void) dup(rpvect[1]);
-                       (void) close(rpvect[1]);
-               }
-               else if (OpMode == MD_SMTP || HoldErrs)
-               {
-                       /* put mailer output in transcript */
-                       (void) close(1);
-                       (void) dup(fileno(CurEnv->e_xfp));
-               }
-               (void) close(2);
-               (void) dup(1);
+       /* see if it died a horrid death */
+       if ((st & 0377) != 0)
+       {
+               syserr("mailer %s died with signal %o", pv[0], st);
 
 
-               /* arrange to get standard input */
-               (void) close(mpvect[1]);
-               (void) close(0);
-               if (dup(mpvect[0]) < 0)
-               {
-                       syserr("Cannot dup to zero!");
-                       _exit(EX_OSERR);
-               }
-               (void) close(mpvect[0]);
-               if (!bitnset(M_RESTR, m->m_flags))
+               /* log the arguments */
+               if (e->e_xfp != NULL)
                {
                {
-                       if (ctladdr == NULL || ctladdr->q_uid == 0)
-                       {
-                               (void) setgid(DefGid);
-                               (void) initgroups(DefUser, DefGid);
-                               (void) setuid(DefUid);
-                       }
-                       else
-                       {
-                               (void) setgid(ctladdr->q_gid);
-                               (void) initgroups(ctladdr->q_ruser?
-                                       ctladdr->q_ruser: ctladdr->q_user,
-                                       ctladdr->q_gid);
-                               (void) setuid(ctladdr->q_uid);
-                       }
-               }
+                       register char **av;
 
 
-               /* arrange for all the files to be closed */
-               for (i = 3; i < DtableSize; i++) {
-                       register int j;
-                       if ((j = fcntl(i, F_GETFD, 0)) != -1)
-                               (void)fcntl(i, F_SETFD, j|1);
+                       fprintf(e->e_xfp, "Arguments:");
+                       for (av = pv; *av != NULL; av++)
+                               fprintf(e->e_xfp, " %s", *av);
+                       fprintf(e->e_xfp, "\n");
                }
 
                }
 
-               /* try to execute the mailer */
-               execve(m->m_mailer, pvp, UserEnviron);
-               syserr("Cannot exec %s", m->m_mailer);
-               if (m == LocalMailer || errno == EIO || errno == EAGAIN ||
-                   errno == ENOMEM || errno == EPROCLIM)
-                       _exit(EX_TEMPFAIL);
-               else
-                       _exit(EX_UNAVAILABLE);
+               ExitStat = EX_TEMPFAIL;
+               return (EX_TEMPFAIL);
        }
 
        }
 
-       /*
-       **  Set up return value.
-       */
-
-       (void) close(mpvect[0]);
-       mfile = fdopen(mpvect[1], "w");
-       if (clever)
-       {
-               (void) close(rpvect[1]);
-               rfile = fdopen(rpvect[0], "r");
-       } else
-               rfile = NULL;
-
-       *pmfile = mfile;
-       *prfile = rfile;
-
-       return (pid);
+       /* normal death -- return status */
+       st = (st >> 8) & 0377;
+       return (st);
 }
 \f/*
 **  GIVERESPONSE -- Interpret an error response from a mailer
 }
 \f/*
 **  GIVERESPONSE -- Interpret an error response from a mailer
@@ -962,7 +1570,10 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
 **             stat -- the status code from the mailer (high byte
 **                     only; core dumps must have been taken care of
 **                     already).
 **             stat -- the status code from the mailer (high byte
 **                     only; core dumps must have been taken care of
 **                     already).
-**             m -- the mailer descriptor for this mailer.
+**             m -- the mailer info for this mailer.
+**             mci -- the mailer connection info -- can be NULL if the
+**                     response is given before the connection is made.
+**             e -- the current envelope.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -972,12 +1583,13 @@ openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
 **             ExitStat may be set.
 */
 
 **             ExitStat may be set.
 */
 
-giveresponse(stat, m, e)
+giveresponse(stat, m, mci, e)
        int stat;
        register MAILER *m;
        int stat;
        register MAILER *m;
+       register MCI *mci;
        ENVELOPE *e;
 {
        ENVELOPE *e;
 {
-       register char *statmsg;
+       register const char *statmsg;
        extern char *SysExMsg[];
        register int i;
        extern int N_SysEx;
        extern char *SysExMsg[];
        register int i;
        extern int N_SysEx;
@@ -986,18 +1598,20 @@ giveresponse(stat, m, e)
 #endif
        char buf[MAXLINE];
 
 #endif
        char buf[MAXLINE];
 
-#ifdef lint
-       if (m == NULL)
-               return;
-#endif lint
-
        /*
        **  Compute status message from code.
        */
 
        i = stat - EX__BASE;
        if (stat == 0)
        /*
        **  Compute status message from code.
        */
 
        i = stat - EX__BASE;
        if (stat == 0)
+       {
                statmsg = "250 Sent";
                statmsg = "250 Sent";
+               if (e->e_statmsg != NULL)
+               {
+                       (void) sprintf(buf, "%s (%s)", statmsg, e->e_statmsg);
+                       statmsg = buf;
+               }
+       }
        else if (i < 0 || i > N_SysEx)
        {
                (void) sprintf(buf, "554 unknown mailer error %d", stat);
        else if (i < 0 || i > N_SysEx)
        {
                (void) sprintf(buf, "554 unknown mailer error %d", stat);
@@ -1006,32 +1620,24 @@ giveresponse(stat, m, e)
        }
        else if (stat == EX_TEMPFAIL)
        {
        }
        else if (stat == EX_TEMPFAIL)
        {
-               (void) strcpy(buf, SysExMsg[i]);
+               (void) strcpy(buf, SysExMsg[i] + 1);
 #ifdef NAMED_BIND
                if (h_errno == TRY_AGAIN)
 #ifdef NAMED_BIND
                if (h_errno == TRY_AGAIN)
-               {
-                       extern char *errstring();
-
                        statmsg = errstring(h_errno+MAX_ERRNO);
                        statmsg = errstring(h_errno+MAX_ERRNO);
-               }
                else
 #endif
                {
                        if (errno != 0)
                else
 #endif
                {
                        if (errno != 0)
-                       {
-                               extern char *errstring();
-
                                statmsg = errstring(errno);
                                statmsg = errstring(errno);
-                       }
                        else
                        {
 #ifdef SMTP
                                extern char SmtpError[];
 
                                statmsg = SmtpError;
                        else
                        {
 #ifdef SMTP
                                extern char SmtpError[];
 
                                statmsg = SmtpError;
-#else SMTP
+#else /* SMTP */
                                statmsg = NULL;
                                statmsg = NULL;
-#endif SMTP
+#endif /* SMTP */
                        }
                }
                if (statmsg != NULL && statmsg[0] != '\0')
                        }
                }
                if (statmsg != NULL && statmsg[0] != '\0')
@@ -1044,6 +1650,11 @@ giveresponse(stat, m, e)
        else
        {
                statmsg = SysExMsg[i];
        else
        {
                statmsg = SysExMsg[i];
+               if (*statmsg++ == ':')
+               {
+                       (void) sprintf(buf, "%s: %s", statmsg, errstring(errno));
+                       statmsg = buf;
+               }
        }
 
        /*
        }
 
        /*
@@ -1051,11 +1662,11 @@ giveresponse(stat, m, e)
        */
 
        if (stat == EX_OK || stat == EX_TEMPFAIL)
        */
 
        if (stat == EX_OK || stat == EX_TEMPFAIL)
-               message(Arpa_Info, &statmsg[4]);
+               message(&statmsg[4], errstring(errno));
        else
        {
                Errors++;
        else
        {
                Errors++;
-               usrerr(statmsg);
+               usrerr(statmsg, errstring(errno));
        }
 
        /*
        }
 
        /*
@@ -1065,8 +1676,8 @@ giveresponse(stat, m, e)
        **      that.
        */
 
        **      that.
        */
 
-       if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2))
-               logdelivery(&statmsg[4]);
+       if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6))
+               logdelivery(m, mci, &statmsg[4], e);
 
        if (stat != EX_TEMPFAIL)
                setstat(stat);
 
        if (stat != EX_TEMPFAIL)
                setstat(stat);
@@ -1085,7 +1696,11 @@ giveresponse(stat, m, e)
 **  LOGDELIVERY -- log the delivery in the system log
 **
 **     Parameters:
 **  LOGDELIVERY -- log the delivery in the system log
 **
 **     Parameters:
-**             stat -- the message to print for the status
+**             m -- the mailer info.  Can be NULL for initial queue.
+**             mci -- the mailer connection info -- can be NULL if the
+**                     log is occuring when no connection is active.
+**             stat -- the message to print for the status.
+**             e -- the current envelope.
 **
 **     Returns:
 **             none
 **
 **     Returns:
 **             none
@@ -1094,15 +1709,52 @@ giveresponse(stat, m, e)
 **             none
 */
 
 **             none
 */
 
-logdelivery(stat)
+logdelivery(m, mci, stat, e)
+       MAILER *m;
+       register MCI *mci;
        char *stat;
        char *stat;
+       register ENVELOPE *e;
 {
 {
-       extern char *pintvl();
-
 # ifdef LOG
 # ifdef LOG
-       syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", CurEnv->e_id,
-              CurEnv->e_to, pintvl(curtime() - CurEnv->e_ctime, TRUE), stat);
-# endif LOG
+       char buf[512];
+
+       (void) sprintf(buf, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE));
+
+       if (m != NULL)
+       {
+               (void) strcat(buf, ", mailer=");
+               (void) strcat(buf, m->m_name);
+       }
+
+       if (mci != NULL && mci->mci_host != NULL)
+       {
+# ifdef DAEMON
+               extern SOCKADDR CurHostAddr;
+# endif
+
+               (void) strcat(buf, ", relay=");
+               (void) strcat(buf, mci->mci_host);
+
+# ifdef DAEMON
+               (void) strcat(buf, " (");
+               (void) strcat(buf, anynet_ntoa(&CurHostAddr));
+               (void) strcat(buf, ")");
+# endif
+       }
+       else
+       {
+               char *p = macvalue('h', e);
+
+               if (p != NULL && p[0] != '\0')
+               {
+                       (void) strcat(buf, ", relay=");
+                       (void) strcat(buf, p);
+               }
+       }
+               
+       syslog(LOG_INFO, "%s: to=%s, %s, stat=%s",
+              e->e_id, e->e_to, buf, stat);
+# endif /* LOG */
 }
 \f/*
 **  PUTFROMLINE -- output a UNIX-style from line (or whatever)
 }
 \f/*
 **  PUTFROMLINE -- output a UNIX-style from line (or whatever)
@@ -1125,11 +1777,12 @@ logdelivery(stat)
 **             outputs some text to fp.
 */
 
 **             outputs some text to fp.
 */
 
-putfromline(fp, m)
+putfromline(fp, m, e)
        register FILE *fp;
        register MAILER *m;
        register FILE *fp;
        register MAILER *m;
+       ENVELOPE *e;
 {
 {
-       char *template = "\001l\n";
+       char *template = "\201l\n";
        char buf[MAXLINE];
 
        if (bitnset(M_NHDR, m->m_flags))
        char buf[MAXLINE];
 
        if (bitnset(M_NHDR, m->m_flags))
@@ -1141,19 +1794,19 @@ putfromline(fp, m)
                char *bang;
                char xbuf[MAXLINE];
 
                char *bang;
                char xbuf[MAXLINE];
 
-               expand("\001g", buf, &buf[sizeof buf - 1], CurEnv);
-               bang = index(buf, '!');
+               expand("\201g", buf, &buf[sizeof buf - 1], e);
+               bang = strchr(buf, '!');
                if (bang == NULL)
                if (bang == NULL)
-                       syserr("No ! in UUCP! (%s)", buf);
+                       syserr("554 No ! in UUCP! (%s)", buf);
                else
                {
                        *bang++ = '\0';
                else
                {
                        *bang++ = '\0';
-                       (void) sprintf(xbuf, "From %s  \001d remote from %s\n", bang, buf);
+                       (void) sprintf(xbuf, "From %s  \201d remote from %s\n", bang, buf);
                        template = xbuf;
                }
        }
                        template = xbuf;
                }
        }
-# endif UGLYUUCP
-       expand(template, buf, &buf[sizeof buf - 1], CurEnv);
+# endif /* UGLYUUCP */
+       expand(template, buf, &buf[sizeof buf - 1], e);
        putline(buf, fp, m);
 }
 \f/*
        putline(buf, fp, m);
 }
 \f/*
@@ -1163,6 +1816,8 @@ putfromline(fp, m)
 **             fp -- file to output onto.
 **             m -- a mailer descriptor to control output format.
 **             e -- the envelope to put out.
 **             fp -- file to output onto.
 **             m -- a mailer descriptor to control output format.
 **             e -- the envelope to put out.
+**             separator -- if non-NULL, a message separator that must
+**                     not be permitted in the resulting message.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -1171,10 +1826,11 @@ putfromline(fp, m)
 **             The message is written onto fp.
 */
 
 **             The message is written onto fp.
 */
 
-putbody(fp, m, e)
+putbody(fp, m, e, separator)
        FILE *fp;
        MAILER *m;
        register ENVELOPE *e;
        FILE *fp;
        MAILER *m;
        register ENVELOPE *e;
+       char *separator;
 {
        char buf[MAXLINE];
 
 {
        char buf[MAXLINE];
 
@@ -1202,6 +1858,14 @@ putbody(fp, m, e)
                        if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) &&
                            strncmp(buf, "From ", 5) == 0)
                                (void) putc('>', fp);
                        if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) &&
                            strncmp(buf, "From ", 5) == 0)
                                (void) putc('>', fp);
+                       if (buf[0] == '-' && buf[1] == '-' && separator != NULL)
+                       {
+                               /* possible separator */
+                               int sl = strlen(separator);
+
+                               if (strncmp(&buf[2], separator, sl) == 0)
+                                       (void) putc(' ', fp);
+                       }
                        putline(buf, fp, m);
                }
 
                        putline(buf, fp, m);
                }
 
@@ -1212,6 +1876,10 @@ putbody(fp, m, e)
                }
        }
 
                }
        }
 
+       /* some mailers want extra blank line at end of message */
+       if (bitnset(M_BLANKEND, m->m_flags) && buf[0] != '\0' && buf[0] != '\n')
+               putline("", fp, m);
+
        (void) fflush(fp);
        if (ferror(fp) && errno != EPIPE)
        {
        (void) fflush(fp);
        if (ferror(fp) && errno != EPIPE)
        {
@@ -1246,13 +1914,20 @@ putbody(fp, m, e)
 **             none.
 */
 
 **             none.
 */
 
-mailfile(filename, ctladdr)
+mailfile(filename, ctladdr, e)
        char *filename;
        ADDRESS *ctladdr;
        char *filename;
        ADDRESS *ctladdr;
+       register ENVELOPE *e;
 {
        register FILE *f;
        register int pid;
 {
        register FILE *f;
        register int pid;
-       ENVELOPE *e = CurEnv;
+       int mode;
+
+       if (tTd(11, 1))
+       {
+               printf("mailfile %s\n  ctladdr=", filename);
+               printaddr(ctladdr, FALSE);
+       }
 
        /*
        **  Fork so we can change permissions here.
 
        /*
        **  Fork so we can change permissions here.
@@ -1273,59 +1948,83 @@ mailfile(filename, ctladdr)
                (void) signal(SIGHUP, SIG_DFL);
                (void) signal(SIGTERM, SIG_DFL);
                (void) umask(OldUmask);
                (void) signal(SIGHUP, SIG_DFL);
                (void) signal(SIGTERM, SIG_DFL);
                (void) umask(OldUmask);
+
                if (stat(filename, &stb) < 0)
                if (stat(filename, &stb) < 0)
-               {
-                       errno = 0;
-                       stb.st_mode = 0666;
-               }
+                       stb.st_mode = FileMode;
+               mode = stb.st_mode;
+
+               /* limit the errors to those actually caused in the child */
+               errno = 0;
+               ExitStat = EX_OK;
+
                if (bitset(0111, stb.st_mode))
                        exit(EX_CANTCREAT);
                if (ctladdr == NULL)
                        ctladdr = &e->e_from;
                if (bitset(0111, stb.st_mode))
                        exit(EX_CANTCREAT);
                if (ctladdr == NULL)
                        ctladdr = &e->e_from;
+               else
+               {
+                       /* ignore setuid and setgid bits */
+                       mode &= ~(S_ISGID|S_ISUID);
+               }
+
                /* we have to open the dfile BEFORE setuid */
                /* we have to open the dfile BEFORE setuid */
-               if (e->e_dfp == NULL &&  e->e_df != NULL)
+               if (e->e_dfp == NULL && e->e_df != NULL)
                {
                        e->e_dfp = fopen(e->e_df, "r");
                {
                        e->e_dfp = fopen(e->e_df, "r");
-                       if (e->e_dfp == NULL) {
+                       if (e->e_dfp == NULL)
+                       {
                                syserr("mailfile: Cannot open %s for %s from %s",
                                syserr("mailfile: Cannot open %s for %s from %s",
-                               e->e_df, e->e_to, e->e_from);
+                                       e->e_df, e->e_to, e->e_from);
                        }
                }
 
                        }
                }
 
-               if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0)
+               if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0)
                {
                {
-                       if (ctladdr->q_uid == 0) {
+                       if (ctladdr->q_uid == 0)
+                       {
                                (void) setgid(DefGid);
                                (void) initgroups(DefUser, DefGid);
                                (void) setgid(DefGid);
                                (void) initgroups(DefUser, DefGid);
-                       } else {
+                       }
+                       else
+                       {
                                (void) setgid(ctladdr->q_gid);
                                (void) setgid(ctladdr->q_gid);
-                               (void) initgroups(ctladdr->q_ruser?
-                                       ctladdr->q_ruser: ctladdr->q_user,
+                               (void) initgroups(ctladdr->q_ruser ?
+                                       ctladdr->q_ruser : ctladdr->q_user,
                                        ctladdr->q_gid);
                        }
                }
                                        ctladdr->q_gid);
                        }
                }
-               if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0)
+               if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0)
                {
                        if (ctladdr->q_uid == 0)
                                (void) setuid(DefUid);
                        else
                                (void) setuid(ctladdr->q_uid);
                }
                {
                        if (ctladdr->q_uid == 0)
                                (void) setuid(DefUid);
                        else
                                (void) setuid(ctladdr->q_uid);
                }
-               f = dfopen(filename, "a");
+               FileName = filename;
+               LineNumber = 0;
+               f = dfopen(filename, O_WRONLY|O_CREAT|O_APPEND, FileMode);
                if (f == NULL)
                if (f == NULL)
+               {
+                       message("554 cannot open");
                        exit(EX_CANTCREAT);
                        exit(EX_CANTCREAT);
+               }
 
 
-               putfromline(f, ProgMailer);
-               (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv);
-               putline("\n", f, ProgMailer);
-               (*CurEnv->e_putbody)(f, ProgMailer, CurEnv);
-               putline("\n", f, ProgMailer);
-               (void) fclose(f);
+               putfromline(f, FileMailer, e);
+               (*e->e_puthdr)(f, FileMailer, e);
+               putline("\n", f, FileMailer);
+               (*e->e_putbody)(f, FileMailer, e, NULL);
+               putline("\n", f, FileMailer);
+               if (ferror(f))
+               {
+                       message("451 I/O error");
+                       setstat(EX_IOERR);
+               }
+               (void) xfclose(f, "mailfile", filename);
                (void) fflush(stdout);
 
                /* reset ISUID & ISGID bits for paranoid systems */
                (void) chmod(filename, (int) stb.st_mode);
                (void) fflush(stdout);
 
                /* reset ISUID & ISGID bits for paranoid systems */
                (void) chmod(filename, (int) stb.st_mode);
-               exit(EX_OK);
+               exit(ExitStat);
                /*NOTREACHED*/
        }
        else
                /*NOTREACHED*/
        }
        else
@@ -1342,212 +2041,139 @@ mailfile(filename, ctladdr)
        }
 }
 \f/*
        }
 }
 \f/*
-**  SENDALL -- actually send all the messages.
+**  HOSTSIGNATURE -- return the "signature" for a host.
+**
+**     The signature describes how we are going to send this -- it
+**     can be just the hostname (for non-Internet hosts) or can be
+**     an ordered list of MX hosts.
 **
 **     Parameters:
 **
 **     Parameters:
-**             e -- the envelope to send.
-**             mode -- the delivery mode to use.  If SM_DEFAULT, use
-**                     the current SendMode.
+**             m -- the mailer describing this host.
+**             host -- the host name.
+**             e -- the current envelope.
 **
 **     Returns:
 **
 **     Returns:
-**             none.
+**             The signature for this host.
 **
 **     Side Effects:
 **
 **     Side Effects:
-**             Scans the send lists and sends everything it finds.
-**             Delivers any appropriate error messages.
-**             If we are running in a non-interactive mode, takes the
-**                     appropriate action.
+**             Can tweak the symbol table.
 */
 
 */
 
-sendall(e, mode)
+char *
+hostsignature(m, host, e)
+       register MAILER *m;
+       char *host;
        ENVELOPE *e;
        ENVELOPE *e;
-       char mode;
 {
 {
-       register ADDRESS *q;
-       bool oldverbose;
-       int pid;
-       int nsent;
-       FILE *lockfp = NULL, *queueup();
-
-       /* determine actual delivery mode */
-       if (mode == SM_DEFAULT)
-       {
-               extern bool shouldqueue();
-
-               if (shouldqueue(e->e_msgpriority))
-                       mode = SM_QUEUE;
-               else
-                       mode = SendMode;
-       }
-
-       if (tTd(13, 1))
-       {
-               printf("\nSENDALL: mode %c, sendqueue:\n", mode);
-               printaddr(e->e_sendqueue, TRUE);
-       }
+       register char *p;
+       register STAB *s;
+       int i;
+       int len;
+#ifdef NAMED_BIND
+       int nmx;
+       auto int rcode;
+       char *hp;
+       char *endp;
+       int oldoptions;
+       char *mxhosts[MAXMXHOSTS + 1];
+#endif
 
        /*
 
        /*
-       **  Do any preprocessing necessary for the mode we are running.
-       **      Check to make sure the hop count is reasonable.
-       **      Delete sends to the sender in mailing lists.
+       **  Check to see if this uses IPC -- if not, it can't have MX records.
        */
 
        */
 
-       CurEnv = e;
-
-       if (e->e_hopcount > MAXHOP)
-       {
-               errno = 0;
-               syserr("sendall: too many hops %d (%d max): from %s, to %s",
-                       e->e_hopcount, MAXHOP, e->e_from, e->e_to);
-               return;
-       }
-
-       if (!MeToo)
+       p = m->m_mailer;
+       if (strcmp(p, "[IPC]") != 0 && strcmp(p, "[TCP]") != 0)
        {
        {
-               extern ADDRESS *recipient();
-
-               e->e_from.q_flags |= QDONTSEND;
-               (void) recipient(&e->e_from, &e->e_sendqueue);
+               /* just an ordinary mailer */
+               return host;
        }
 
        }
 
-# ifdef QUEUE
-       if ((mode == SM_QUEUE || mode == SM_FORK ||
-            (mode != SM_VERIFY && SuperSafe)) &&
-           !bitset(EF_INQUEUE, e->e_flags))
-               lockfp = queueup(e, TRUE, mode == SM_QUEUE);
-#endif QUEUE
-
-       oldverbose = Verbose;
-       switch (mode)
-       {
-         case SM_VERIFY:
-               Verbose = TRUE;
-               break;
-
-         case SM_QUEUE:
-               e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE;
-               return;
-
-         case SM_FORK:
-               if (e->e_xfp != NULL)
-                       (void) fflush(e->e_xfp);
-               pid = fork();
-               if (pid < 0)
-               {
-                       mode = SM_DELIVER;
-                       break;
-               }
-               else if (pid > 0)
-               {
-                       /* be sure we leave the temp files to our child */
-                       e->e_id = e->e_df = NULL;
-                       if (lockfp != NULL)
-                               (void) fclose(lockfp);
-                       return;
-               }
-
-               /* double fork to avoid zombies */
-               if (fork() > 0)
-                       exit(EX_OK);
-
-               /* be sure we are immune from the terminal */
-               disconnect(FALSE);
+       /*
+       **  If it is a numeric address, just return it.
+       */
 
 
-               break;
-       }
+       if (host[0] == '[')
+               return host;
 
        /*
 
        /*
-       **  Run through the list and send everything.
+       **  Look it up in the symbol table.
        */
 
        */
 
-       nsent = 0;
-       for (q = e->e_sendqueue; q != NULL; q = q->q_next)
-       {
-               if (mode == SM_VERIFY)
-               {
-                       e->e_to = q->q_paddr;
-                       if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
-                               message(Arpa_Info, "deliverable");
-               }
-               else if (!bitset(QDONTSEND, q->q_flags))
-               {
-                       /*
-                       **  Checkpoint the send list every few addresses
-                       */
-
-                       if (nsent >= CheckpointInterval)
-                       {
-                               queueup(e, TRUE, FALSE);
-                               nsent = 0;
-                       }
-                       if (deliver(e, q) == EX_OK)
-                               nsent++;
-               }
-       }
-       Verbose = oldverbose;
+       s = stab(host, ST_HOSTSIG, ST_ENTER);
+       if (s->s_hostsig != NULL)
+               return s->s_hostsig;
 
        /*
 
        /*
-       **  Now run through and check for errors.
+       **  Not already there -- create a signature.
        */
 
        */
 
-       if (mode == SM_VERIFY) {
-               if (lockfp != NULL)
-                       (void) fclose(lockfp);
-               return;
+#ifdef NAMED_BIND
+       if (ConfigLevel < 2)
+       {
+               oldoptions = _res.options;
+               _res.options &= ~(RES_DEFNAMES | RES_DNSRCH);   /* XXX */
        }
 
        }
 
-       for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+       for (hp = host; hp != NULL; hp = endp)
        {
        {
-               register ADDRESS *qq;
-
-               if (tTd(13, 3))
-               {
-                       printf("Checking ");
-                       printaddr(q, FALSE);
-               }
+               endp = strchr(hp, ':');
+               if (endp != NULL)
+                       *endp = '\0';
 
 
-               /* only send errors if the message failed */
-               if (!bitset(QBADADDR, q->q_flags))
-                       continue;
+               nmx = getmxrr(hp, mxhosts, TRUE, &rcode);
 
 
-               /* we have an address that failed -- find the parent */
-               for (qq = q; qq != NULL; qq = qq->q_alias)
+               if (nmx <= 0)
                {
                {
-                       char obuf[MAXNAME + 6];
-                       extern char *aliaslookup();
-
-                       /* we can only have owners for local addresses */
-                       if (!bitnset(M_LOCAL, qq->q_mailer->m_flags))
-                               continue;
+                       register MCI *mci;
+                       extern int errno;
 
 
-                       /* see if the owner list exists */
-                       (void) strcpy(obuf, "owner-");
-                       if (strncmp(qq->q_user, "owner-", 6) == 0)
-                               (void) strcat(obuf, "owner");
-                       else
-                               (void) strcat(obuf, qq->q_user);
-                       makelower(obuf);
-                       if (aliaslookup(obuf) == NULL)
-                               continue;
+                       /* update the connection info for this host */
+                       mci = mci_get(hp, m);
+                       mci->mci_exitstat = rcode;
+                       mci->mci_errno = errno;
 
 
-                       if (tTd(13, 4))
-                               printf("Errors to %s\n", obuf);
-
-                       /* owner list exists -- add it to the error queue */
-                       sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue);
-                       ErrorMode = EM_MAIL;
-                       break;
+                       /* and return the original host name as the signature */
+                       nmx = 1;
+                       mxhosts[0] = hp;
                }
 
                }
 
-               /* if we did not find an owner, send to the sender */
-               if (qq == NULL && bitset(QBADADDR, q->q_flags))
-                       sendtolist(e->e_from.q_paddr, qq, &e->e_errorqueue);
+               len = 0;
+               for (i = 0; i < nmx; i++)
+               {
+                       len += strlen(mxhosts[i]) + 1;
+               }
+               if (s->s_hostsig != NULL)
+                       len += strlen(s->s_hostsig) + 1;
+               p = xalloc(len);
+               if (s->s_hostsig != NULL)
+               {
+                       (void) strcpy(p, s->s_hostsig);
+                       free(s->s_hostsig);
+                       s->s_hostsig = p;
+                       p += strlen(p);
+                       *p++ = ':';
+               }
+               else
+                       s->s_hostsig = p;
+               for (i = 0; i < nmx; i++)
+               {
+                       if (i != 0)
+                               *p++ = ':';
+                       strcpy(p, mxhosts[i]);
+                       p += strlen(p);
+               }
+               if (endp != NULL)
+                       *endp++ = ':';
        }
        }
-
-       /* this removes the lock on the file */
-       if (lockfp != NULL)
-               (void) fclose(lockfp);
-
-       if (mode == SM_FORK)
-               finis();
+       makelower(s->s_hostsig);
+       if (ConfigLevel < 2)
+               _res.options = oldoptions;
+#else
+       /* not using BIND -- the signature is just the host name */
+       s->s_hostsig = host;
+#endif
+       if (tTd(17, 1))
+               printf("hostsignature(%s) = %s\n", host, s->s_hostsig);
+       return s->s_hostsig;
 }
 }
index 1bef478..fe977d2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1986 Eric P. Allman
 /*
  * Copyright (c) 1986 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #ifndef lint
 #ifdef NAMED_BIND
 
 #ifndef lint
 #ifdef NAMED_BIND
-static char sccsid[] = "@(#)domain.c   5.23 (Berkeley) 3/2/91 (with name server)";
+static char sccsid[] = "@(#)domain.c   8.1 (Berkeley) 6/7/93 (with name server)";
 #else
 #else
-static char sccsid[] = "@(#)domain.c   5.23 (Berkeley) 3/2/91 (without name server)";
+static char sccsid[] = "@(#)domain.c   8.1 (Berkeley) 6/7/93 (without name server)";
 #endif
 #endif /* not lint */
 
 #ifdef NAMED_BIND
 
 #endif
 #endif /* not lint */
 
 #ifdef NAMED_BIND
 
-#include <sys/param.h>
 #include <errno.h>
 #include <arpa/nameser.h>
 #include <resolv.h>
 #include <netdb.h>
 
 #include <errno.h>
 #include <arpa/nameser.h>
 #include <resolv.h>
 #include <netdb.h>
 
-typedef union {
-       HEADER qb1;
-       char qb2[PACKETSZ];
+typedef union
+{
+       HEADER  qb1;
+       char    qb2[PACKETSZ];
 } querybuf;
 
 } querybuf;
 
-static char hostbuf[MAXMXHOSTS*PACKETSZ];
+static char    MXHostBuf[MAXMXHOSTS*PACKETSZ];
+
+#ifndef MAXDNSRCH
+#define MAXDNSRCH      6       /* number of possible domains to search */
+#endif
+
+#ifndef MAX
+#define MAX(a, b)      ((a) > (b) ? (a) : (b))
+#endif
+
+/* don't use sizeof because sizeof(long) is different on 64-bit machines */
+#define SHORTSIZE      2       /* size of a short (really, must be 2) */
+#define LONGSIZE       4       /* size of a long (really, must be 4) */
+
+#define MAXCNAMEDEPTH  10      /* maximum depth of CNAME recursion */
+\f/*
+**  GETMXRR -- get MX resource records for a domain
+**
+**     Parameters:
+**             host -- the name of the host to MX.
+**             mxhosts -- a pointer to a return buffer of MX records.
+**             droplocalhost -- If TRUE, all MX records less preferred
+**                     than the local host (as determined by $=w) will
+**                     be discarded.
+**             rcode -- a pointer to an EX_ status code.
+**
+**     Returns:
+**             The number of MX records found.
+**             -1 if there is an internal failure.
+**             If no MX records are found, mxhosts[0] is set to host
+**                     and 1 is returned.
+*/
 
 
-getmxrr(host, mxhosts, localhost, rcode)
-       char *host, **mxhosts, *localhost;
+getmxrr(host, mxhosts, droplocalhost, rcode)
+       char *host;
+       char **mxhosts;
+       bool droplocalhost;
        int *rcode;
 {
        extern int h_errno;
        int *rcode;
 {
        extern int h_errno;
@@ -67,16 +100,40 @@ getmxrr(host, mxhosts, localhost, rcode)
        register char *bp;
        HEADER *hp;
        querybuf answer;
        register char *bp;
        HEADER *hp;
        querybuf answer;
-       int ancount, qdcount, buflen, seenlocal;
-       u_short pref, localpref, type, prefer[MAXMXHOSTS];
+       int ancount, qdcount, buflen;
+       bool seenlocal;
+       u_short pref, localpref, type;
+       char *fallbackMX = FallBackMX;
+       static bool firsttime = TRUE;
+       STAB *st;
+       u_short prefer[MAXMXHOSTS];
+       int weight[MAXMXHOSTS];
+
+       if (fallbackMX != NULL)
+       {
+               if (firsttime && res_query(FallBackMX, C_IN, T_A,
+                                          (char *) &answer, sizeof answer) < 0)
+               {
+                       /* this entry is bogus */
+                       fallbackMX = FallBackMX = NULL;
+               }
+               else if (droplocalhost &&
+                        (st = stab(fallbackMX, ST_CLASS, ST_FIND)) != NULL &&
+                        bitnset('w', st->s_class))
+               {
+                       /* don't use fallback for this pass */
+                       fallbackMX = NULL;
+               }
+               firsttime = FALSE;
+       }
 
        errno = 0;
        n = res_search(host, C_IN, T_MX, (char *)&answer, sizeof(answer));
        if (n < 0)
        {
                if (tTd(8, 1))
 
        errno = 0;
        n = res_search(host, C_IN, T_MX, (char *)&answer, sizeof(answer));
        if (n < 0)
        {
                if (tTd(8, 1))
-                       printf("getmxrr: res_search failed (errno=%d, h_errno=%d)\n",
-                           errno, h_errno);
+                       printf("getmxrr: res_search(%s) failed (errno=%d, h_errno=%d)\n",
+                           (host == NULL) ? "<NULL>" : host, errno, h_errno);
                switch (h_errno)
                {
                  case NO_DATA:
                switch (h_errno)
                {
                  case NO_DATA:
@@ -108,174 +165,439 @@ getmxrr(host, mxhosts, localhost, rcode)
        cp = (u_char *)&answer + sizeof(HEADER);
        eom = (u_char *)&answer + n;
        for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
        cp = (u_char *)&answer + sizeof(HEADER);
        eom = (u_char *)&answer + n;
        for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
-               if ((n = __dn_skipname(cp, eom)) < 0)
+               if ((n = dn_skipname(cp, eom)) < 0)
                        goto punt;
        nmx = 0;
                        goto punt;
        nmx = 0;
-       seenlocal = 0;
-       buflen = sizeof(hostbuf);
-       bp = hostbuf;
+       seenlocal = FALSE;
+       buflen = sizeof(MXHostBuf) - 1;
+       bp = MXHostBuf;
        ancount = ntohs(hp->ancount);
        ancount = ntohs(hp->ancount);
-       while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS) {
+       while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS - 1)
+       {
                if ((n = dn_expand((u_char *)&answer,
                    eom, cp, (u_char *)bp, buflen)) < 0)
                        break;
                cp += n;
                GETSHORT(type, cp);
                if ((n = dn_expand((u_char *)&answer,
                    eom, cp, (u_char *)bp, buflen)) < 0)
                        break;
                cp += n;
                GETSHORT(type, cp);
-               cp += sizeof(u_short) + sizeof(u_long);
+               cp += SHORTSIZE + LONGSIZE;
                GETSHORT(n, cp);
                GETSHORT(n, cp);
-               if (type != T_MX)  {
-                       if (tTd(8, 1) || _res.options & RES_DEBUG)
+               if (type != T_MX)
+               {
+                       if (tTd(8, 8) || _res.options & RES_DEBUG)
                                printf("unexpected answer type %d, size %d\n",
                                    type, n);
                        cp += n;
                        continue;
                }
                GETSHORT(pref, cp);
                                printf("unexpected answer type %d, size %d\n",
                                    type, n);
                        cp += n;
                        continue;
                }
                GETSHORT(pref, cp);
-               if ((n = dn_expand((u_char *)&answer,
-                   eom, cp, (u_char *)bp, buflen)) < 0)
+               if ((n = dn_expand((u_char *)&answer, eom, cp,
+                                  (u_char *)bp, buflen)) < 0)
                        break;
                cp += n;
                        break;
                cp += n;
-               if (!strcasecmp(bp, localhost)) {
-                       if (seenlocal == 0 || pref < localpref)
+               if (droplocalhost &&
+                   (st = stab(bp, ST_CLASS, ST_FIND)) != NULL &&
+                   bitnset('w', st->s_class))
+               {
+                       if (!seenlocal || pref < localpref)
                                localpref = pref;
                                localpref = pref;
-                       seenlocal = 1;
+                       seenlocal = TRUE;
                        continue;
                }
                        continue;
                }
+               weight[nmx] = mxrand(bp);
                prefer[nmx] = pref;
                mxhosts[nmx++] = bp;
                prefer[nmx] = pref;
                mxhosts[nmx++] = bp;
-               n = strlen(bp) + 1;
+               n = strlen(bp);
                bp += n;
                bp += n;
-               buflen -= n;
+               if (bp[-1] != '.')
+               {
+                       *bp++ = '.';
+                       n++;
+               }
+               *bp++ = '\0';
+               buflen -= n + 1;
        }
        }
-       if (nmx == 0) {
-punt:          mxhosts[0] = strcpy(hostbuf, host);
-               return(1);
+       if (nmx == 0)
+       {
+punt:
+               mxhosts[0] = strcpy(MXHostBuf, host);
+               bp = &MXHostBuf[strlen(MXHostBuf)];
+               if (bp[-1] != '.')
+               {
+                       *bp++ = '.';
+                       *bp = '\0';
+               }
+               nmx = 1;
        }
        }
+       else
+       {
+               /* sort the records */
+               for (i = 0; i < nmx; i++)
+               {
+                       for (j = i + 1; j < nmx; j++)
+                       {
+                               if (prefer[i] > prefer[j] ||
+                                   (prefer[i] == prefer[j] && weight[i] > weight[j]))
+                               {
+                                       register int temp;
+                                       register char *temp1;
 
 
-       /* sort the records */
-       for (i = 0; i < nmx; i++) {
-               for (j = i + 1; j < nmx; j++) {
-                       if (prefer[i] > prefer[j] ||
-                           (prefer[i] == prefer[j] && rand() % 1 == 0)) {
-                               register int temp;
-                               register char *temp1;
-
-                               temp = prefer[i];
-                               prefer[i] = prefer[j];
-                               prefer[j] = temp;
-                               temp1 = mxhosts[i];
-                               mxhosts[i] = mxhosts[j];
-                               mxhosts[j] = temp1;
+                                       temp = prefer[i];
+                                       prefer[i] = prefer[j];
+                                       prefer[j] = temp;
+                                       temp1 = mxhosts[i];
+                                       mxhosts[i] = mxhosts[j];
+                                       mxhosts[j] = temp1;
+                                       temp = weight[i];
+                                       weight[i] = weight[j];
+                                       weight[j] = temp;
+                               }
                        }
                        }
-               }
-               if (seenlocal && prefer[i] >= localpref) {
-                       /*
-                        * truncate higher pref part of list; if we're
-                        * the best choice left, we should have realized
-                        * awhile ago that this was a local delivery.
-                        */
-                       if (i == 0) {
-                               *rcode = EX_CONFIG;
-                               return(-1);
+                       if (seenlocal && prefer[i] >= localpref)
+                       {
+                               /*
+                                * truncate higher pref part of list; if we're
+                                * the best choice left, we should have realized
+                                * awhile ago that this was a local delivery.
+                                */
+                               if (i == 0)
+                               {
+                                       *rcode = EX_CONFIG;
+                                       return (-1);
+                               }
+                               nmx = i;
+                               break;
                        }
                        }
-                       nmx = i;
-                       break;
                }
        }
                }
        }
-       return(nmx);
+
+       /* if we have a default lowest preference, include that */
+       if (FallBackMX != NULL && !seenlocal)
+               mxhosts[nmx++] = FallBackMX;
+
+       return (nmx);
 }
 }
+\f/*
+**  MXRAND -- create a randomizer for equal MX preferences
+**
+**     If two MX hosts have equal preferences we want to randomize
+**     the selection.  But in order for signatures to be the same,
+**     we need to randomize the same way each time.  This function
+**     computes a pseudo-random hash function from the host name.
+**
+**     Parameters:
+**             host -- the name of the host.
+**
+**     Returns:
+**             A random but repeatable value based on the host name.
+**
+**     Side Effects:
+**             none.
+*/
+
+mxrand(host)
+       register char *host;
+{
+       int hfunc;
+       static unsigned int seed;
 
 
+       if (seed == 0)
+       {
+               seed = (int) curtime() & 0xffff;
+               if (seed == 0)
+                       seed++;
+       }
+
+       if (tTd(17, 9))
+               printf("mxrand(%s)", host);
+
+       hfunc = seed;
+       while (*host != '\0')
+       {
+               int c = *host++;
+
+               if (isascii(c) && isupper(c))
+                       c = tolower(c);
+               hfunc = ((hfunc << 1) + c) % 2003;
+       }
+
+       hfunc &= 0xff;
+
+       if (tTd(17, 9))
+               printf(" = %d\n", hfunc);
+       return hfunc;
+}
+\f/*
+**  GETCANONNAME -- get the canonical name for named host
+**
+**     This algorithm tries to be smart about wildcard MX records.
+**     This is hard to do because DNS doesn't tell is if we matched
+**     against a wildcard or a specific MX.
+**     
+**     We always prefer A & CNAME records, since these are presumed
+**     to be specific.
+**
+**     If we match an MX in one pass and lose it in the next, we use
+**     the old one.  For example, consider an MX matching *.FOO.BAR.COM.
+**     A hostname bletch.foo.bar.com will match against this MX, but
+**     will stop matching when we try bletch.bar.com -- so we know
+**     that bletch.foo.bar.com must have been right.  This fails if
+**     there was also an MX record matching *.BAR.COM, but there are
+**     some things that just can't be fixed.
+**
+**     Parameters:
+**             host -- a buffer containing the name of the host.
+**                     This is a value-result parameter.
+**             hbsize -- the size of the host buffer.
+**
+**     Returns:
+**             TRUE -- if the host matched.
+**             FALSE -- otherwise.
+*/
+
+bool
 getcanonname(host, hbsize)
        char *host;
        int hbsize;
 {
        extern int h_errno;
 getcanonname(host, hbsize)
        char *host;
        int hbsize;
 {
        extern int h_errno;
-       register u_char *eom, *cp;
+       register u_char *eom, *ap;
+       register char *cp;
        register int n; 
        HEADER *hp;
        querybuf answer;
        register int n; 
        HEADER *hp;
        querybuf answer;
-       u_short type;
-       int first, ancount, qdcount, loopcnt;
-       char nbuf[PACKETSZ];
+       int ancount, qdcount;
+       int ret;
+       char **domain;
+       int type;
+       char **dp;
+       char *mxmatch;
+       bool amatch;
+       bool gotmx;
+       int qtype;
+       int loopcnt;
+       char nbuf[MAX(PACKETSZ, MAXDNAME*2+2)];
+       char *searchlist[MAXDNSRCH+2];
+
+       if (tTd(8, 2))
+               printf("getcanonname(%s)\n", host);
+
+       if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+               return (FALSE);
 
 
-       loopcnt = 0;
-loop:
        /*
        /*
-        * Use query type of ANY if possible (NO_WILDCARD_MX), which will
-        * find types CNAME, A, and MX, and will cause all existing records
-        * to be cached by our local server.  If there is (might be) a
-        * wildcard MX record in the local domain or its parents that are
-        * searched, we can't use ANY; it would cause fully-qualified names
-        * to match as names in a local domain.
-        */
-# ifdef NO_WILDCARD_MX
-       n = res_search(host, C_IN, T_ANY, (char *)&answer, sizeof(answer));
-# else
-       n = res_search(host, C_IN, T_CNAME, (char *)&answer, sizeof(answer));
-# endif
-       if (n < 0) {
-               if (tTd(8, 1))
-                       printf("getcanonname:  res_search failed (errno=%d, h_errno=%d)\n",
-                           errno, h_errno);
-               return;
-       }
+       **  Initialize domain search list.  If there is at least one
+       **  dot in the name, search the unmodified name first so we
+       **  find "vse.CS" in Czechoslovakia instead of in the local
+       **  domain (e.g., vse.CS.Berkeley.EDU).
+       **
+       **  Older versions of the resolver could create this
+       **  list by tearing apart the host name.
+       */
 
 
-       /* find first satisfactory answer */
-       hp = (HEADER *)&answer;
-       ancount = ntohs(hp->ancount);
+       loopcnt = 0;
+cnameloop:
+       for (cp = host, n = 0; *cp; cp++)
+               if (*cp == '.')
+                       n++;
 
 
-       /* we don't care about errors here, only if we got an answer */
-       if (ancount == 0) {
-               if (tTd(8, 1))
-                       printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
-               return;
+       dp = searchlist;
+       if (n > 0)
+               *dp++ = "";
+       if (n >= 0 && *--cp != '.' && bitset(RES_DNSRCH, _res.options))
+       {
+               for (domain = _res.dnsrch; *domain != NULL; )
+                       *dp++ = *domain++;
        }
        }
-       cp = (u_char *)&answer + sizeof(HEADER);
-       eom = (u_char *)&answer + n;
-       for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
-               if ((n = __dn_skipname(cp, eom)) < 0)
-                       return;
+       else if (n == 0 && bitset(RES_DEFNAMES, _res.options))
+       {
+               *dp++ = _res.defdname;
+       }
+       *dp = NULL;
 
        /*
 
        /*
-        * just in case someone puts a CNAME record after another record,
-        * check all records for CNAME; otherwise, just take the first
-        * name found.
-        */
-       for (first = 1; --ancount >= 0 && cp < eom; cp += n) {
-               if ((n = dn_expand((u_char *)&answer,
-                   eom, cp, (u_char *)nbuf, sizeof(nbuf))) < 0)
-                       break;
-               if (first) {                    /* XXX */
-                       (void)strncpy(host, nbuf, hbsize);
-                       host[hbsize - 1] = '\0';
-                       first = 0;
+       **  Now run through the search list for the name in question.
+       */
+
+       mxmatch = NULL;
+       qtype = T_ANY;
+
+       for (dp = searchlist; *dp != NULL; )
+       {
+               if (qtype == T_ANY)
+                       gotmx = FALSE;
+               if (tTd(8, 5))
+                       printf("getcanonname: trying %s.%s (%s)\n", host, *dp,
+                               qtype == T_ANY ? "ANY" : qtype == T_A ? "A" :
+                               qtype == T_MX ? "MX" : "???");
+               ret = res_querydomain(host, *dp, C_IN, qtype,
+                                     &answer, sizeof(answer));
+               if (ret <= 0)
+               {
+                       if (tTd(8, 7))
+                               printf("\tNO: errno=%d, h_errno=%d\n",
+                                       errno, h_errno);
+
+                       if (errno == ECONNREFUSED || h_errno == TRY_AGAIN)
+                       {
+                               /* the name server seems to be down */
+                               h_errno = TRY_AGAIN;
+                               return FALSE;
+                       }
+
+                       if (h_errno != HOST_NOT_FOUND)
+                       {
+                               /* might have another type of interest */
+                               if (qtype == T_ANY)
+                               {
+                                       qtype = T_A;
+                                       continue;
+                               }
+                               else if (qtype == T_A && !gotmx)
+                               {
+                                       qtype = T_MX;
+                                       continue;
+                               }
+                       }
+
+                       if (mxmatch != NULL)
+                       {
+                               /* we matched before -- use that one */
+                               break;
+                       }
+
+                       /* otherwise, try the next name */
+                       dp++;
+                       qtype = T_ANY;
+                       continue;
                }
                }
-               cp += n;
-               GETSHORT(type, cp);
-               cp += sizeof(u_short) + sizeof(u_long);
-               GETSHORT(n, cp);
-               if (type == T_CNAME)  {
-                       /*
-                        * assume that only one cname will be found.  More
-                        * than one is undefined.  Copy so that if dn_expand
-                        * fails, `host' is still okay.
-                        */
-                       if ((n = dn_expand((u_char *)&answer,
-                           eom, cp, (u_char *)nbuf, sizeof(nbuf))) < 0)
+               else if (tTd(8, 7))
+                       printf("\tYES\n");
+
+               /*
+               **  This might be a bogus match.  Search for A or
+               **  CNAME records.  If we don't have a matching
+               **  wild card MX record, we will accept MX as well.
+               */
+
+               hp = (HEADER *) &answer;
+               ap = (u_char *) &answer + sizeof(HEADER);
+               eom = (u_char *) &answer + ret;
+
+               /* skip question part of response -- we know what we asked */
+               for (qdcount = ntohs(hp->qdcount); qdcount--; ap += ret + QFIXEDSZ)
+               {
+                       if ((ret = dn_skipname(ap, eom)) < 0)
+                       {
+                               if (tTd(8, 20))
+                                       printf("qdcount failure (%d)\n",
+                                               ntohs(hp->qdcount));
+                               return FALSE;           /* ???XXX??? */
+                       }
+               }
+
+               amatch = FALSE;
+               for (ancount = ntohs(hp->ancount); --ancount >= 0 && ap < eom; ap += n)
+               {
+                       n = dn_expand((u_char *) &answer, eom, ap,
+                                     (u_char *) nbuf, sizeof nbuf);
+                       if (n < 0)
                                break;
                                break;
-                       (void)strncpy(host, nbuf, hbsize); /* XXX */
-                       host[hbsize - 1] = '\0';
-                       if (++loopcnt > 8)      /* never be more than 1 */
-                               return;
-                       goto loop;
+                       ap += n;
+                       GETSHORT(type, ap);
+                       ap += SHORTSIZE + LONGSIZE;
+                       GETSHORT(n, ap);
+                       switch (type)
+                       {
+                         case T_MX:
+                               gotmx = TRUE;
+                               if (**dp != '\0')
+                               {
+                                       /* got a match -- save that info */
+                                       if (mxmatch == NULL)
+                                               mxmatch = *dp;
+                                       continue;
+                               }
+
+                               /* exact MX matches are as good as an A match */
+                               /* fall through */
+
+                         case T_A:
+                               /* good show */
+                               amatch = TRUE;
+
+                               /* continue in case a CNAME also exists */
+                               continue;
+
+                         case T_CNAME:
+                               if (loopcnt++ > MAXCNAMEDEPTH)
+                               {
+                                       syserr("DNS failure: CNAME loop for %s",
+                                               host);
+                                       continue;
+                               }
+
+                               /* value points at name */
+                               if ((ret = dn_expand((u_char *)&answer,
+                                   eom, ap, (u_char *)nbuf, sizeof(nbuf))) < 0)
+                                       break;
+                               (void)strncpy(host, nbuf, hbsize); /* XXX */
+                               host[hbsize - 1] = '\0';
+
+                               /*
+                               **  RFC 1034 section 3.6 specifies that CNAME
+                               **  should point at the canonical name -- but
+                               **  urges software to try again anyway.
+                               */
+
+                               goto cnameloop;
+
+                         default:
+                               /* not a record of interest */
+                               continue;
+                       }
+               }
+
+               if (amatch)
+               {
+                       /* got an A record and no CNAME */
+                       mxmatch = *dp;
+                       break;
+               }
+
+               /*
+               **  If this was a T_ANY query, we may have the info but
+               **  need an explicit query.  Try T_A, then T_MX.
+               */
+
+               if (qtype == T_ANY)
+                       qtype = T_A;
+               else if (qtype == T_A && !gotmx)
+                       qtype = T_MX;
+               else
+               {
+                       /* really nothing in this domain; try the next */
+                       qtype = T_ANY;
+                       dp++;
                }
        }
                }
        }
+
+       if (mxmatch == NULL)
+               return FALSE;
+
+       /* create matching name and return */
+       (void) sprintf(nbuf, "%.*s%s%.*s", MAXDNAME, host,
+                       *mxmatch == '\0' ? "" : ".",
+                       MAXDNAME, mxmatch);
+       strncpy(host, nbuf, hbsize);
+       host[hbsize - 1] = '\0';
+       return TRUE;
 }
 
 #else /* not NAMED_BIND */
 
 #include <netdb.h>
 
 }
 
 #else /* not NAMED_BIND */
 
 #include <netdb.h>
 
+bool
 getcanonname(host, hbsize)
        char *host;
        int hbsize;
 getcanonname(host, hbsize)
        char *host;
        int hbsize;
@@ -284,12 +606,13 @@ getcanonname(host, hbsize)
 
        hp = gethostbyname(host);
        if (hp == NULL)
 
        hp = gethostbyname(host);
        if (hp == NULL)
-               return;
+               return (FALSE);
 
        if (strlen(hp->h_name) >= hbsize)
 
        if (strlen(hp->h_name) >= hbsize)
-               return;
+               return (FALSE);
 
        (void) strcpy(host, hp->h_name);
 
        (void) strcpy(host, hp->h_name);
+       return (TRUE);
 }
 
 #endif /* not NAMED_BIND */
 }
 
 #endif /* not NAMED_BIND */
index 24b914a..3b6d2c1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)envelope.c 5.22 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)envelope.c 8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #endif /* not lint */
 
-#include <sys/types.h>
+#include "sendmail.h"
 #include <sys/time.h>
 #include <sys/time.h>
-#include <sys/stat.h>
 #include <pwd.h>
 #include <pwd.h>
-#include <sys/file.h>
-#include "sendmail.h"
 
 /*
 **  NEWENVELOPE -- allocate a new envelope
 
 /*
 **  NEWENVELOPE -- allocate a new envelope
@@ -50,6 +47,7 @@ static char sccsid[] = "@(#)envelope.c        5.22 (Berkeley) 6/1/90";
 **
 **     Parameters:
 **             e -- the new envelope to fill in.
 **
 **     Parameters:
 **             e -- the new envelope to fill in.
+**             parent -- the envelope to be the parent of e.
 **
 **     Returns:
 **             e.
 **
 **     Returns:
 **             e.
@@ -59,15 +57,14 @@ static char sccsid[] = "@(#)envelope.c      5.22 (Berkeley) 6/1/90";
 */
 
 ENVELOPE *
 */
 
 ENVELOPE *
-newenvelope(e)
+newenvelope(e, parent)
        register ENVELOPE *e;
        register ENVELOPE *e;
-{
        register ENVELOPE *parent;
        register ENVELOPE *parent;
+{
        extern putheader(), putbody();
        extern ENVELOPE BlankEnvelope;
 
        extern putheader(), putbody();
        extern ENVELOPE BlankEnvelope;
 
-       parent = CurEnv;
-       if (e == CurEnv)
+       if (e == parent && e->e_parent != NULL)
                parent = e->e_parent;
        clearenvelope(e, TRUE);
        if (e == CurEnv)
                parent = e->e_parent;
        clearenvelope(e, TRUE);
        if (e == CurEnv)
@@ -76,7 +73,8 @@ newenvelope(e)
                bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
        e->e_parent = parent;
        e->e_ctime = curtime();
                bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
        e->e_parent = parent;
        e->e_ctime = curtime();
-       e->e_msgpriority = parent->e_msgsize;
+       if (parent != NULL)
+               e->e_msgpriority = parent->e_msgsize;
        e->e_puthdr = putheader;
        e->e_putbody = putbody;
        if (CurEnv->e_xfp != NULL)
        e->e_puthdr = putheader;
        e->e_putbody = putbody;
        if (CurEnv->e_xfp != NULL)
@@ -98,29 +96,31 @@ newenvelope(e)
 **             Unlocks this queue file.
 */
 
 **             Unlocks this queue file.
 */
 
+void
 dropenvelope(e)
        register ENVELOPE *e;
 {
        bool queueit = FALSE;
        register ADDRESS *q;
 dropenvelope(e)
        register ENVELOPE *e;
 {
        bool queueit = FALSE;
        register ADDRESS *q;
+       char *id = e->e_id;
 
        if (tTd(50, 1))
        {
 
        if (tTd(50, 1))
        {
-               printf("dropenvelope %x id=", e);
+               printf("dropenvelope %x: id=", e);
                xputs(e->e_id);
                xputs(e->e_id);
-               printf(" flags=%o\n", e->e_flags);
+               printf(", flags=%o\n", e->e_flags);
        }
        }
-#ifdef LOG
-       if (LogLevel > 10)
-               syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d",
-                                 e->e_id == NULL ? "(none)" : e->e_id,
-                                 e->e_flags, getpid());
-#endif LOG
 
        /* we must have an id to remove disk files */
 
        /* we must have an id to remove disk files */
-       if (e->e_id == NULL)
+       if (id == NULL)
                return;
 
                return;
 
+#ifdef LOG
+       if (LogLevel > 84)
+               syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d",
+                                 id, e->e_flags, getpid());
+#endif /* LOG */
+
        /*
        **  Extract state information from dregs of send list.
        */
        /*
        **  Extract state information from dregs of send list.
        */
@@ -139,15 +139,16 @@ dropenvelope(e)
        {
                auto ADDRESS *rlist = NULL;
 
        {
                auto ADDRESS *rlist = NULL;
 
-               sendtolist(CurEnv->e_receiptto, (ADDRESS *) NULL, &rlist);
-               (void) returntosender("Return receipt", rlist, FALSE);
+               (void) sendtolist(e->e_receiptto, (ADDRESS *) NULL, &rlist, e);
+               (void) returntosender("Return receipt", rlist, FALSE, e);
        }
 
        /*
        **  Arrange to send error messages if there are fatal errors.
        */
 
        }
 
        /*
        **  Arrange to send error messages if there are fatal errors.
        */
 
-       if (bitset(EF_FATALERRS|EF_TIMEOUT, e->e_flags) && ErrorMode != EM_QUIET)
+       if (bitset(EF_FATALERRS|EF_TIMEOUT, e->e_flags) &&
+           e->e_errormode != EM_QUIET)
                savemail(e);
 
        /*
                savemail(e);
 
        /*
@@ -164,13 +165,10 @@ dropenvelope(e)
        else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
        {
 #ifdef QUEUE
        else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
        {
 #ifdef QUEUE
-               FILE *lockfp, *queueup();
-               lockfp = queueup(e, FALSE, FALSE);
-               if (lockfp != NULL)
-                       (void) fclose(lockfp);
-#else QUEUE
-               syserr("dropenvelope: queueup");
-#endif QUEUE
+               queueup(e, FALSE, FALSE);
+#else /* QUEUE */
+               syserr("554 dropenvelope: queueup");
+#endif /* QUEUE */
        }
 
        /* now unlock the job */
        }
 
        /* now unlock the job */
@@ -178,10 +176,15 @@ dropenvelope(e)
        unlockqueue(e);
 
        /* make sure that this envelope is marked unused */
        unlockqueue(e);
 
        /* make sure that this envelope is marked unused */
-       e->e_id = e->e_df = NULL;
        if (e->e_dfp != NULL)
        if (e->e_dfp != NULL)
-               (void) fclose(e->e_dfp);
+               (void) xfclose(e->e_dfp, "dropenvelope", e->e_df);
        e->e_dfp = NULL;
        e->e_dfp = NULL;
+       e->e_id = e->e_df = NULL;
+
+#ifdef LOG
+       if (LogLevel > 74)
+               syslog(LOG_INFO, "%s: done", id);
+#endif /* LOG */
 }
 \f/*
 **  CLEARENVELOPE -- clear an envelope without unlocking
 }
 \f/*
 **  CLEARENVELOPE -- clear an envelope without unlocking
@@ -203,6 +206,7 @@ dropenvelope(e)
 **             Marks the envelope as unallocated.
 */
 
 **             Marks the envelope as unallocated.
 */
 
+void
 clearenvelope(e, fullclear)
        register ENVELOPE *e;
        bool fullclear;
 clearenvelope(e, fullclear)
        register ENVELOPE *e;
        bool fullclear;
@@ -215,13 +219,16 @@ clearenvelope(e, fullclear)
        {
                /* clear out any file information */
                if (e->e_xfp != NULL)
        {
                /* clear out any file information */
                if (e->e_xfp != NULL)
-                       (void) fclose(e->e_xfp);
+                       (void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id);
                if (e->e_dfp != NULL)
                if (e->e_dfp != NULL)
-                       (void) fclose(e->e_dfp);
+                       (void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_df);
+               e->e_xfp = e->e_dfp = NULL;
        }
 
        /* now clear out the data */
        STRUCTCOPY(BlankEnvelope, *e);
        }
 
        /* now clear out the data */
        STRUCTCOPY(BlankEnvelope, *e);
+       if (Verbose)
+               e->e_sendmode = SM_DELIVER;
        bh = BlankEnvelope.e_header;
        nhp = &e->e_header;
        while (bh != NULL)
        bh = BlankEnvelope.e_header;
        nhp = &e->e_header;
        while (bh != NULL)
@@ -249,16 +256,18 @@ clearenvelope(e, fullclear)
 **             forms is set.
 */
 
 **             forms is set.
 */
 
-initsys()
+void
+initsys(e)
+       register ENVELOPE *e;
 {
        static char cbuf[5];                    /* holds hop count */
        static char pbuf[10];                   /* holds pid */
 #ifdef TTYNAME
 {
        static char cbuf[5];                    /* holds hop count */
        static char pbuf[10];                   /* holds pid */
 #ifdef TTYNAME
-       static char ybuf[10];                   /* holds tty id */
+       static char ybuf[60];                   /* holds tty id */
        register char *p;
        register char *p;
-#endif TTYNAME
+#endif /* TTYNAME */
        extern char *ttyname();
        extern char *ttyname();
-       extern char *macvalue();
+       extern void settime();
        extern char Version[];
 
        /*
        extern char Version[];
 
        /*
@@ -266,8 +275,8 @@ initsys()
        **      I.e., an id, a transcript, and a creation time.
        */
 
        **      I.e., an id, a transcript, and a creation time.
        */
 
-       openxscript(CurEnv);
-       CurEnv->e_ctime = curtime();
+       openxscript(e);
+       e->e_ctime = curtime();
 
        /*
        **  Set OutChannel to something useful if stdout isn't it.
 
        /*
        **  Set OutChannel to something useful if stdout isn't it.
@@ -276,8 +285,9 @@ initsys()
        **      tucked away in the transcript).
        */
 
        **      tucked away in the transcript).
        */
 
-       if (OpMode == MD_DAEMON && QueueRun)
-               OutChannel = CurEnv->e_xfp;
+       if (OpMode == MD_DAEMON && !bitset(EF_QUEUERUN, e->e_flags) &&
+           e->e_xfp != NULL)
+               OutChannel = e->e_xfp;
 
        /*
        **  Set up some basic system macros.
 
        /*
        **  Set up some basic system macros.
@@ -285,29 +295,29 @@ initsys()
 
        /* process id */
        (void) sprintf(pbuf, "%d", getpid());
 
        /* process id */
        (void) sprintf(pbuf, "%d", getpid());
-       define('p', pbuf, CurEnv);
+       define('p', pbuf, e);
 
        /* hop count */
 
        /* hop count */
-       (void) sprintf(cbuf, "%d", CurEnv->e_hopcount);
-       define('c', cbuf, CurEnv);
+       (void) sprintf(cbuf, "%d", e->e_hopcount);
+       define('c', cbuf, e);
 
        /* time as integer, unix time, arpa time */
 
        /* time as integer, unix time, arpa time */
-       settime();
+       settime(e);
 
 #ifdef TTYNAME
        /* tty name */
 
 #ifdef TTYNAME
        /* tty name */
-       if (macvalue('y', CurEnv) == NULL)
+       if (macvalue('y', e) == NULL)
        {
                p = ttyname(2);
                if (p != NULL)
                {
        {
                p = ttyname(2);
                if (p != NULL)
                {
-                       if (rindex(p, '/') != NULL)
-                               p = rindex(p, '/') + 1;
+                       if (strrchr(p, '/') != NULL)
+                               p = strrchr(p, '/') + 1;
                        (void) strcpy(ybuf, p);
                        (void) strcpy(ybuf, p);
-                       define('y', ybuf, CurEnv);
+                       define('y', ybuf, e);
                }
        }
                }
        }
-#endif TTYNAME
+#endif /* TTYNAME */
 }
 \f/*
 **  SETTIME -- set the current time.
 }
 \f/*
 **  SETTIME -- set the current time.
@@ -322,7 +332,9 @@ initsys()
 **             Sets the various time macros -- $a, $b, $d, $t.
 */
 
 **             Sets the various time macros -- $a, $b, $d, $t.
 */
 
-settime()
+void
+settime(e)
+       register ENVELOPE *e;
 {
        register char *p;
        auto time_t now;
 {
        register char *p;
        auto time_t now;
@@ -331,21 +343,21 @@ settime()
        register struct tm *tm;
        extern char *arpadate();
        extern struct tm *gmtime();
        register struct tm *tm;
        extern char *arpadate();
        extern struct tm *gmtime();
-       extern char *macvalue();
 
        now = curtime();
        tm = gmtime(&now);
 
        now = curtime();
        tm = gmtime(&now);
-       (void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon+1,
-                       tm->tm_mday, tm->tm_hour, tm->tm_min);
-       define('t', tbuf, CurEnv);
+       (void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
+                       tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
+       define('t', tbuf, e);
        (void) strcpy(dbuf, ctime(&now));
        (void) strcpy(dbuf, ctime(&now));
-       *index(dbuf, '\n') = '\0';
-       if (macvalue('d', CurEnv) == NULL)
-               define('d', dbuf, CurEnv);
+       p = strchr(dbuf, '\n');
+       if (p != NULL)
+               *p = '\0';
+       define('d', dbuf, e);
        p = newstr(arpadate(dbuf));
        p = newstr(arpadate(dbuf));
-       if (macvalue('a', CurEnv) == NULL)
-               define('a', p, CurEnv);
-       define('b', p, CurEnv);
+       if (macvalue('a', e) == NULL)
+               define('a', p, e);
+       define('b', p, e);
 }
 \f/*
 **  OPENXSCRIPT -- Open transcript file
 }
 \f/*
 **  OPENXSCRIPT -- Open transcript file
@@ -363,20 +375,21 @@ settime()
 **             Creates the transcript file.
 */
 
 **             Creates the transcript file.
 */
 
+#ifndef O_APPEND
+#define O_APPEND       0
+#endif
+
+void
 openxscript(e)
        register ENVELOPE *e;
 {
        register char *p;
        int fd;
 
 openxscript(e)
        register ENVELOPE *e;
 {
        register char *p;
        int fd;
 
-# ifdef LOG
-       if (LogLevel > 19)
-               syslog(LOG_DEBUG, "%s: openx%s", e->e_id, e->e_xfp == NULL ? "" : " (no)");
-# endif LOG
        if (e->e_xfp != NULL)
                return;
        p = queuename(e, 'x');
        if (e->e_xfp != NULL)
                return;
        p = queuename(e, 'x');
-       fd = open(p, O_WRONLY|O_CREAT, 0644);
+       fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644);
        if (fd < 0)
                syserr("Can't create %s", p);
        else
        if (fd < 0)
                syserr("Can't create %s", p);
        else
@@ -395,12 +408,13 @@ openxscript(e)
 **             none.
 */
 
 **             none.
 */
 
+void
 closexscript(e)
        register ENVELOPE *e;
 {
        if (e->e_xfp == NULL)
                return;
 closexscript(e)
        register ENVELOPE *e;
 {
        if (e->e_xfp == NULL)
                return;
-       (void) fclose(e->e_xfp);
+       (void) xfclose(e->e_xfp, "closexscript", e->e_id);
        e->e_xfp = NULL;
 }
 \f/*
        e->e_xfp = NULL;
 }
 \f/*
@@ -427,6 +441,11 @@ closexscript(e)
 **     Parameters:
 **             from -- the person we would like to believe this message
 **                     is from, as specified on the command line.
 **     Parameters:
 **             from -- the person we would like to believe this message
 **                     is from, as specified on the command line.
+**             e -- the envelope in which we would like the sender set.
+**             delimptr -- if non-NULL, set to the location of the
+**                     trailing delimiter.
+**             internal -- set if this address is coming from an internal
+**                     source such as an owner alias.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -435,18 +454,20 @@ closexscript(e)
 **             sets sendmail's notion of who the from person is.
 */
 
 **             sets sendmail's notion of who the from person is.
 */
 
-setsender(from)
+void
+setsender(from, e, delimptr, internal)
        char *from;
        char *from;
+       register ENVELOPE *e;
+       char **delimptr;
+       bool internal;
 {
        register char **pvp;
        char *realname = NULL;
        register struct passwd *pw;
 {
        register char **pvp;
        char *realname = NULL;
        register struct passwd *pw;
+       char delimchar;
        char buf[MAXNAME];
        char pvpbuf[PSBUFSIZE];
        extern struct passwd *getpwnam();
        char buf[MAXNAME];
        char pvpbuf[PSBUFSIZE];
        extern struct passwd *getpwnam();
-       extern char *macvalue();
-       extern char **prescan();
-       extern bool safefile();
        extern char *FullName;
 
        if (tTd(45, 1))
        extern char *FullName;
 
        if (tTd(45, 1))
@@ -457,102 +478,123 @@ setsender(from)
        **      Username can return errno != 0 on non-errors.
        */
 
        **      Username can return errno != 0 on non-errors.
        */
 
-       if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
+       if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP)
                realname = from;
        if (realname == NULL || realname[0] == '\0')
                realname = from;
        if (realname == NULL || realname[0] == '\0')
-       {
-               extern char *username();
-
                realname = username();
                realname = username();
-       }
-
-       /*
-       **  Determine if this real person is allowed to alias themselves.
-       */
 
 
-       if (from != NULL)
-       {
-               extern bool trusteduser();
-
-               if (!trusteduser(realname) && getuid() != geteuid() &&
-                   index(from, '!') == NULL && getuid() != 0)
-               {
-                       /* network sends -r regardless (why why why?) */
-                       /* syserr("%s, you cannot use the -f flag", realname); */
-                       from = NULL;
-               }
-       }
+       if (ConfigLevel < 2)
+               SuprErrs = TRUE;
 
 
-       SuprErrs = TRUE;
-       if (from == NULL || parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL)
+       delimchar = internal ? '\0' : ' ';
+       if (from == NULL ||
+           parseaddr(from, &e->e_from, 1, delimchar, delimptr, e) == NULL)
        {
                /* log garbage addresses for traceback */
        {
                /* log garbage addresses for traceback */
-               if (from != NULL)
-               {
 # ifdef LOG
 # ifdef LOG
-                       if (LogLevel >= 1)
-                           if (realname == from && RealHostName != NULL)
-                               syslog(LOG_NOTICE,
-                                   "from=%s unparseable, received from %s",
-                                   from, RealHostName);
-                           else
-                               syslog(LOG_NOTICE,
-                                   "Unparseable username %s wants from=%s",
-                                   realname, from);
-# endif LOG
+               if (from != NULL && LogLevel > 2)
+               {
+                       char *p;
+                       char ebuf[MAXNAME * 2 + 2];
+
+                       p = macvalue('_', e);
+                       if (p == NULL)
+                       {
+                               char *host = RealHostName;
+                               if (host == NULL)
+                                       host = MyHostName;
+                               (void) sprintf(ebuf, "%s@%s", realname, host);
+                               p = ebuf;
+                       }
+                       syslog(LOG_NOTICE,
+                               "from=%s unparseable, received from %s",
+                               from, p);
                }
                }
-               from = newstr(realname);
-               if (parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL &&
-                   parseaddr("postmaster", &CurEnv->e_from, 1, '\0') == NULL)
+# endif /* LOG */
+               if (from != NULL)
+                       SuprErrs = TRUE;
+               if (from == realname ||
+                   parseaddr(from = newstr(realname), &e->e_from, 1, ' ', NULL, e) == NULL)
                {
                {
-                       syserr("setsender: can't even parse postmaster!");
+                       SuprErrs = TRUE;
+                       if (parseaddr("postmaster", &e->e_from, 1, ' ', NULL, e) == NULL)
+                               syserr("553 setsender: can't even parse postmaster!");
                }
        }
        else
                FromFlag = TRUE;
                }
        }
        else
                FromFlag = TRUE;
-       CurEnv->e_from.q_flags |= QDONTSEND;
-       loweraddr(&CurEnv->e_from);
+       e->e_from.q_flags |= QDONTSEND;
+       if (tTd(45, 5))
+       {
+               printf("setsender: QDONTSEND ");
+               printaddr(&e->e_from, FALSE);
+       }
        SuprErrs = FALSE;
 
        SuprErrs = FALSE;
 
-       if (CurEnv->e_from.q_mailer == LocalMailer &&
-           (pw = getpwnam(CurEnv->e_from.q_user)) != NULL)
+       pvp = NULL;
+       if (e->e_from.q_mailer == LocalMailer)
        {
        {
-               /*
-               **  Process passwd file entry.
-               */
-
-
-               /* extract home directory */
-               CurEnv->e_from.q_home = newstr(pw->pw_dir);
-               define('z', CurEnv->e_from.q_home, CurEnv);
-
-               /* extract user and group id */
-               CurEnv->e_from.q_uid = pw->pw_uid;
-               CurEnv->e_from.q_gid = pw->pw_gid;
+# ifdef USERDB
+               register char *p;
+               extern char *udbsender();
+# endif
 
 
-               /* if the user has given fullname already, don't redefine */
-               if (FullName == NULL)
-                       FullName = macvalue('x', CurEnv);
-               if (FullName != NULL && FullName[0] == '\0')
-                       FullName = NULL;
+               if (!internal)
+               {
+                       /* if the user has given fullname already, don't redefine */
+                       if (FullName == NULL)
+                               FullName = macvalue('x', e);
+                       if (FullName != NULL && FullName[0] == '\0')
+                               FullName = NULL;
+
+# ifdef USERDB
+                       p = udbsender(from);
+
+                       if (p != NULL)
+                       {
+                               /*
+                               **  We have an alternate address for the sender
+                               */
+
+                               pvp = prescan(p, '\0', pvpbuf, NULL);
+                       }
+# endif /* USERDB */
+               }
 
 
-               /* extract full name from passwd file */
-               if (FullName == NULL && pw->pw_gecos != NULL &&
-                   strcmp(pw->pw_name, CurEnv->e_from.q_user) == 0)
+               if ((pw = getpwnam(e->e_from.q_user)) != NULL)
                {
                {
-                       buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf);
-                       if (buf[0] != '\0')
-                               FullName = newstr(buf);
+                       /*
+                       **  Process passwd file entry.
+                       */
+
+
+                       /* extract home directory */
+                       e->e_from.q_home = newstr(pw->pw_dir);
+                       define('z', e->e_from.q_home, e);
+
+                       /* extract user and group id */
+                       e->e_from.q_uid = pw->pw_uid;
+                       e->e_from.q_gid = pw->pw_gid;
+
+                       /* extract full name from passwd file */
+                       if (FullName == NULL && pw->pw_gecos != NULL &&
+                           strcmp(pw->pw_name, e->e_from.q_user) == 0 &&
+                           !internal)
+                       {
+                               buildfname(pw->pw_gecos, e->e_from.q_user, buf);
+                               if (buf[0] != '\0')
+                                       FullName = newstr(buf);
+                       }
                }
                }
-               if (FullName != NULL)
-                       define('x', FullName, CurEnv);
+               if (FullName != NULL && !internal)
+                       define('x', FullName, e);
        }
        }
-       else
+       else if (!internal)
        {
        {
-               if (CurEnv->e_from.q_home == NULL)
-                       CurEnv->e_from.q_home = getenv("HOME");
-               CurEnv->e_from.q_uid = getuid();
-               CurEnv->e_from.q_gid = getgid();
+               if (e->e_from.q_home == NULL)
+                       e->e_from.q_home = getenv("HOME");
+               e->e_from.q_uid = getuid();
+               e->e_from.q_gid = getgid();
        }
 
        /*
        }
 
        /*
@@ -560,57 +602,33 @@ setsender(from)
        **      links in the net.
        */
 
        **      links in the net.
        */
 
-       pvp = prescan(from, '\0', pvpbuf);
+       if (pvp == NULL)
+               pvp = prescan(from, '\0', pvpbuf, NULL);
        if (pvp == NULL)
        {
        if (pvp == NULL)
        {
+               /* don't need to give error -- prescan did that already */
 # ifdef LOG
 # ifdef LOG
-               if (LogLevel >= 1)
+               if (LogLevel > 2)
                        syslog(LOG_NOTICE, "cannot prescan from (%s)", from);
 # endif
                        syslog(LOG_NOTICE, "cannot prescan from (%s)", from);
 # endif
-               usrerr("cannot prescan from (%s)", from);
                finis();
        }
                finis();
        }
-       rewrite(pvp, 3);
-       rewrite(pvp, 1);
-       rewrite(pvp, 4);
-       cataddr(pvp, buf, sizeof buf);
-       define('f', newstr(buf), CurEnv);
+       (void) rewrite(pvp, 3, e);
+       (void) rewrite(pvp, 1, e);
+       (void) rewrite(pvp, 4, e);
+       cataddr(pvp, NULL, buf, sizeof buf, '\0');
+       e->e_sender = newstr(buf);
+       define('f', e->e_sender, e);
 
        /* save the domain spec if this mailer wants it */
 
        /* save the domain spec if this mailer wants it */
-       if (CurEnv->e_from.q_mailer != NULL &&
-           bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags))
+       if (!internal && e->e_from.q_mailer != NULL &&
+           bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
        {
                extern char **copyplist();
 
                while (*pvp != NULL && strcmp(*pvp, "@") != 0)
                        pvp++;
                if (*pvp != NULL)
        {
                extern char **copyplist();
 
                while (*pvp != NULL && strcmp(*pvp, "@") != 0)
                        pvp++;
                if (*pvp != NULL)
-                       CurEnv->e_fromdomain = copyplist(pvp, TRUE);
+                       e->e_fromdomain = copyplist(pvp, TRUE);
        }
 }
        }
 }
-\f/*
-**  TRUSTEDUSER -- tell us if this user is to be trusted.
-**
-**     Parameters:
-**             user -- the user to be checked.
-**
-**     Returns:
-**             TRUE if the user is in an approved list.
-**             FALSE otherwise.
-**
-**     Side Effects:
-**             none.
-*/
-
-bool
-trusteduser(user)
-       char *user;
-{
-       register char **ulist;
-       extern char *TrustedUsers[];
-
-       for (ulist = TrustedUsers; *ulist != NULL; ulist++)
-               if (strcmp(*ulist, user) == 0)
-                       return (TRUE);
-       return (FALSE);
-}
index 3242da0..57ffcce 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)err.c      5.11 (Berkeley) 3/2/91";
+static char sccsid[] = "@(#)err.c      8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -46,6 +46,11 @@ static char sccsid[] = "@(#)err.c    5.11 (Berkeley) 3/2/91";
 **     Prints an error message via printf to the diagnostic
 **     output.  If LOG is defined, it logs it also.
 **
 **     Prints an error message via printf to the diagnostic
 **     output.  If LOG is defined, it logs it also.
 **
+**     If the first character of the syserr message is `!' it will
+**     log this as an ALERT message and exit immediately.  This can
+**     leave queue files in an indeterminate state, so it should not
+**     be used lightly.
+**
 **     Parameters:
 **             f -- the format string
 **             a, b, c, d, e -- parameters
 **     Parameters:
 **             f -- the format string
 **             a, b, c, d, e -- parameters
@@ -67,21 +72,33 @@ char        MsgBuf[BUFSIZ*2];       /* text of most recent message */
 
 static void fmtmsg();
 
 
 static void fmtmsg();
 
+void
 /*VARARGS1*/
 /*VARARGS1*/
-syserr(fmt, a, b, c, d, e)
-       char *fmt;
+#ifdef __STDC__
+syserr(const char *fmt, ...)
+#else
+syserr(fmt, va_alist)
+       const char *fmt;
+       va_dcl
+#endif
 {
        register char *p;
        int olderrno = errno;
 {
        register char *p;
        int olderrno = errno;
-       extern char Arpa_PSyserr[];
-       extern char Arpa_TSyserr[];
+       bool panic;
+       VA_LOCAL_DECL
+
+       panic = *fmt == '!';
+       if (panic)
+               fmt++;
 
        /* format and output the error message */
        if (olderrno == 0)
 
        /* format and output the error message */
        if (olderrno == 0)
-               p = Arpa_PSyserr;
+               p = "554";
        else
        else
-               p = Arpa_TSyserr;
-       fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, a, b, c, d, e);
+               p = "451";
+       VA_START(fmt);
+       fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap);
+       VA_END;
        puterrmsg(MsgBuf);
 
        /* determine exit status if not already set */
        puterrmsg(MsgBuf);
 
        /* determine exit status if not already set */
@@ -95,10 +112,17 @@ syserr(fmt, a, b, c, d, e)
 
 # ifdef LOG
        if (LogLevel > 0)
 
 # ifdef LOG
        if (LogLevel > 0)
-               syslog(LOG_CRIT, "%s: SYSERR: %s",
+               syslog(panic ? LOG_ALERT : LOG_CRIT, "%s: SYSERR: %s",
                        CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
                        &MsgBuf[4]);
                        CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
                        &MsgBuf[4]);
-# endif LOG
+# endif /* LOG */
+       if (panic)
+       {
+#ifdef XLA
+               xla_all_end();
+#endif
+               exit(EX_OSERR);
+       }
        errno = 0;
        if (QuickAbort)
                longjmp(TopFrame, 2);
        errno = 0;
        if (QuickAbort)
                longjmp(TopFrame, 2);
@@ -120,19 +144,34 @@ syserr(fmt, a, b, c, d, e)
 */
 
 /*VARARGS1*/
 */
 
 /*VARARGS1*/
-usrerr(fmt, a, b, c, d, e)
-       char *fmt;
+void
+#ifdef __STDC__
+usrerr(const char *fmt, ...)
+#else
+usrerr(fmt, va_alist)
+       const char *fmt;
+       va_dcl
+#endif
 {
 {
+       VA_LOCAL_DECL
        extern char SuprErrs;
        extern char SuprErrs;
-       extern char Arpa_Usrerr[];
        extern int errno;
 
        if (SuprErrs)
                return;
 
        extern int errno;
 
        if (SuprErrs)
                return;
 
-       fmtmsg(MsgBuf, CurEnv->e_to, Arpa_Usrerr, errno, fmt, a, b, c, d, e);
+       VA_START(fmt);
+       fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap);
+       VA_END;
        puterrmsg(MsgBuf);
 
        puterrmsg(MsgBuf);
 
+# ifdef LOG
+       if (LogLevel > 3 && LogUsrErrs)
+               syslog(LOG_NOTICE, "%s: %s",
+                       CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
+                       &MsgBuf[4]);
+# endif /* LOG */
+
        if (QuickAbort)
                longjmp(TopFrame, 1);
 }
        if (QuickAbort)
                longjmp(TopFrame, 1);
 }
@@ -140,9 +179,8 @@ usrerr(fmt, a, b, c, d, e)
 **  MESSAGE -- print message (not necessarily an error)
 **
 **     Parameters:
 **  MESSAGE -- print message (not necessarily an error)
 **
 **     Parameters:
-**             num -- the default ARPANET error number (in ascii)
-**             msg -- the message (printf fmt) -- if it begins
-**                     with a digit, this number overrides num.
+**             msg -- the message (printf fmt) -- it can begin with
+**                     an SMTP reply code.  If not, 050 is assumed.
 **             a, b, c, d, e -- printf arguments
 **
 **     Returns:
 **             a, b, c, d, e -- printf arguments
 **
 **     Returns:
@@ -153,12 +191,21 @@ usrerr(fmt, a, b, c, d, e)
 */
 
 /*VARARGS2*/
 */
 
 /*VARARGS2*/
-message(num, msg, a, b, c, d, e)
-       register char *num;
-       register char *msg;
+void
+#ifdef __STDC__
+message(const char *msg, ...)
+#else
+message(msg, va_alist)
+       const char *msg;
+       va_dcl
+#endif
 {
 {
+       VA_LOCAL_DECL
+
        errno = 0;
        errno = 0;
-       fmtmsg(MsgBuf, CurEnv->e_to, num, 0, msg, a, b, c, d, e);
+       VA_START(msg);
+       fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
+       VA_END;
        putmsg(MsgBuf, FALSE);
 }
 \f/*
        putmsg(MsgBuf, FALSE);
 }
 \f/*
@@ -180,12 +227,21 @@ message(num, msg, a, b, c, d, e)
 */
 
 /*VARARGS2*/
 */
 
 /*VARARGS2*/
-nmessage(num, msg, a, b, c, d, e)
-       register char *num;
-       register char *msg;
+void
+#ifdef __STDC__
+nmessage(const char *msg, ...)
+#else
+nmessage(msg, va_alist)
+       const char *msg;
+       va_dcl
+#endif
 {
 {
+       VA_LOCAL_DECL
+
        errno = 0;
        errno = 0;
-       fmtmsg(MsgBuf, (char *) NULL, num, 0, msg, a, b, c, d, e);
+       VA_START(msg);
+       fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
+       VA_END;
        putmsg(MsgBuf, FALSE);
 }
 \f/*
        putmsg(MsgBuf, FALSE);
 }
 \f/*
@@ -214,15 +270,32 @@ putmsg(msg, holdmsg)
                fprintf(CurEnv->e_xfp, "%s\n", msg);
 
        /* output to channel if appropriate */
                fprintf(CurEnv->e_xfp, "%s\n", msg);
 
        /* output to channel if appropriate */
-       if (!holdmsg && (Verbose || msg[0] != '0'))
-       {
-               (void) fflush(stdout);
-               if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
-                       fprintf(OutChannel, "%s\r\n", msg);
-               else
-                       fprintf(OutChannel, "%s\n", &msg[4]);
+       if (holdmsg || (!Verbose && msg[0] == '0'))
+               return;
+
+       (void) fflush(stdout);
+       if (OpMode == MD_SMTP)
+               fprintf(OutChannel, "%s\r\n", msg);
+       else
+               fprintf(OutChannel, "%s\n", &msg[4]);
+       if (msg[3] == ' ')
                (void) fflush(OutChannel);
                (void) fflush(OutChannel);
-       }
+       if (!ferror(OutChannel))
+               return;
+
+       /* error on output -- if reporting lost channel, just ignore it */
+       if (feof(InChannel) || ferror(InChannel))
+               return;
+
+       /* can't call syserr, 'cause we are using MsgBuf */
+       HoldErrs = TRUE;
+#ifdef LOG
+       if (LogLevel > 0)
+               syslog(LOG_CRIT,
+                       "%s: SYSERR: putmsg (%s): error on output channel sending \"%s\"",
+                       CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
+                       CurHostName, msg);
+#endif
 }
 \f/*
 **  PUTERRMSG -- like putmsg, but does special processing for error messages
 }
 \f/*
 **  PUTERRMSG -- like putmsg, but does special processing for error messages
@@ -266,16 +339,17 @@ puterrmsg(msg)
 **             none.
 */
 
 **             none.
 */
 
-/*VARARGS5*/
 static void
 static void
-fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
+fmtmsg(eb, to, num, eno, fmt, ap)
        register char *eb;
        char *to;
        char *num;
        int eno;
        char *fmt;
        register char *eb;
        char *to;
        char *num;
        int eno;
        char *fmt;
+       va_list ap;
 {
        char del;
 {
        char del;
+       char *meb;
 
        /* output the reply code */
        if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
 
        /* output the reply code */
        if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
@@ -305,19 +379,22 @@ fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
                        *eb++ &= 0177;
        }
 
                        *eb++ &= 0177;
        }
 
+       meb = eb;
+
        /* output the message */
        /* output the message */
-       (void) sprintf(eb, fmt, a, b, c, d, e);
+       (void) vsprintf(eb, fmt, ap);
        while (*eb != '\0')
                *eb++ &= 0177;
 
        /* output the error code, if any */
        if (eno != 0)
        {
        while (*eb != '\0')
                *eb++ &= 0177;
 
        /* output the error code, if any */
        if (eno != 0)
        {
-               extern char *errstring();
-
                (void) sprintf(eb, ": %s", errstring(eno));
                eb += strlen(eb);
        }
                (void) sprintf(eb, ": %s", errstring(eno));
                eb += strlen(eb);
        }
+
+       if (CurEnv->e_message == NULL && strchr("45", num[0]) != NULL)
+               CurEnv->e_message = newstr(meb);
 }
 \f/*
 **  ERRSTRING -- return string description of error code
 }
 \f/*
 **  ERRSTRING -- return string description of error code
@@ -332,19 +409,19 @@ fmtmsg(eb, to, num, eno, fmt, a, b, c, d, e)
 **             none.
 */
 
 **             none.
 */
 
-char *
+const char *
 errstring(errno)
        int errno;
 {
 errstring(errno)
        int errno;
 {
-       extern char *sys_errlist[];
+       extern const char *const sys_errlist[];
        extern int sys_nerr;
        extern int sys_nerr;
-       static char buf[100];
+       static char buf[MAXLINE];
 # ifdef SMTP
        extern char *SmtpPhase;
 # ifdef SMTP
        extern char *SmtpPhase;
-# endif SMTP
+# endif /* SMTP */
 
 # ifdef DAEMON
 
 # ifdef DAEMON
-# ifdef VMUNIX
+# ifdef ETIMEDOUT
        /*
        **  Handle special network error codes.
        **
        /*
        **  Handle special network error codes.
        **
@@ -380,12 +457,22 @@ errstring(errno)
                (void) sprintf(buf, "Connection refused by %s", CurHostName);
                return (buf);
 
                (void) sprintf(buf, "Connection refused by %s", CurHostName);
                return (buf);
 
-         case (TRY_AGAIN+MAX_ERRNO):
-               (void) sprintf(buf, "Host Name Lookup Failure");
-               return (buf);
+# ifdef NAMED_BIND
+         case HOST_NOT_FOUND + MAX_ERRNO:
+               return ("Name server: host not found");
+
+         case TRY_AGAIN + MAX_ERRNO:
+               return ("Name server: host name lookup failure");
+
+         case NO_RECOVERY + MAX_ERRNO:
+               return ("Name server: non-recoverable error");
+
+         case NO_DATA + MAX_ERRNO:
+               return ("Name server: no data known for name");
+# endif
        }
        }
-# endif VMUNIX
-# endif DAEMON
+# endif
+# endif
 
        if (errno > 0 && errno < sys_nerr)
                return (sys_errlist[errno]);
 
        if (errno > 0 && errno < sys_nerr)
                return (sys_errlist[errno]);
index 02950f0..387b7fb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)headers.c  5.15 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)headers.c  8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #endif /* not lint */
 
-# include <sys/param.h>
 # include <errno.h>
 # include "sendmail.h"
 
 # include <errno.h>
 # include "sendmail.h"
 
@@ -48,6 +47,7 @@ static char sccsid[] = "@(#)headers.c 5.15 (Berkeley) 6/1/90";
 **     Parameters:
 **             line -- header as a text line.
 **             def -- if set, this is a default value.
 **     Parameters:
 **             line -- header as a text line.
 **             def -- if set, this is a default value.
+**             e -- the envelope including this header.
 **
 **     Returns:
 **             flags for this header.
 **
 **     Returns:
 **             flags for this header.
@@ -57,9 +57,10 @@ static char sccsid[] = "@(#)headers.c        5.15 (Berkeley) 6/1/90";
 **             Contents of 'line' are destroyed.
 */
 
 **             Contents of 'line' are destroyed.
 */
 
-chompheader(line, def)
+chompheader(line, def, e)
        char *line;
        bool def;
        char *line;
        bool def;
+       register ENVELOPE *e;
 {
        register char *p;
        register HDR *h;
 {
        register char *p;
        register HDR *h;
@@ -69,7 +70,6 @@ chompheader(line, def)
        struct hdrinfo *hi;
        bool cond = FALSE;
        BITMAP mopts;
        struct hdrinfo *hi;
        bool cond = FALSE;
        BITMAP mopts;
-       extern char *crackaddr();
 
        if (tTd(31, 6))
                printf("chompheader: %s\n", line);
 
        if (tTd(31, 6))
                printf("chompheader: %s\n", line);
@@ -80,7 +80,7 @@ chompheader(line, def)
        if (*p == '?')
        {
                /* have some */
        if (*p == '?')
        {
                /* have some */
-               register char *q = index(p + 1, *p);
+               register char *q = strchr(p + 1, *p);
                
                if (q != NULL)
                {
                
                if (q != NULL)
                {
@@ -90,23 +90,22 @@ chompheader(line, def)
                        p = q;
                }
                else
                        p = q;
                }
                else
-                       usrerr("chompheader: syntax error, line \"%s\"", line);
+                       usrerr("553 header syntax error, line \"%s\"", line);
                cond = TRUE;
        }
 
        /* find canonical name */
        fname = p;
                cond = TRUE;
        }
 
        /* find canonical name */
        fname = p;
-       p = index(p, ':');
+       p = strchr(p, ':');
        if (p == NULL)
        {
        if (p == NULL)
        {
-               syserr("chompheader: syntax error, line \"%s\"", line);
+               syserr("553 header syntax error, line \"%s\"", line);
                return (0);
        }
        fvalue = &p[1];
                return (0);
        }
        fvalue = &p[1];
-       while (isspace(*--p))
+       while (isascii(*--p) && isspace(*p))
                continue;
        *++p = '\0';
                continue;
        *++p = '\0';
-       makelower(fname);
 
        /* strip field value on front */
        if (*fvalue == ' ')
 
        /* strip field value on front */
        if (*fvalue == ' ')
@@ -115,13 +114,13 @@ chompheader(line, def)
        /* see if it is a known type */
        for (hi = HdrInfo; hi->hi_field != NULL; hi++)
        {
        /* see if it is a known type */
        for (hi = HdrInfo; hi->hi_field != NULL; hi++)
        {
-               if (strcmp(hi->hi_field, fname) == 0)
+               if (strcasecmp(hi->hi_field, fname) == 0)
                        break;
        }
 
        /* see if this is a resent message */
        if (!def && bitset(H_RESENT, hi->hi_flags))
                        break;
        }
 
        /* see if this is a resent message */
        if (!def && bitset(H_RESENT, hi->hi_flags))
-               CurEnv->e_flags |= EF_RESENT;
+               e->e_flags |= EF_RESENT;
 
        /* if this means "end of header" quit now */
        if (bitset(H_EOH, hi->hi_flags))
 
        /* if this means "end of header" quit now */
        if (bitset(H_EOH, hi->hi_flags))
@@ -129,19 +128,19 @@ chompheader(line, def)
 
        /* drop explicit From: if same as what we would generate -- for MH */
        p = "resent-from";
 
        /* drop explicit From: if same as what we would generate -- for MH */
        p = "resent-from";
-       if (!bitset(EF_RESENT, CurEnv->e_flags))
+       if (!bitset(EF_RESENT, e->e_flags))
                p += 7;
                p += 7;
-       if (!def && !QueueRun && strcmp(fname, p) == 0)
+       if (!def && !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0)
        {
        {
-               if (CurEnv->e_from.q_paddr != NULL &&
-                   strcmp(fvalue, CurEnv->e_from.q_paddr) == 0)
+               if (e->e_from.q_paddr != NULL &&
+                   strcmp(fvalue, e->e_from.q_paddr) == 0)
                        return (hi->hi_flags);
        }
 
        /* delete default value for this header */
                        return (hi->hi_flags);
        }
 
        /* delete default value for this header */
-       for (hp = &CurEnv->e_header; (h = *hp) != NULL; hp = &h->h_link)
+       for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link)
        {
        {
-               if (strcmp(fname, h->h_field) == 0 &&
+               if (strcasecmp(fname, h->h_field) == 0 &&
                    bitset(H_DEFAULT, h->h_flags) &&
                    !bitset(H_FORCE, h->h_flags))
                        h->h_value = NULL;
                    bitset(H_DEFAULT, h->h_flags) &&
                    !bitset(H_FORCE, h->h_flags))
                        h->h_value = NULL;
@@ -165,10 +164,10 @@ chompheader(line, def)
 
        /* hack to see if this is a new format message */
        if (!def && bitset(H_RCPT|H_FROM, h->h_flags) &&
 
        /* hack to see if this is a new format message */
        if (!def && bitset(H_RCPT|H_FROM, h->h_flags) &&
-           (index(fvalue, ',') != NULL || index(fvalue, '(') != NULL ||
-            index(fvalue, '<') != NULL || index(fvalue, ';') != NULL))
+           (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||
+            strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))
        {
        {
-               CurEnv->e_flags &= ~EF_OLDSTYLE;
+               e->e_flags &= ~EF_OLDSTYLE;
        }
 
        return (h->h_flags);
        }
 
        return (h->h_flags);
@@ -180,7 +179,7 @@ chompheader(line, def)
 **
 **     Parameters:
 **             field -- the name of the header field.
 **
 **     Parameters:
 **             field -- the name of the header field.
-**             value -- the value of the field.  It must be lower-cased.
+**             value -- the value of the field.
 **             e -- the envelope to add them to.
 **
 **     Returns:
 **             e -- the envelope to add them to.
 **
 **     Returns:
@@ -202,14 +201,14 @@ addheader(field, value, e)
        /* find info struct */
        for (hi = HdrInfo; hi->hi_field != NULL; hi++)
        {
        /* find info struct */
        for (hi = HdrInfo; hi->hi_field != NULL; hi++)
        {
-               if (strcmp(field, hi->hi_field) == 0)
+               if (strcasecmp(field, hi->hi_field) == 0)
                        break;
        }
 
        /* find current place in list -- keep back pointer? */
        for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link)
        {
                        break;
        }
 
        /* find current place in list -- keep back pointer? */
        for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link)
        {
-               if (strcmp(field, h->h_field) == 0)
+               if (strcasecmp(field, h->h_field) == 0)
                        break;
        }
 
                        break;
        }
 
@@ -230,6 +229,7 @@ addheader(field, value, e)
 **
 **     Parameters:
 **             field -- the field name.
 **
 **     Parameters:
 **             field -- the field name.
+**             e -- the envelope containing the header.
 **
 **     Returns:
 **             pointer to the value part.
 **
 **     Returns:
 **             pointer to the value part.
@@ -240,14 +240,16 @@ addheader(field, value, e)
 */
 
 char *
 */
 
 char *
-hvalue(field)
+hvalue(field, e)
        char *field;
        char *field;
+       register ENVELOPE *e;
 {
        register HDR *h;
 
 {
        register HDR *h;
 
-       for (h = CurEnv->e_header; h != NULL; h = h->h_link)
+       for (h = e->e_header; h != NULL; h = h->h_link)
        {
        {
-               if (!bitset(H_DEFAULT, h->h_flags) && strcmp(h->h_field, field) == 0)
+               if (!bitset(H_DEFAULT, h->h_flags) &&
+                   strcasecmp(h->h_field, field) == 0)
                        return (h->h_value);
        }
        return (NULL);
                        return (h->h_value);
        }
        return (NULL);
@@ -277,7 +279,7 @@ isheader(s)
                s++;
 
        /* following technically violates RFC822 */
                s++;
 
        /* following technically violates RFC822 */
-       while (isspace(*s))
+       while (isascii(*s) && isspace(*s))
                s++;
 
        return (*s == ':');
                s++;
 
        return (*s == ':');
@@ -287,6 +289,8 @@ isheader(s)
 **
 **     Parameters:
 **             e -- the envelope to process.
 **
 **     Parameters:
 **             e -- the envelope to process.
+**             full -- if set, do full processing (e.g., compute
+**                     message priority).
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -297,21 +301,42 @@ isheader(s)
 **             Aborts the message if the hop count is exceeded.
 */
 
 **             Aborts the message if the hop count is exceeded.
 */
 
-eatheader(e)
+eatheader(e, full)
        register ENVELOPE *e;
        register ENVELOPE *e;
+       bool full;
 {
        register HDR *h;
        register char *p;
        int hopcnt = 0;
 {
        register HDR *h;
        register char *p;
        int hopcnt = 0;
+       char *msgid;
+       char buf[MAXLINE];
+
+       /*
+       **  Set up macros for possible expansion in headers.
+       */
+
+       define('f', e->e_sender, e);
+       define('g', e->e_sender, e);
 
        if (tTd(32, 1))
                printf("----- collected header -----\n");
 
        if (tTd(32, 1))
                printf("----- collected header -----\n");
+       msgid = "<none>";
        for (h = e->e_header; h != NULL; h = h->h_link)
        {
        for (h = e->e_header; h != NULL; h = h->h_link)
        {
-               extern char *capitalize();
+               /* do early binding */
+               if (bitset(H_DEFAULT, h->h_flags) && h->h_value != NULL)
+               {
+                       expand(h->h_value, buf, &buf[sizeof buf], e);
+                       if (buf[0] != '\0')
+                       {
+                               h->h_value = newstr(buf);
+                               h->h_flags &= ~H_DEFAULT;
+                       }
+               }
 
                if (tTd(32, 1))
 
                if (tTd(32, 1))
-                       printf("%s: %s\n", capitalize(h->h_field), h->h_value);
+                       printf("%s: %s\n", h->h_field, h->h_value);
+
                /* count the number of times it has been processed */
                if (bitset(H_TRACE, h->h_flags))
                        hopcnt++;
                /* count the number of times it has been processed */
                if (bitset(H_TRACE, h->h_flags))
                        hopcnt++;
@@ -319,107 +344,110 @@ eatheader(e)
                /* send to this person if we so desire */
                if (GrabTo && bitset(H_RCPT, h->h_flags) &&
                    !bitset(H_DEFAULT, h->h_flags) &&
                /* send to this person if we so desire */
                if (GrabTo && bitset(H_RCPT, h->h_flags) &&
                    !bitset(H_DEFAULT, h->h_flags) &&
-                   (!bitset(EF_RESENT, CurEnv->e_flags) || bitset(H_RESENT, h->h_flags)))
+                   (!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
                {
                {
-                       sendtolist(h->h_value, (ADDRESS *) NULL, &CurEnv->e_sendqueue);
+                       (void) sendtolist(h->h_value, (ADDRESS *) NULL,
+                                         &e->e_sendqueue, e);
                }
 
                }
 
-               /* log the message-id */
-#ifdef LOG
-               if (!QueueRun && LogLevel > 8 && h->h_value != NULL &&
-                   strcmp(h->h_field, "message-id") == 0)
+               /* save the message-id for logging */
+               if (full && h->h_value != NULL &&
+                   strcasecmp(h->h_field, "message-id") == 0)
                {
                {
-                       char buf[MAXNAME];
-
-                       p = h->h_value;
-                       if (bitset(H_DEFAULT, h->h_flags))
-                       {
-                               expand(p, buf, &buf[sizeof buf], e);
-                               p = buf;
-                       }
-                       syslog(LOG_INFO, "%s: message-id=%s", e->e_id, p);
+                       msgid = h->h_value;
+                       while (isascii(*msgid) && isspace(*msgid))
+                               msgid++;
                }
                }
-#endif LOG
+
+               /* see if this is a return-receipt header */
+               if (bitset(H_RECEIPTTO, h->h_flags))
+                       e->e_receiptto = h->h_value;
+
+               /* see if this is an errors-to header */
+               if (UseErrorsTo && bitset(H_ERRORSTO, h->h_flags))
+                       (void) sendtolist(h->h_value, (ADDRESS *) NULL,
+                                         &e->e_errorqueue, e);
        }
        if (tTd(32, 1))
                printf("----------------------------\n");
 
        }
        if (tTd(32, 1))
                printf("----------------------------\n");
 
+       /* if we are just verifying (that is, sendmail -t -bv), drop out now */
+       if (OpMode == MD_VERIFY)
+               return;
+
        /* store hop count */
        if (hopcnt > e->e_hopcount)
                e->e_hopcount = hopcnt;
 
        /* message priority */
        /* store hop count */
        if (hopcnt > e->e_hopcount)
                e->e_hopcount = hopcnt;
 
        /* message priority */
-       p = hvalue("precedence");
+       p = hvalue("precedence", e);
        if (p != NULL)
                e->e_class = priencode(p);
        if (p != NULL)
                e->e_class = priencode(p);
-       if (!QueueRun)
+       if (full)
                e->e_msgpriority = e->e_msgsize
                                 - e->e_class * WkClassFact
                                 + e->e_nrcpts * WkRecipFact;
 
                e->e_msgpriority = e->e_msgsize
                                 - e->e_class * WkClassFact
                                 + e->e_nrcpts * WkRecipFact;
 
-       /* return receipt to */
-       p = hvalue("return-receipt-to");
-       if (p != NULL)
-               e->e_receiptto = p;
-
-       /* errors to */
-       p = hvalue("errors-to");
-       if (p != NULL)
-               sendtolist(p, (ADDRESS *) NULL, &e->e_errorqueue);
-
-       /* from person */
-       if (OpMode == MD_ARPAFTP)
-       {
-               register struct hdrinfo *hi = HdrInfo;
-
-               for (p = NULL; p == NULL && hi->hi_field != NULL; hi++)
-               {
-                       if (bitset(H_FROM, hi->hi_flags))
-                               p = hvalue(hi->hi_field);
-               }
-               if (p != NULL)
-                       setsender(p);
-       }
-
        /* full name of from person */
        /* full name of from person */
-       p = hvalue("full-name");
+       p = hvalue("full-name", e);
        if (p != NULL)
                define('x', p, e);
 
        /* date message originated */
        if (p != NULL)
                define('x', p, e);
 
        /* date message originated */
-       p = hvalue("posted-date");
+       p = hvalue("posted-date", e);
        if (p == NULL)
        if (p == NULL)
-               p = hvalue("date");
+               p = hvalue("date", e);
        if (p != NULL)
        if (p != NULL)
-       {
                define('a', p, e);
                define('a', p, e);
-               /* we don't have a good way to do canonical conversion ....
-               define('d', newstr(arpatounix(p)), e);
-               .... so we will ignore the problem for the time being */
-       }
 
        /*
        **  Log collection information.
        */
 
 # ifdef LOG
 
        /*
        **  Log collection information.
        */
 
 # ifdef LOG
-       if (!QueueRun && LogLevel > 1)
+       if (full && LogLevel > 4)
        {
        {
-               char hbuf[100], *name = hbuf;
-
-               if (RealHostName == NULL)
-                       name = "local";
+               char *name;
+               register char *sbp;
+               char hbuf[MAXNAME];
+               char sbuf[MAXLINE];
+
+               if (bitset(EF_RESPONSE, e->e_flags))
+                       name = "[RESPONSE]";
+               else if ((name = macvalue('_', e)) != NULL)
+                       ;
                else if (RealHostName[0] == '[')
                        name = RealHostName;
                else
                else if (RealHostName[0] == '[')
                        name = RealHostName;
                else
-                       (void)sprintf(hbuf, "%.90s (%s)", 
-                           RealHostName, inet_ntoa(RealHostAddr.sin_addr));
-               syslog(LOG_INFO,
-                   "%s: from=%s, size=%ld, class=%d, received from %s\n",
-                   CurEnv->e_id, CurEnv->e_from.q_paddr, CurEnv->e_msgsize,
-                   CurEnv->e_class, name);
+               {
+                       name = hbuf;
+                       (void) sprintf(hbuf, "%.80s", RealHostName);
+                       if (RealHostAddr.sa.sa_family != 0)
+                       {
+                               p = &hbuf[strlen(hbuf)];
+                               (void) sprintf(p, " (%s)",
+                                       anynet_ntoa(&RealHostAddr));
+                       }
+               }
+
+               /* some versions of syslog only take 5 printf args */
+               sbp = sbuf;
+               sprintf(sbp, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d, msgid=%.100s",
+                   e->e_from.q_paddr, e->e_msgsize, e->e_class,
+                   e->e_msgpriority, e->e_nrcpts, msgid);
+               sbp += strlen(sbp);
+               if (e->e_bodytype != NULL)
+               {
+                       (void) sprintf(sbp, ", bodytype=%.20s", e->e_bodytype);
+                       sbp += strlen(sbp);
+               }
+               p = macvalue('r', e);
+               if (p != NULL)
+                       (void) sprintf(sbp, ", proto=%.20s", p);
+               syslog(LOG_INFO, "%s: %s, relay=%s",
+                   e->e_id, sbuf, name);
        }
        }
-# endif LOG
+# endif /* LOG */
 }
 \f/*
 **  PRIENCODE -- encode external priority names into internal values.
 }
 \f/*
 **  PRIENCODE -- encode external priority names into internal values.
@@ -457,16 +485,10 @@ priencode(p)
 **     identical to what it started with.  However, it does leave
 **     something semantically identical.
 **
 **     identical to what it started with.  However, it does leave
 **     something semantically identical.
 **
-**     The process is kind of strange.  There are a number of
-**     interesting cases:
-**             1.  comment <address> comment   ==> comment <$g> comment
-**             2.  address                     ==> address
-**             3.  address (comment)           ==> $g (comment)
-**             4.  (comment) address           ==> (comment) $g
-**     And then there are the hard cases....
-**             5.  add (comment) ress          ==> $g (comment)
-**             6.  comment <address (comment)> ==> comment <$g (comment)>
-**             7.    .... etc ....
+**     This algorithm has been cleaned up to handle a wider range
+**     of cases -- notably quoted and backslash escaped strings.
+**     This modification makes it substantially better at preserving
+**     the original syntax.
 **
 **     Parameters:
 **             addr -- the address to be cracked.
 **
 **     Parameters:
 **             addr -- the address to be cracked.
@@ -487,132 +509,221 @@ crackaddr(addr)
        register char *addr;
 {
        register char *p;
        register char *addr;
 {
        register char *p;
-       register int i;
-       static char buf[MAXNAME];
-       char *rhs;
-       bool gotaddr;
+       register char c;
+       int cmtlev;
+       int realcmtlev;
+       int anglelev, realanglelev;
+       int copylev;
+       bool qmode;
+       bool realqmode;
+       bool skipping;
+       bool putgmac = FALSE;
+       bool quoteit = FALSE;
        register char *bp;
        register char *bp;
+       char *buflim;
+       static char buf[MAXNAME];
 
        if (tTd(33, 1))
                printf("crackaddr(%s)\n", addr);
 
 
        if (tTd(33, 1))
                printf("crackaddr(%s)\n", addr);
 
-       (void) strcpy(buf, "");
-       rhs = NULL;
-
        /* strip leading spaces */
        /* strip leading spaces */
-       while (*addr != '\0' && isspace(*addr))
+       while (*addr != '\0' && isascii(*addr) && isspace(*addr))
                addr++;
 
        /*
                addr++;
 
        /*
-       **  See if we have anything in angle brackets.  If so, that is
-       **  the address part, and the rest is the comment.
+       **  Start by assuming we have no angle brackets.  This will be
+       **  adjusted later if we find them.
        */
 
        */
 
-       p = index(addr, '<');
-       if (p != NULL)
+       bp = buf;
+       buflim = &buf[sizeof buf - 5];
+       p = addr;
+       copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
+       qmode = realqmode = FALSE;
+
+       while ((c = *p++) != '\0')
        {
        {
-               /* copy the beginning of the addr field to the buffer */
-               *p = '\0';
-               (void) strcpy(buf, addr);
-               (void) strcat(buf, "<");
-               *p++ = '<';
+               /*
+               **  If the buffer is overful, go into a special "skipping"
+               **  mode that tries to keep legal syntax but doesn't actually
+               **  output things.
+               */
 
 
-               /* skip spaces */
-               while (isspace(*p))
-                       p++;
+               skipping = bp >= buflim;
+
+               if (copylev > 0 && !skipping)
+                       *bp++ = c;
 
 
-               /* find the matching right angle bracket */
-               addr = p;
-               for (i = 0; *p != '\0'; p++)
+               /* check for backslash escapes */
+               if (c == '\\')
                {
                {
-                       switch (*p)
-                       {
-                         case '<':
-                               i++;
-                               break;
+                       /* arrange to quote the address */
+                       if (cmtlev <= 0 && !qmode)
+                               quoteit = TRUE;
 
 
-                         case '>':
-                               i--;
-                               break;
+                       if ((c = *p++) == '\0')
+                       {
+                               /* too far */
+                               p--;
+                               goto putg;
                        }
                        }
-                       if (i < 0)
-                               break;
+                       if (copylev > 0 && !skipping)
+                               *bp++ = c;
+                       goto putg;
                }
 
                }
 
-               /* p now points to the closing quote (or a null byte) */
-               if (*p != '\0')
+               /* check for quoted strings */
+               if (c == '"')
                {
                {
-                       /* make rhs point to the extra stuff at the end */
-                       rhs = p;
-                       *p++ = '\0';
+                       qmode = !qmode;
+                       if (copylev > 0 && !skipping)
+                               realqmode = !realqmode;
+                       continue;
                }
                }
-       }
-
-       /*
-       **  Now parse the real address part.  "addr" points to the (null
-       **  terminated) version of what we are inerested in; rhs points
-       **  to the extra stuff at the end of the line, if any.
-       */
+               if (qmode)
+                       goto putg;
 
 
-       p = addr;
+               /* check for comments */
+               if (c == '(')
+               {
+                       cmtlev++;
 
 
-       /* now strip out comments */
-       bp = &buf[strlen(buf)];
-       gotaddr = FALSE;
-       for (; *p != '\0'; p++)
-       {
-               if (*p == '(')
+                       /* allow space for closing paren */
+                       if (!skipping)
+                       {
+                               buflim--;
+                               realcmtlev++;
+                               if (copylev++ <= 0)
+                               {
+                                       *bp++ = ' ';
+                                       *bp++ = c;
+                               }
+                       }
+               }
+               if (cmtlev > 0)
                {
                {
-                       /* copy to matching close paren */
-                       *bp++ = *p++;
-                       for (i = 0; *p != '\0'; p++)
+                       if (c == ')')
                        {
                        {
-                               *bp++ = *p;
-                               switch (*p)
+                               cmtlev--;
+                               copylev--;
+                               if (!skipping)
                                {
                                {
-                                 case '(':
-                                       i++;
-                                       break;
-
-                                 case ')':
-                                       i--;
-                                       break;
+                                       realcmtlev--;
+                                       buflim++;
                                }
                                }
-                               if (i < 0)
-                                       break;
                        }
                        continue;
                }
                        }
                        continue;
                }
+               else if (c == ')')
+               {
+                       /* syntax error: unmatched ) */
+                       if (!skipping)
+                               bp--;
+               }
 
 
-               /*
-               **  If this is the first "real" character we have seen,
-               **  then we put the "$g" in the buffer now.
-               */
 
 
-               if (isspace(*p))
-                       *bp++ = *p;
-               else if (!gotaddr)
+               /* check for characters that may have to be quoted */
+               if (strchr(".'@,;:\\()", c) != NULL)
                {
                {
-                       (void) strcpy(bp, "\001g");
-                       bp += 2;
-                       gotaddr = TRUE;
+                       /*
+                       **  If these occur as the phrase part of a <>
+                       **  construct, but are not inside of () or already
+                       **  quoted, they will have to be quoted.  Note that
+                       **  now (but don't actually do the quoting).
+                       */
+
+                       if (cmtlev <= 0 && !qmode)
+                               quoteit = TRUE;
                }
                }
-       }
 
 
-       /* hack, hack.... strip trailing blanks */
-       do
-       {
-               *bp-- = '\0';
-       } while (isspace(*bp));
-       bp++;
+               /* check for angle brackets */
+               if (c == '<')
+               {
+                       register char *q;
 
 
-       /* put any right hand side back on */
-       if (rhs != NULL)
-       {
-               *rhs = '>';
-               (void) strcpy(bp, rhs);
+                       /* oops -- have to change our mind */
+                       anglelev++;
+                       if (!skipping)
+                               realanglelev++;
+
+                       bp = buf;
+                       if (quoteit)
+                       {
+                               *bp++ = '"';
+
+                               /* back up over the '<' and any spaces */
+                               --p;
+                               while (isascii(*--p) && isspace(*p))
+                                       continue;
+                               p++;
+                       }
+                       for (q = addr; q < p; )
+                       {
+                               c = *q++;
+                               if (bp < buflim)
+                               {
+                                       if (quoteit && c == '"')
+                                               *bp++ = '\\';
+                                       *bp++ = c;
+                               }
+                       }
+                       if (quoteit)
+                       {
+                               *bp++ = '"';
+                               while ((c = *p++) != '<')
+                               {
+                                       if (bp < buflim)
+                                               *bp++ = c;
+                               }
+                               *bp++ = c;
+                       }
+                       copylev = 0;
+                       putgmac = quoteit = FALSE;
+                       continue;
+               }
+
+               if (c == '>')
+               {
+                       if (anglelev > 0)
+                       {
+                               anglelev--;
+                               if (!skipping)
+                               {
+                                       realanglelev--;
+                                       buflim++;
+                               }
+                       }
+                       else if (!skipping)
+                       {
+                               /* syntax error: unmatched > */
+                               if (copylev > 0)
+                                       bp--;
+                               continue;
+                       }
+                       if (copylev++ <= 0)
+                               *bp++ = c;
+                       continue;
+               }
+
+               /* must be a real address character */
+       putg:
+               if (copylev <= 0 && !putgmac)
+               {
+                       *bp++ = MACROEXPAND;
+                       *bp++ = 'g';
+                       putgmac = TRUE;
+               }
        }
 
        }
 
+       /* repair any syntactic damage */
+       if (realqmode)
+               *bp++ = '"';
+       while (realcmtlev-- > 0)
+               *bp++ = ')';
+       while (realanglelev-- > 0)
+               *bp++ = '>';
+       *bp++ = '\0';
+
        if (tTd(33, 1))
                printf("crackaddr=>`%s'\n", buf);
 
        if (tTd(33, 1))
                printf("crackaddr=>`%s'\n", buf);
 
@@ -633,29 +744,53 @@ crackaddr(addr)
 **             none.
 */
 
 **             none.
 */
 
+/*
+ * Macro for fast max (not available in e.g. DG/UX, 386/ix).
+ */
+#ifndef MAX
+# define MAX(a,b) (((a)>(b))?(a):(b))
+#endif
+
 putheader(fp, m, e)
        register FILE *fp;
        register MAILER *m;
        register ENVELOPE *e;
 {
 putheader(fp, m, e)
        register FILE *fp;
        register MAILER *m;
        register ENVELOPE *e;
 {
-       char buf[MAX(MAXFIELD,BUFSIZ)];
+       char buf[MAX(MAXLINE,BUFSIZ)];
        register HDR *h;
        register HDR *h;
-       extern char *arpadate();
-       extern char *capitalize();
-       char obuf[MAX(MAXFIELD,MAXLINE)];
+       char obuf[MAXLINE];
+
+       if (tTd(34, 1))
+               printf("--- putheader, mailer = %s ---\n", m->m_name);
 
        for (h = e->e_header; h != NULL; h = h->h_link)
        {
                register char *p;
                extern bool bitintersect();
 
 
        for (h = e->e_header; h != NULL; h = h->h_link)
        {
                register char *p;
                extern bool bitintersect();
 
+               if (tTd(34, 11))
+               {
+                       printf("  %s: ", h->h_field);
+                       xputs(h->h_value);
+               }
+
                if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
                    !bitintersect(h->h_mflags, m->m_flags))
                if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
                    !bitintersect(h->h_mflags, m->m_flags))
+               {
+                       if (tTd(34, 11))
+                               printf(" (skipped)\n");
                        continue;
                        continue;
+               }
 
                /* handle Resent-... headers specially */
                if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
 
                /* handle Resent-... headers specially */
                if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
+               {
+                       if (tTd(34, 11))
+                               printf(" (skipped (resent))\n");
                        continue;
                        continue;
+               }
+               if (tTd(34, 11))
+                       printf("\n");
 
                p = h->h_value;
                if (bitset(H_DEFAULT, h->h_flags))
 
                p = h->h_value;
                if (bitset(H_DEFAULT, h->h_flags))
@@ -674,15 +809,15 @@ putheader(fp, m, e)
 
                        if (bitset(H_FROM, h->h_flags))
                                oldstyle = FALSE;
 
                        if (bitset(H_FROM, h->h_flags))
                                oldstyle = FALSE;
-                       commaize(h, p, fp, oldstyle, m);
+                       commaize(h, p, fp, oldstyle, m, e);
                }
                else
                {
                        /* vanilla header line */
                        register char *nlp;
 
                }
                else
                {
                        /* vanilla header line */
                        register char *nlp;
 
-                       (void) sprintf(obuf, "%s: ", capitalize(h->h_field));
-                       while ((nlp = index(p, '\n')) != NULL)
+                       (void) sprintf(obuf, "%s: ", h->h_field);
+                       while ((nlp = strchr(p, '\n')) != NULL)
                        {
                                *nlp = '\0';
                                (void) strcat(obuf, p);
                        {
                                *nlp = '\0';
                                (void) strcat(obuf, p);
@@ -706,6 +841,7 @@ putheader(fp, m, e)
 **             oldstyle -- TRUE if this is an old style header.
 **             m -- a pointer to the mailer descriptor.  If NULL,
 **                     don't transform the name at all.
 **             oldstyle -- TRUE if this is an old style header.
 **             m -- a pointer to the mailer descriptor.  If NULL,
 **                     don't transform the name at all.
+**             e -- the envelope containing the message.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -714,12 +850,13 @@ putheader(fp, m, e)
 **             outputs "p" to file "fp".
 */
 
 **             outputs "p" to file "fp".
 */
 
-commaize(h, p, fp, oldstyle, m)
+commaize(h, p, fp, oldstyle, m, e)
        register HDR *h;
        register char *p;
        FILE *fp;
        bool oldstyle;
        register MAILER *m;
        register HDR *h;
        register char *p;
        FILE *fp;
        bool oldstyle;
        register MAILER *m;
+       register ENVELOPE *e;
 {
        register char *obp;
        int opos;
 {
        register char *obp;
        int opos;
@@ -735,7 +872,7 @@ commaize(h, p, fp, oldstyle, m)
                printf("commaize(%s: %s)\n", h->h_field, p);
 
        obp = obuf;
                printf("commaize(%s: %s)\n", h->h_field, p);
 
        obp = obuf;
-       (void) sprintf(obp, "%s: ", capitalize(h->h_field));
+       (void) sprintf(obp, "%s: ", h->h_field);
        opos = strlen(h->h_field) + 2;
        obp += opos;
 
        opos = strlen(h->h_field) + 2;
        obp += opos;
 
@@ -746,9 +883,10 @@ commaize(h, p, fp, oldstyle, m)
        while (*p != '\0')
        {
                register char *name;
        while (*p != '\0')
        {
                register char *name;
+               register int c;
                char savechar;
                char savechar;
-               extern char *remotename();
-               extern char *DelimChar;         /* defined in prescan */
+               int flags;
+               auto int stat;
 
                /*
                **  Find the end of the name.  New style names
 
                /*
                **  Find the end of the name.  New style names
@@ -759,37 +897,35 @@ commaize(h, p, fp, oldstyle, m)
                */
 
                /* find end of name */
                */
 
                /* find end of name */
-               while (isspace(*p) || *p == ',')
+               while ((isascii(*p) && isspace(*p)) || *p == ',')
                        p++;
                name = p;
                for (;;)
                {
                        p++;
                name = p;
                for (;;)
                {
-                       char *oldp;
+                       auto char *oldp;
                        char pvpbuf[PSBUFSIZE];
                        char pvpbuf[PSBUFSIZE];
-                       extern bool isatword();
-                       extern char **prescan();
 
 
-                       (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf);
-                       p = DelimChar;
+                       (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf, &oldp);
+                       p = oldp;
 
                        /* look to see if we have an at sign */
 
                        /* look to see if we have an at sign */
-                       oldp = p;
-                       while (*p != '\0' && isspace(*p))
+                       while (*p != '\0' && isascii(*p) && isspace(*p))
                                p++;
 
                                p++;
 
-                       if (*p != '@' && !isatword(p))
+                       if (*p != '@')
                        {
                                p = oldp;
                                break;
                        }
                        p += *p == '@' ? 1 : 2;
                        {
                                p = oldp;
                                break;
                        }
                        p += *p == '@' ? 1 : 2;
-                       while (*p != '\0' && isspace(*p))
+                       while (*p != '\0' && isascii(*p) && isspace(*p))
                                p++;
                }
                /* at the end of one complete name */
 
                /* strip off trailing white space */
                                p++;
                }
                /* at the end of one complete name */
 
                /* strip off trailing white space */
-               while (p >= name && (isspace(*p) || *p == ',' || *p == '\0'))
+               while (p >= name &&
+                      ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
                        p--;
                if (++p == name)
                        continue;
                        p--;
                if (++p == name)
                        continue;
@@ -797,7 +933,11 @@ commaize(h, p, fp, oldstyle, m)
                *p = '\0';
 
                /* translate the name to be relative */
                *p = '\0';
 
                /* translate the name to be relative */
-               name = remotename(name, m, bitset(H_FROM, h->h_flags), FALSE);
+               flags = RF_HEADERADDR|RF_ADDDOMAIN;
+               if (bitset(H_FROM, h->h_flags))
+                       flags |= RF_SENDERADDR;
+               stat = EX_OK;
+               name = remotename(name, m, flags, &stat, e);
                if (*name == '\0')
                {
                        *p = savechar;
                if (*name == '\0')
                {
                        *p = savechar;
@@ -805,7 +945,7 @@ commaize(h, p, fp, oldstyle, m)
                }
 
                /* output the name with nice formatting */
                }
 
                /* output the name with nice formatting */
-               opos += qstrlen(name);
+               opos += strlen(name);
                if (!firstone)
                        opos += 2;
                if (opos > 78 && !firstone)
                if (!firstone)
                        opos += 2;
                if (opos > 78 && !firstone)
@@ -816,7 +956,7 @@ commaize(h, p, fp, oldstyle, m)
                        (void) sprintf(obp, "        ");
                        opos = strlen(obp);
                        obp += opos;
                        (void) sprintf(obp, "        ");
                        opos = strlen(obp);
                        obp += opos;
-                       opos += qstrlen(name);
+                       opos += strlen(name);
                }
                else if (!firstone)
                {
                }
                else if (!firstone)
                {
@@ -824,13 +964,8 @@ commaize(h, p, fp, oldstyle, m)
                        obp += 2;
                }
 
                        obp += 2;
                }
 
-               /* strip off quote bits as we output */
-               while (*name != '\0' && obp < &obuf[MAXLINE])
-               {
-                       if (bitset(0200, *name))
-                               *obp++ = '\\';
-                       *obp++ = *name++ & ~0200;
-               }
+               while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
+                       *obp++ = c;
                firstone = FALSE;
                *p = savechar;
        }
                firstone = FALSE;
                *p = savechar;
        }
@@ -838,27 +973,37 @@ commaize(h, p, fp, oldstyle, m)
        putline(obuf, fp, m);
 }
 \f/*
        putline(obuf, fp, m);
 }
 \f/*
-**  ISATWORD -- tell if the word we are pointing to is "at".
+**  COPYHEADER -- copy header list
+**
+**     This routine is the equivalent of newstr for header lists
 **
 **     Parameters:
 **
 **     Parameters:
-**             p -- word to check.
+**             header -- list of header structures to copy.
 **
 **     Returns:
 **
 **     Returns:
-**             TRUE -- if p is the word at.
-**             FALSE -- otherwise.
+**             a copy of 'header'.
 **
 **     Side Effects:
 **             none.
 */
 
 **
 **     Side Effects:
 **             none.
 */
 
-bool
-isatword(p)
-       register char *p;
+HDR *
+copyheader(header)
+       register HDR *header;
 {
 {
-       extern char lower();
+       register HDR *newhdr;
+       HDR *ret;
+       register HDR **tail = &ret;
 
 
-       if (lower(p[0]) == 'a' && lower(p[1]) == 't' &&
-           p[2] != '\0' && isspace(p[2]))
-               return (TRUE);
-       return (FALSE);
+       while (header != NULL)
+       {
+               newhdr = (HDR *) xalloc(sizeof(HDR));
+               STRUCTCOPY(*header, *newhdr);
+               *tail = newhdr;
+               tail = &newhdr->h_link;
+               header = header->h_link;
+       }
+       *tail = NULL;
+       
+       return ret;
 }
 }
index da35b46..877251d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)macro.c    5.7 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)macro.c    8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -55,6 +55,7 @@ static char sccsid[] = "@(#)macro.c   5.7 (Berkeley) 6/1/90";
 **             none.
 */
 
 **             none.
 */
 
+void
 expand(s, buf, buflim, e)
        register char *s;
        register char *buf;
 expand(s, buf, buflim, e)
        register char *s;
        register char *buf;
@@ -66,8 +67,8 @@ expand(s, buf, buflim, e)
        bool skipping;          /* set if conditionally skipping output */
        bool recurse = FALSE;   /* set if recursion required */
        int i;
        bool skipping;          /* set if conditionally skipping output */
        bool recurse = FALSE;   /* set if recursion required */
        int i;
+       int iflev;              /* if nesting level */
        char xbuf[BUFSIZ];
        char xbuf[BUFSIZ];
-       extern char *macvalue();
 
        if (tTd(35, 24))
        {
 
        if (tTd(35, 24))
        {
@@ -77,6 +78,7 @@ expand(s, buf, buflim, e)
        }
 
        skipping = FALSE;
        }
 
        skipping = FALSE;
+       iflev = 0;
        if (s == NULL)
                s = "";
        for (xp = xbuf; *s != '\0'; s++)
        if (s == NULL)
                s = "";
        for (xp = xbuf; *s != '\0'; s++)
@@ -90,22 +92,29 @@ expand(s, buf, buflim, e)
 
                q = NULL;
                c = *s;
 
                q = NULL;
                c = *s;
-               switch (c)
+               switch (c & 0377)
                {
                  case CONDIF:          /* see if var set */
                        c = *++s;
                {
                  case CONDIF:          /* see if var set */
                        c = *++s;
-                       skipping = macvalue(c, e) == NULL;
+                       if (skipping)
+                               iflev++;
+                       else
+                               skipping = macvalue(c, e) == NULL;
                        continue;
 
                  case CONDELSE:        /* change state of skipping */
                        continue;
 
                  case CONDELSE:        /* change state of skipping */
-                       skipping = !skipping;
+                       if (iflev == 0)
+                               skipping = !skipping;
                        continue;
 
                  case CONDFI:          /* stop skipping */
                        continue;
 
                  case CONDFI:          /* stop skipping */
-                       skipping = FALSE;
+                       if (iflev == 0)
+                               skipping = FALSE;
+                       if (skipping)
+                               iflev--;
                        continue;
 
                        continue;
 
-                 case '\001':          /* macro interpolation */
+                 case MACROEXPAND:     /* macro interpolation */
                        c = *++s;
                        q = macvalue(c & 0177, e);
                        if (q == NULL)
                        c = *++s;
                        q = macvalue(c & 0177, e);
                        if (q == NULL)
@@ -126,7 +135,8 @@ expand(s, buf, buflim, e)
                        /* copy to end of q or max space remaining in buf */
                        while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
                        {
                        /* copy to end of q or max space remaining in buf */
                        while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
                        {
-                               if (iscntrl(c) && !isspace(c))
+                               /* check for any sendmail metacharacters */
+                               if ((c & 0340) == 0200)
                                        recurse = TRUE;
                                *xp++ = c;
                        }
                                        recurse = TRUE;
                                *xp++ = c;
                        }
@@ -188,7 +198,9 @@ expand(s, buf, buflim, e)
 **             $h   to host
 **             $i   queue id
 **             $j   official SMTP hostname, used in messages+
 **             $h   to host
 **             $i   queue id
 **             $j   official SMTP hostname, used in messages+
+**             $k   UUCP node name
 **             $l   UNIX-style from line+
 **             $l   UNIX-style from line+
+**             $m   The domain part of our full name.
 **             $n   name of sendmail ("MAILER-DAEMON" on local
 **                  net typically)+
 **             $o   delimiters ("operators") for address tokens+
 **             $n   name of sendmail ("MAILER-DAEMON" on local
 **                  net typically)+
 **             $o   delimiters ("operators") for address tokens+
@@ -204,6 +216,7 @@ expand(s, buf, buflim, e)
 **             $x   signature (full name) of from person
 **             $y   the tty id of our terminal
 **             $z   home directory of to person
 **             $x   signature (full name) of from person
 **             $y   the tty id of our terminal
 **             $z   home directory of to person
+**             $_   RFC1413 authenticated sender address
 **
 **             Macros marked with + must be defined in the
 **             configuration file and are used internally, but
 **
 **             Macros marked with + must be defined in the
 **             configuration file and are used internally, but
@@ -215,6 +228,7 @@ expand(s, buf, buflim, e)
 **             are available.
 */
 
 **             are available.
 */
 
+void
 define(n, v, e)
        char n;
        char *v;
 define(n, v, e)
        char n;
        char *v;
index a67ff58..0164d91 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,7 +31,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)mailstats.h 5.4 (Berkeley) 6/1/90
+ *     @(#)mailstats.h 8.1 (Berkeley) 6/7/93
  */
 
 /*
  */
 
 /*
index 895a589..5027aeb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1988 Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
      The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     5.32 (Berkeley) 3/2/91";
+static char sccsid[] = "@(#)main.c     8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #define        _DEFINE
 
 #endif /* not lint */
 
 #define        _DEFINE
 
-#include <sys/param.h>
-#include <sys/file.h>
+#include "sendmail.h"
 #include <signal.h>
 #include <sgtty.h>
 #include <signal.h>
 #include <sgtty.h>
-#include "sendmail.h"
+#ifdef NAMED_BIND
 #include <arpa/nameser.h>
 #include <resolv.h>
 #include <arpa/nameser.h>
 #include <resolv.h>
+#endif
+#include <pwd.h>
 
 # ifdef lint
 char   edata, end;
 
 # ifdef lint
 char   edata, end;
@@ -81,6 +82,7 @@ char  edata, end;
 **             Eric Allman, UCB/INGRES (until 10/81)
 **                          Britton-Lee, Inc., purveyors of fine
 **                             database computers (from 11/81)
 **             Eric Allman, UCB/INGRES (until 10/81)
 **                          Britton-Lee, Inc., purveyors of fine
 **                             database computers (from 11/81)
+**                          Now back at UCB at the Mammoth project.
 **             The support of the INGRES Project and Britton-Lee is
 **                     gratefully acknowledged.  Britton-Lee in
 **                     particular had absolutely nothing to gain from
 **             The support of the INGRES Project and Britton-Lee is
 **                     gratefully acknowledged.  Britton-Lee in
 **                     particular had absolutely nothing to gain from
@@ -94,6 +96,9 @@ ENVELOPE      BlankEnvelope;  /* a "blank" envelope */
 ENVELOPE       MainEnvelope;   /* the envelope around the basic letter */
 ADDRESS                NullAddress =   /* a null address */
                { "", "", NULL, "" };
 ENVELOPE       MainEnvelope;   /* the envelope around the basic letter */
 ADDRESS                NullAddress =   /* a null address */
                { "", "", NULL, "" };
+char           *UserEnviron[MAXUSERENVIRON + 1];
+                               /* saved user environment */
+char           RealUserName[256];      /* the actual user id on this host */
 
 /*
 **  Pointers for setproctitle.
 
 /*
 **  Pointers for setproctitle.
@@ -105,13 +110,17 @@ ADDRESS           NullAddress =   /* a null address */
 # ifdef SETPROCTITLE
 char           **Argv = NULL;          /* pointer to argument vector */
 char           *LastArgv = NULL;       /* end of argv */
 # ifdef SETPROCTITLE
 char           **Argv = NULL;          /* pointer to argument vector */
 char           *LastArgv = NULL;       /* end of argv */
-# endif SETPROCTITLE
+# endif /* SETPROCTITLE */
+
+static void    obsolete();
 
 #ifdef DAEMON
 #ifndef SMTP
 ERROR %%%%   Cannot have daemon mode without SMTP   %%%% ERROR
 
 #ifdef DAEMON
 #ifndef SMTP
 ERROR %%%%   Cannot have daemon mode without SMTP   %%%% ERROR
-#endif SMTP
-#endif DAEMON
+#endif /* SMTP */
+#endif /* DAEMON */
+
+#define MAXCONFIGLEVEL 4       /* highest config version level known */
 
 main(argc, argv, envp)
        int argc;
 
 main(argc, argv, envp)
        int argc;
@@ -119,25 +128,33 @@ main(argc, argv, envp)
        char **envp;
 {
        register char *p;
        char **envp;
 {
        register char *p;
+       register char *q;
        char **av;
        extern int finis();
        extern char Version[];
        char **av;
        extern int finis();
        extern char Version[];
-       char *from;
+       char *ep, *from;
        typedef int (*fnptr)();
        STAB *st;
        register int i;
        typedef int (*fnptr)();
        STAB *st;
        register int i;
+       int j;
        bool readconfig = TRUE;
        bool queuemode = FALSE;         /* process queue requests */
        bool nothaw;
        bool readconfig = TRUE;
        bool queuemode = FALSE;         /* process queue requests */
        bool nothaw;
+       bool safecf = TRUE;
        static bool reenter = FALSE;
        static bool reenter = FALSE;
-       char jbuf[30];                  /* holds MyHostName */
-       extern bool safefile();
+       char *argv0 = argv[0];
+       struct passwd *pw;
+       struct stat stb;
+       char jbuf[MAXHOSTNAMELEN];      /* holds MyHostName */
+       extern int DtableSize;
+       extern int optind;
        extern time_t convtime();
        extern putheader(), putbody();
        extern time_t convtime();
        extern putheader(), putbody();
-       extern ENVELOPE *newenvelope();
        extern void intsig();
        extern char **myhostname();
        extern char *arpadate();
        extern void intsig();
        extern char **myhostname();
        extern char *arpadate();
+       extern char *getauthinfo();
+       extern char *optarg;
        extern char **environ;
 
        /*
        extern char **environ;
 
        /*
@@ -153,8 +170,15 @@ main(argc, argv, envp)
        }
        reenter = TRUE;
 
        }
        reenter = TRUE;
 
-       /* Enforce use of local time */
+#ifndef SYS5TZ
+       /* enforce use of kernel-supplied time zone information */
        unsetenv("TZ");
        unsetenv("TZ");
+#endif
+
+       /* in 4.4BSD, the table can be huge; impose a reasonable limit */
+       DtableSize = getdtablesize();
+       if (DtableSize > 256)
+               DtableSize = 256;
 
        /*
        **  Be sure we have enough file descriptors.
 
        /*
        **  Be sure we have enough file descriptors.
@@ -162,10 +186,20 @@ main(argc, argv, envp)
        */
 
        i = open("/dev/null", O_RDWR);
        */
 
        i = open("/dev/null", O_RDWR);
-       while (i >= 0 && i < 2)
-               i = dup(i);
-       for (i = getdtablesize(); i > 2; --i)
-               (void) close(i);
+       if (fstat(STDIN_FILENO, &stb) < 0)
+               (void) dup2(i, STDIN_FILENO);
+       if (fstat(STDOUT_FILENO, &stb) < 0)
+               (void) dup2(i, STDOUT_FILENO);
+       if (fstat(STDERR_FILENO, &stb) < 0)
+               (void) dup2(i, STDERR_FILENO);
+       (void) close(i);
+
+       i = DtableSize;
+       while (--i > 0)
+       {
+               if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO)
+                       (void) close(i);
+       }
        errno = 0;
 
 #ifdef LOG_MAIL
        errno = 0;
 
 #ifdef LOG_MAIL
@@ -174,13 +208,6 @@ main(argc, argv, envp)
        openlog("sendmail", LOG_PID);
 #endif 
 
        openlog("sendmail", LOG_PID);
 #endif 
 
-       /*
-       **  Set default values for variables.
-       **      These cannot be in initialized data space.
-       */
-
-       setdefaults();
-
        /* set up the blank envelope */
        BlankEnvelope.e_puthdr = putheader;
        BlankEnvelope.e_putbody = putbody;
        /* set up the blank envelope */
        BlankEnvelope.e_puthdr = putheader;
        BlankEnvelope.e_putbody = putbody;
@@ -189,6 +216,25 @@ main(argc, argv, envp)
        CurEnv = &BlankEnvelope;
        STRUCTCOPY(NullAddress, MainEnvelope.e_from);
 
        CurEnv = &BlankEnvelope;
        STRUCTCOPY(NullAddress, MainEnvelope.e_from);
 
+       /*
+       **  Set default values for variables.
+       **      These cannot be in initialized data space.
+       */
+
+       setdefaults(&BlankEnvelope);
+
+       RealUid = getuid();
+       RealGid = getgid();
+
+       pw = getpwuid(RealUid);
+       if (pw != NULL)
+               (void) strcpy(RealUserName, pw->pw_name);
+       else
+               (void) sprintf(RealUserName, "Unknown UID %d", RealUid);
+
+       /* Handle any non-getoptable constructions. */
+       obsolete(argv);
+
        /*
        **  Do a quick prescan of the argument list.
        **      We do this to find out if we can potentially thaw the
        /*
        **  Do a quick prescan of the argument list.
        **      We do this to find out if we can potentially thaw the
@@ -196,45 +242,63 @@ main(argc, argv, envp)
        **      the argument processing applies to this run rather than
        **      to the run that froze the configuration.
        */
        **      the argument processing applies to this run rather than
        **      to the run that froze the configuration.
        */
-
-       argv[argc] = NULL;
-       av = argv;
        nothaw = FALSE;
        nothaw = FALSE;
-       while ((p = *++av) != NULL)
+#ifdef __osf__
+#define OPTIONS                "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvx"
+#else
+#define OPTIONS                "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtv"
+#endif
+       while ((j = getopt(argc, argv, OPTIONS)) != EOF)
        {
        {
-               if (strncmp(p, "-C", 2) == 0)
+               switch (j)
                {
                {
-                       ConfFile = &p[2];
-                       if (ConfFile[0] == '\0')
-                               ConfFile = "sendmail.cf";
+                 case 'b':
+                       if (optarg[0] == 'z' && optarg[1] == '\0')
+                               nothaw = TRUE;
+                       break;
+
+                 case 'C':
+                       ConfFile = optarg;
                        (void) setgid(getrgid());
                        (void) setuid(getruid());
                        (void) setgid(getrgid());
                        (void) setuid(getruid());
+                       safecf = FALSE;
                        nothaw = TRUE;
                        nothaw = TRUE;
-               }
-               else if (strncmp(p, "-bz", 3) == 0)
-                       nothaw = TRUE;
-               else if (strncmp(p, "-d", 2) == 0)
-               {
+                       break;
+
+                 case 'd':
                        tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
                        tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
-                       tTflag(&p[2]);
+                       tTflag(optarg);
                        setbuf(stdout, (char *) NULL);
                        printf("Version %s\n", Version);
                        setbuf(stdout, (char *) NULL);
                        printf("Version %s\n", Version);
+                       break;
                }
        }
 
        InChannel = stdin;
        OutChannel = stdout;
 
                }
        }
 
        InChannel = stdin;
        OutChannel = stdout;
 
+# ifdef FROZENCONFIG
        if (!nothaw)
        if (!nothaw)
-               readconfig = !thaw(FreezeFile);
+               readconfig = !thaw(FreezeFile, argv0);
+# else
+       readconfig = TRUE;
+# endif
 
 
-       /* reset the environment after the thaw */
-       for (i = 0; i < MAXUSERENVIRON && envp[i] != NULL; i++)
-               UserEnviron[i] = newstr(envp[i]);
-       UserEnviron[i] = NULL;
+# ifdef SETPROCTITLE
+       /*
+       **  Move the environment so setproctitle can use the space at
+       **  the top of memory.
+       */
+
+       for (i = j = 0; j < MAXUSERENVIRON && (p = envp[i]) != NULL; i++)
+       {
+               if (strncmp(p, "FS=", 3) == 0 || strncmp(p, "LD_", 3) == 0)
+                       continue;
+               UserEnviron[j++] = newstr(p);
+       }
+       UserEnviron[j] = NULL;
        environ = UserEnviron;
 
        environ = UserEnviron;
 
-# ifdef SETPROCTITLE
        /*
        **  Save start and extent of argv for setproctitle.
        */
        /*
        **  Save start and extent of argv for setproctitle.
        */
@@ -244,7 +308,7 @@ main(argc, argv, envp)
                LastArgv = envp[i - 1] + strlen(envp[i - 1]);
        else
                LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
                LastArgv = envp[i - 1] + strlen(envp[i - 1]);
        else
                LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
-# endif SETPROCTITLE
+# endif /* SETPROCTITLE */
 
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                (void) signal(SIGINT, intsig);
 
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                (void) signal(SIGINT, intsig);
@@ -252,11 +316,15 @@ main(argc, argv, envp)
                (void) signal(SIGHUP, intsig);
        (void) signal(SIGTERM, intsig);
        (void) signal(SIGPIPE, SIG_IGN);
                (void) signal(SIGHUP, intsig);
        (void) signal(SIGTERM, intsig);
        (void) signal(SIGPIPE, SIG_IGN);
-       OldUmask = umask(0);
+       OldUmask = umask(022);
        OpMode = MD_DELIVER;
        OpMode = MD_DELIVER;
-       MotherPid = getpid();
        FullName = getenv("NAME");
 
        FullName = getenv("NAME");
 
+#ifdef NAMED_BIND
+       if (tTd(8, 8))
+               _res.options |= RES_DEBUG;
+#endif
+
        errno = 0;
        from = NULL;
 
        errno = 0;
        from = NULL;
 
@@ -265,36 +333,67 @@ main(argc, argv, envp)
                /* initialize some macros, etc. */
                initmacros();
 
                /* initialize some macros, etc. */
                initmacros();
 
-               /* hostname */
-               av = myhostname(jbuf, sizeof jbuf);
-               if (jbuf[0] != '\0')
+               /* version */
+               define('v', Version, CurEnv);
+       }
+
+       /* hostname */
+       av = myhostname(jbuf, sizeof jbuf);
+       if (jbuf[0] != '\0')
+       {
+               struct  utsname utsname;
+
+               if (tTd(0, 4))
+                       printf("canonical name: %s\n", jbuf);
+               p = newstr(jbuf);
+               define('w', p, CurEnv);
+               setclass('w', p);
+
+               q = strchr(jbuf, '.');
+               if (q != NULL)
                {
                {
-                       if (tTd(0, 4))
-                               printf("canonical name: %s\n", jbuf);
+                       *q++ = '\0';
+                       define('m', q, CurEnv);
                        p = newstr(jbuf);
                        p = newstr(jbuf);
-                       define('w', p, CurEnv);
                        setclass('w', p);
                }
                        setclass('w', p);
                }
-               while (av != NULL && *av != NULL)
+
+               if (uname(&utsname) >= 0)
+                       p = utsname.nodename;
+               else
                {
                {
-                       if (tTd(0, 4))
-                               printf("\ta.k.a.: %s\n", *av);
-                       setclass('w', *av++);
+                       makelower(jbuf);
+                       p = jbuf;
                }
                }
-
-               /* version */
-               define('v', Version, CurEnv);
+               if (tTd(0, 4))
+                       printf("UUCP nodename: %s\n", p);
+               p = newstr(p);
+               define('k', p, CurEnv);
+               setclass('w', p);
+       }
+       while (av != NULL && *av != NULL)
+       {
+               if (tTd(0, 4))
+                       printf("\ta.k.a.: %s\n", *av);
+               setclass('w', *av++);
        }
 
        /* current time */
        define('b', arpadate((char *) NULL), CurEnv);
 
        }
 
        /* current time */
        define('b', arpadate((char *) NULL), CurEnv);
 
+       /*
+       **  Find our real host name for future logging.
+       */
+
+       p = getauthinfo(STDIN_FILENO);
+       define('_', p, CurEnv);
+
        /*
        ** Crack argv.
        */
 
        av = argv;
        /*
        ** Crack argv.
        */
 
        av = argv;
-       p = rindex(*av, '/');
+       p = strrchr(*av, '/');
        if (p++ == NULL)
                p = *av;
        if (strcmp(p, "newaliases") == 0)
        if (p++ == NULL)
                p = *av;
        if (strcmp(p, "newaliases") == 0)
@@ -303,12 +402,14 @@ main(argc, argv, envp)
                OpMode = MD_PRINT;
        else if (strcmp(p, "smtpd") == 0)
                OpMode = MD_DAEMON;
                OpMode = MD_PRINT;
        else if (strcmp(p, "smtpd") == 0)
                OpMode = MD_DAEMON;
-       while ((p = *++av) != NULL && p[0] == '-')
+
+       optind = 1;
+       while ((j = getopt(argc, argv, OPTIONS)) != EOF)
        {
        {
-               switch (p[1])
+               switch (j)
                {
                  case 'b':     /* operations mode */
                {
                  case 'b':     /* operations mode */
-                       switch (p[2])
+                       switch (j = *optarg)
                        {
                          case MD_DAEMON:
 # ifdef DAEMON
                        {
                          case MD_DAEMON:
 # ifdef DAEMON
@@ -321,87 +422,82 @@ main(argc, argv, envp)
                                usrerr("Daemon mode not implemented");
                                ExitStat = EX_USAGE;
                                break;
                                usrerr("Daemon mode not implemented");
                                ExitStat = EX_USAGE;
                                break;
-# endif DAEMON
+# endif /* DAEMON */
                          case MD_SMTP:
 # ifndef SMTP
                                usrerr("I don't speak SMTP");
                                ExitStat = EX_USAGE;
                                break;
                          case MD_SMTP:
 # ifndef SMTP
                                usrerr("I don't speak SMTP");
                                ExitStat = EX_USAGE;
                                break;
-# endif SMTP
-                         case MD_ARPAFTP:
+# endif /* SMTP */
                          case MD_DELIVER:
                          case MD_VERIFY:
                          case MD_TEST:
                          case MD_INITALIAS:
                          case MD_PRINT:
                          case MD_DELIVER:
                          case MD_VERIFY:
                          case MD_TEST:
                          case MD_INITALIAS:
                          case MD_PRINT:
+#ifdef FROZENCONFIG
                          case MD_FREEZE:
                          case MD_FREEZE:
-                               OpMode = p[2];
+#endif
+                               OpMode = j;
                                break;
 
                                break;
 
+#ifndef FROZENCONFIG
+                         case MD_FREEZE:
+                               usrerr("Frozen configurations unsupported");
+                               ExitStat = EX_USAGE;
+                               break;
+#endif
+
                          default:
                          default:
-                               usrerr("Invalid operation mode %c", p[2]);
+                               usrerr("Invalid operation mode %c", j);
                                ExitStat = EX_USAGE;
                                break;
                        }
                        break;
 
                                ExitStat = EX_USAGE;
                                break;
                        }
                        break;
 
+                 case 'B':     /* body type */
+                       CurEnv->e_bodytype = newstr(optarg);
+                       break;
+
                  case 'C':     /* select configuration file (already done) */
                  case 'C':     /* select configuration file (already done) */
+                       if (getuid() != 0)
+                               auth_warning(CurEnv,
+                                       "Processed by %s with -C %s",
+                                       RealUserName, optarg);
                        break;
 
                  case 'd':     /* debugging -- redo in case frozen */
                        tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
                        break;
 
                  case 'd':     /* debugging -- redo in case frozen */
                        tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
-                       tTflag(&p[2]);
+                       tTflag(optarg);
                        setbuf(stdout, (char *) NULL);
                        setbuf(stdout, (char *) NULL);
-#ifdef NAMED_BIND
-                       _res.options |= RES_DEBUG;
-#endif
                        break;
 
                  case 'f':     /* from address */
                  case 'r':     /* obsolete -f flag */
                        break;
 
                  case 'f':     /* from address */
                  case 'r':     /* obsolete -f flag */
-                       p += 2;
-                       if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
-                       {
-                               p = *++av;
-                               if (p == NULL || *p == '-')
-                               {
-                                       usrerr("No \"from\" person");
-                                       ExitStat = EX_USAGE;
-                                       av--;
-                                       break;
-                               }
-                       }
                        if (from != NULL)
                        {
                                usrerr("More than one \"from\" person");
                                ExitStat = EX_USAGE;
                                break;
                        }
                        if (from != NULL)
                        {
                                usrerr("More than one \"from\" person");
                                ExitStat = EX_USAGE;
                                break;
                        }
-                       from = newstr(p);
+                       from = newstr(optarg);
+                       if (strcmp(RealUserName, from) != 0)
+                               auth_warning(CurEnv,
+                                       "%s set sender to %s using -%c",
+                                       RealUserName, from, j);
                        break;
 
                  case 'F':     /* set full name */
                        break;
 
                  case 'F':     /* set full name */
-                       p += 2;
-                       if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
-                       {
-                               usrerr("Bad -F flag");
-                               ExitStat = EX_USAGE;
-                               av--;
-                               break;
-                       }
-                       FullName = newstr(p);
+                       FullName = newstr(optarg);
                        break;
 
                  case 'h':     /* hop count */
                        break;
 
                  case 'h':     /* hop count */
-                       p += 2;
-                       if (*p == '\0' && ((p = *++av) == NULL || !isdigit(*p)))
+                       CurEnv->e_hopcount = strtol(optarg, &ep, 10);
+                       if (*ep)
                        {
                        {
-                               usrerr("Bad hop count (%s)", p);
+                               usrerr("Bad hop count (%s)", optarg);
                                ExitStat = EX_USAGE;
                                ExitStat = EX_USAGE;
-                               av--;
                                break;
                        }
                                break;
                        }
-                       CurEnv->e_hopcount = atoi(p);
                        break;
                
                  case 'n':     /* don't alias */
                        break;
                
                  case 'n':     /* don't alias */
@@ -409,22 +505,46 @@ main(argc, argv, envp)
                        break;
 
                  case 'o':     /* set option */
                        break;
 
                  case 'o':     /* set option */
-                       setoption(p[2], &p[3], FALSE, TRUE);
+                       setoption(*optarg, optarg + 1, FALSE, TRUE, CurEnv);
+                       break;
+
+                 case 'p':     /* set protocol */
+                       q = strchr(optarg, ':');
+                       if (q != NULL)
+                               *q++ = '\0';
+                       if (*optarg != '\0')
+                               define('r', newstr(optarg), CurEnv);
+                       if (q != NULL && *q != '\0')
+                               define('s', newstr(q), CurEnv);
                        break;
 
                  case 'q':     /* run queue files at intervals */
 # ifdef QUEUE
                        break;
 
                  case 'q':     /* run queue files at intervals */
 # ifdef QUEUE
-                       if (getuid() != 0) {
-                               usrerr("Permission denied");
-                               exit (EX_USAGE);
-                       }
                        (void) unsetenv("HOSTALIASES");
                        (void) unsetenv("HOSTALIASES");
+                       FullName = NULL;
                        queuemode = TRUE;
                        queuemode = TRUE;
-                       QueueIntvl = convtime(&p[2]);
-# else QUEUE
+                       switch (optarg[0])
+                       {
+                         case 'I':
+                               QueueLimitId = newstr(&optarg[1]);
+                               break;
+
+                         case 'R':
+                               QueueLimitRecipient = newstr(&optarg[1]);
+                               break;
+
+                         case 'S':
+                               QueueLimitSender = newstr(&optarg[1]);
+                               break;
+
+                         default:
+                               QueueIntvl = convtime(optarg, 'm');
+                               break;
+                       }
+# else /* QUEUE */
                        usrerr("I don't know about queues");
                        ExitStat = EX_USAGE;
                        usrerr("I don't know about queues");
                        ExitStat = EX_USAGE;
-# endif QUEUE
+# endif /* QUEUE */
                        break;
 
                  case 't':     /* read recipients from message */
                        break;
 
                  case 't':     /* read recipients from message */
@@ -433,25 +553,39 @@ main(argc, argv, envp)
 
                        /* compatibility flags */
                  case 'c':     /* connect to non-local mailers */
 
                        /* compatibility flags */
                  case 'c':     /* connect to non-local mailers */
-                 case 'e':     /* error message disposition */
                  case 'i':     /* don't let dot stop me */
                  case 'm':     /* send to me too */
                  case 'T':     /* set timeout interval */
                  case 'v':     /* give blow-by-blow description */
                  case 'i':     /* don't let dot stop me */
                  case 'm':     /* send to me too */
                  case 'T':     /* set timeout interval */
                  case 'v':     /* give blow-by-blow description */
-                       setoption(p[1], &p[2], FALSE, TRUE);
+                       setoption(j, "T", FALSE, TRUE, CurEnv);
+                       break;
+
+                 case 'e':     /* error message disposition */
+                       setoption(j, optarg, FALSE, TRUE, CurEnv);
                        break;
 
                  case 's':     /* save From lines in headers */
                        break;
 
                  case 's':     /* save From lines in headers */
-                       setoption('f', &p[2], FALSE, TRUE);
+                       setoption('f', "T", FALSE, TRUE, CurEnv);
                        break;
 
 # ifdef DBM
                  case 'I':     /* initialize alias DBM file */
                        OpMode = MD_INITALIAS;
                        break;
                        break;
 
 # ifdef DBM
                  case 'I':     /* initialize alias DBM file */
                        OpMode = MD_INITALIAS;
                        break;
-# endif DBM
+# endif /* DBM */
+
+# ifdef __osf__
+                 case 'x':     /* random flag that DEC OSF/1 mailx passes */
+                       break;
+# endif
+
+                 default:
+                       ExitStat = EX_USAGE;
+                       finis();
+                       break;
                }
        }
                }
        }
+       av += optind;
 
        /*
        **  Do basic initialization.
 
        /*
        **  Do basic initialization.
@@ -460,10 +594,46 @@ main(argc, argv, envp)
        */
 
        if (OpMode == MD_FREEZE || readconfig)
        */
 
        if (OpMode == MD_FREEZE || readconfig)
-               readcf(ConfFile);
+               readcf(ConfFile, safecf, CurEnv);
+
+#ifdef SYS5TZ
+       /* Enforce use of local time (null string overrides this) */
+       if (TimeZoneSpec == NULL)
+               unsetenv("TZ");
+       else if (TimeZoneSpec[0] != '\0')
+       {
+               p = xalloc(strlen(TimeZoneSpec) + 4);
+               (void) strcpy(p, "TZ=");
+               (void) strcat(p, TimeZoneSpec);
+               putenv(p);
+       }
+#endif
+
+       if (ConfigLevel > MAXCONFIGLEVEL)
+       {
+               syserr("Warning: .cf version level (%d) exceeds program functionality (%d)",
+                       ConfigLevel, MAXCONFIGLEVEL);
+       }
+# ifdef QUEUE
+       if (queuemode && getuid() != 0)
+       {
+               struct stat stbuf;
+
+               /* check to see if we own the queue directory */
+               if (stat(QueueDir, &stbuf) < 0)
+                       syserr("main: cannot stat %s", QueueDir);
+               if (stbuf.st_uid != getuid())
+               {
+                       /* nope, really a botch */
+                       usrerr("Permission denied");
+                       exit (EX_NOPERM);
+               }
+       }
+# endif /* QUEUE */
 
        switch (OpMode)
        {
 
        switch (OpMode)
        {
+# ifdef FROZENCONFIG
          case MD_FREEZE:
                /* this is critical to avoid forgeries of the frozen config */
                (void) setgid(getgid());
          case MD_FREEZE:
                /* this is critical to avoid forgeries of the frozen config */
                (void) setgid(getgid());
@@ -472,38 +642,65 @@ main(argc, argv, envp)
                /* freeze the configuration */
                freeze(FreezeFile);
                exit(EX_OK);
                /* freeze the configuration */
                freeze(FreezeFile);
                exit(EX_OK);
+# endif
 
          case MD_INITALIAS:
                Verbose = TRUE;
                break;
 
          case MD_INITALIAS:
                Verbose = TRUE;
                break;
+
+         case MD_DAEMON:
+               /* remove things that don't make sense in daemon mode */
+               FullName = NULL;
+               break;
+
+         case MD_SMTP:
+               if (RealUid != 0)
+                       auth_warning(CurEnv,
+                               "%s owned process doing -bs",
+                               RealUserName);
+               break;
        }
 
        /* do heuristic mode adjustment */
        if (Verbose)
        {
                /* turn off noconnect option */
        }
 
        /* do heuristic mode adjustment */
        if (Verbose)
        {
                /* turn off noconnect option */
-               setoption('c', "F", TRUE, FALSE);
+               setoption('c', "F", TRUE, FALSE, CurEnv);
 
                /* turn on interactive delivery */
 
                /* turn on interactive delivery */
-               setoption('d', "", TRUE, FALSE);
+               setoption('d', "", TRUE, FALSE, CurEnv);
        }
 
        /* our name for SMTP codes */
        }
 
        /* our name for SMTP codes */
-       expand("\001j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv);
+       expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv);
        MyHostName = jbuf;
 
        MyHostName = jbuf;
 
-       /* the indices of local and program mailers */
+       /* the indices of built-in mailers */
        st = stab("local", ST_MAILER, ST_FIND);
        if (st == NULL)
                syserr("No local mailer defined");
        else
                LocalMailer = st->s_mailer;
        st = stab("local", ST_MAILER, ST_FIND);
        if (st == NULL)
                syserr("No local mailer defined");
        else
                LocalMailer = st->s_mailer;
+
        st = stab("prog", ST_MAILER, ST_FIND);
        if (st == NULL)
                syserr("No prog mailer defined");
        else
                ProgMailer = st->s_mailer;
 
        st = stab("prog", ST_MAILER, ST_FIND);
        if (st == NULL)
                syserr("No prog mailer defined");
        else
                ProgMailer = st->s_mailer;
 
+       st = stab("*file*", ST_MAILER, ST_FIND);
+       if (st == NULL)
+               syserr("No *file* mailer defined");
+       else
+               FileMailer = st->s_mailer;
+
+       st = stab("*include*", ST_MAILER, ST_FIND);
+       if (st == NULL)
+               syserr("No *include* mailer defined");
+       else
+               InclMailer = st->s_mailer;
+
+
        /* operate in queue directory */
        if (chdir(QueueDir) < 0)
        {
        /* operate in queue directory */
        if (chdir(QueueDir) < 0)
        {
@@ -511,6 +708,10 @@ main(argc, argv, envp)
                exit(EX_SOFTWARE);
        }
 
                exit(EX_SOFTWARE);
        }
 
+       /* if we've had errors so far, exit now */
+       if (ExitStat != EX_OK)
+               exit(ExitStat);
+
        /*
        **  Do operation-mode-dependent initialization.
        */
        /*
        **  Do operation-mode-dependent initialization.
        */
@@ -523,14 +724,14 @@ main(argc, argv, envp)
                dropenvelope(CurEnv);
                printqueue();
                exit(EX_OK);
                dropenvelope(CurEnv);
                printqueue();
                exit(EX_OK);
-#else QUEUE
+#else /* QUEUE */
                usrerr("No queue to print");
                finis();
                usrerr("No queue to print");
                finis();
-#endif QUEUE
+#endif /* QUEUE */
 
          case MD_INITALIAS:
                /* initialize alias database */
 
          case MD_INITALIAS:
                /* initialize alias database */
-               initaliases(AliasFile, TRUE);
+               initmaps(TRUE, CurEnv);
                exit(EX_OK);
 
          case MD_DAEMON:
                exit(EX_OK);
 
          case MD_DAEMON:
@@ -539,7 +740,7 @@ main(argc, argv, envp)
 
          default:
                /* open the alias database */
 
          default:
                /* open the alias database */
-               initaliases(AliasFile, FALSE);
+               initmaps(FALSE, CurEnv);
                break;
        }
 
                break;
        }
 
@@ -554,14 +755,26 @@ main(argc, argv, envp)
 
                        if (m == NULL)
                                continue;
 
                        if (m == NULL)
                                continue;
-                       printf("mailer %d (%s): P=%s S=%d R=%d M=%ld F=", i, m->m_name,
-                               m->m_mailer, m->m_s_rwset, m->m_r_rwset,
-                               m->m_maxsize);
+                       printf("mailer %d (%s): P=%s S=%d/%d R=%d/%d M=%ld F=", i, m->m_name,
+                               m->m_mailer, m->m_se_rwset, m->m_sh_rwset,
+                               m->m_re_rwset, m->m_rh_rwset, m->m_maxsize);
                        for (j = '\0'; j <= '\177'; j++)
                                if (bitnset(j, m->m_flags))
                                        (void) putchar(j);
                        printf(" E=");
                        xputs(m->m_eol);
                        for (j = '\0'; j <= '\177'; j++)
                                if (bitnset(j, m->m_flags))
                                        (void) putchar(j);
                        printf(" E=");
                        xputs(m->m_eol);
+                       if (m->m_argv != NULL)
+                       {
+                               char **a = m->m_argv;
+
+                               printf(" A=");
+                               while (*a != NULL)
+                               {
+                                       if (a != m->m_argv)
+                                               printf(" ");
+                                       xputs(*a++);
+                               }
+                       }
                        printf("\n");
                }
        }
                        printf("\n");
                }
        }
@@ -570,7 +783,7 @@ main(argc, argv, envp)
        **  Switch to the main envelope.
        */
 
        **  Switch to the main envelope.
        */
 
-       CurEnv = newenvelope(&MainEnvelope);
+       CurEnv = newenvelope(&MainEnvelope, CurEnv);
        MainEnvelope.e_flags = BlankEnvelope.e_flags;
 
        /*
        MainEnvelope.e_flags = BlankEnvelope.e_flags;
 
        /*
@@ -581,42 +794,63 @@ main(argc, argv, envp)
        {
                char buf[MAXLINE];
 
        {
                char buf[MAXLINE];
 
-               printf("ADDRESS TEST MODE\nEnter <ruleset> <address>\n");
+               if (isatty(fileno(stdin)))
+                       Verbose = TRUE;
+
+               if (Verbose)
+               {
+                       printf("ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n");
+                       printf("Enter <ruleset> <address>\n");
+               }
                for (;;)
                {
                        register char **pvp;
                        char *q;
                for (;;)
                {
                        register char **pvp;
                        char *q;
-                       extern char *DelimChar;
+                       auto char *delimptr;
+                       extern bool invalidaddr();
 
 
-                       printf("> ");
+                       if (Verbose)
+                               printf("> ");
                        (void) fflush(stdout);
                        if (fgets(buf, sizeof buf, stdin) == NULL)
                                finis();
                        (void) fflush(stdout);
                        if (fgets(buf, sizeof buf, stdin) == NULL)
                                finis();
-                       for (p = buf; isspace(*p); p++)
+                       if (!Verbose)
+                               printf("> %s", buf);
+                       if (buf[0] == '#')
+                               continue;
+                       for (p = buf; isascii(*p) && isspace(*p); p++)
                                continue;
                        q = p;
                                continue;
                        q = p;
-                       while (*p != '\0' && !isspace(*p))
+                       while (*p != '\0' && !(isascii(*p) && isspace(*p)))
                                p++;
                        if (*p == '\0')
                                p++;
                        if (*p == '\0')
+                       {
+                               printf("No address!\n");
                                continue;
                                continue;
+                       }
                        *p = '\0';
                        *p = '\0';
+                       if (invalidaddr(p + 1))
+                               continue;
                        do
                        {
                        do
                        {
-                               extern char **prescan();
                                char pvpbuf[PSBUFSIZE];
 
                                char pvpbuf[PSBUFSIZE];
 
-                               pvp = prescan(++p, ',', pvpbuf);
+                               pvp = prescan(++p, ',', pvpbuf, &delimptr);
                                if (pvp == NULL)
                                        continue;
                                if (pvp == NULL)
                                        continue;
-                               rewrite(pvp, 3);
                                p = q;
                                while (*p != '\0')
                                {
                                p = q;
                                while (*p != '\0')
                                {
-                                       rewrite(pvp, atoi(p));
+                                       int stat;
+
+                                       stat = rewrite(pvp, atoi(p), CurEnv);
+                                       if (stat != EX_OK)
+                                               printf("== Ruleset %s status %d\n",
+                                                       p, stat);
                                        while (*p != '\0' && *p++ != ',')
                                                continue;
                                }
                                        while (*p != '\0' && *p++ != ',')
                                                continue;
                                }
-                       } while (*(p = DelimChar) != '\0');
+                       } while (*(p = delimptr) != '\0');
                }
        }
 
                }
        }
 
@@ -630,7 +864,7 @@ main(argc, argv, envp)
                runqueue(FALSE);
                finis();
        }
                runqueue(FALSE);
                finis();
        }
-# endif QUEUE
+# endif /* QUEUE */
 
        /*
        **  If a daemon, wait for a request.
 
        /*
        **  If a daemon, wait for a request.
@@ -643,6 +877,8 @@ main(argc, argv, envp)
 
        if (OpMode == MD_DAEMON || QueueIntvl != 0)
        {
 
        if (OpMode == MD_DAEMON || QueueIntvl != 0)
        {
+               char dtype[200];
+
                if (!tTd(0, 1))
                {
                        /* put us in background */
                if (!tTd(0, 1))
                {
                        /* put us in background */
@@ -652,13 +888,26 @@ main(argc, argv, envp)
                        if (i != 0)
                                exit(0);
 
                        if (i != 0)
                                exit(0);
 
-                       /* get our pid right */
-                       MotherPid = getpid();
-
                        /* disconnect from our controlling tty */
                        /* disconnect from our controlling tty */
-                       disconnect(TRUE);
+                       disconnect(TRUE, CurEnv);
                }
 
                }
 
+               dtype[0] = '\0';
+               if (OpMode == MD_DAEMON)
+                       strcat(dtype, "+SMTP");
+               if (QueueIntvl != 0)
+               {
+                       strcat(dtype, "+queueing@");
+                       strcat(dtype, pintvl(QueueIntvl, TRUE));
+               }
+               if (tTd(0, 1))
+                       strcat(dtype, "+debugging");
+
+               syslog(LOG_INFO, "starting daemon (%s): %s", Version, dtype + 1);
+#ifdef XLA
+               xla_create_file();
+#endif
+
 # ifdef QUEUE
                if (queuemode)
                {
 # ifdef QUEUE
                if (queuemode)
                {
@@ -667,17 +916,23 @@ main(argc, argv, envp)
                                for (;;)
                                        pause();
                }
                                for (;;)
                                        pause();
                }
-# endif QUEUE
+# endif /* QUEUE */
                dropenvelope(CurEnv);
 
 #ifdef DAEMON
                getrequests();
 
                /* at this point we are in a child: reset state */
                dropenvelope(CurEnv);
 
 #ifdef DAEMON
                getrequests();
 
                /* at this point we are in a child: reset state */
-               OpMode = MD_SMTP;
-               (void) newenvelope(CurEnv);
-               openxscript(CurEnv);
-#endif DAEMON
+               (void) newenvelope(CurEnv, CurEnv);
+
+               /*
+               **  Get authentication data
+               */
+
+               p = getauthinfo(fileno(InChannel));
+               define('_', p, CurEnv);
+
+#endif /* DAEMON */
        }
        
 # ifdef SMTP
        }
        
 # ifdef SMTP
@@ -687,33 +942,47 @@ main(argc, argv, envp)
        */
 
        if (OpMode == MD_SMTP)
        */
 
        if (OpMode == MD_SMTP)
-               smtp();
-# endif SMTP
+               smtp(CurEnv);
+# endif /* SMTP */
 
        /*
        **  Do basic system initialization and set the sender
        */
 
 
        /*
        **  Do basic system initialization and set the sender
        */
 
-       initsys();
-       setsender(from);
+       /* make sendmail immune from process group signals */
+# ifdef _POSIX_JOB_CONTROL
+       (void) setpgid(0, getpid());
+# else
+# ifndef SYSTEM5
+       (void) setpgrp(0, getpid());
+# endif
+# endif
+
+       initsys(CurEnv);
+       setsender(from, CurEnv, NULL, FALSE);
+       if (macvalue('s', CurEnv) == NULL)
+               define('s', RealHostName, CurEnv);
 
 
-       if (OpMode != MD_ARPAFTP && *av == NULL && !GrabTo)
+       if (*av == NULL && !GrabTo)
        {
                usrerr("Recipient names must be specified");
 
                /* collect body for UUCP return */
                if (OpMode != MD_VERIFY)
        {
                usrerr("Recipient names must be specified");
 
                /* collect body for UUCP return */
                if (OpMode != MD_VERIFY)
-                       collect(FALSE);
+                       collect(FALSE, FALSE, CurEnv);
                finis();
        }
        if (OpMode == MD_VERIFY)
                finis();
        }
        if (OpMode == MD_VERIFY)
-               SendMode = SM_VERIFY;
+       {
+               CurEnv->e_sendmode = SM_VERIFY;
+               CurEnv->e_errormode = EM_QUIET;
+       }
 
        /*
        **  Scan argv and deliver the message to everyone.
        */
 
 
        /*
        **  Scan argv and deliver the message to everyone.
        */
 
-       sendtoargv(av);
+       sendtoargv(av, CurEnv);
 
        /* if we have had errors sofar, arrange a meaningful exit stat */
        if (Errors > 0 && ExitStat == EX_OK)
 
        /* if we have had errors sofar, arrange a meaningful exit stat */
        if (Errors > 0 && ExitStat == EX_OK)
@@ -725,7 +994,7 @@ main(argc, argv, envp)
 
        CurEnv->e_to = NULL;
        if (OpMode != MD_VERIFY || GrabTo)
 
        CurEnv->e_to = NULL;
        if (OpMode != MD_VERIFY || GrabTo)
-               collect(FALSE);
+               collect(FALSE, FALSE, CurEnv);
        errno = 0;
 
        /* collect statistics */
        errno = 0;
 
        /* collect statistics */
@@ -741,11 +1010,17 @@ main(argc, argv, envp)
        */
 
        CurEnv->e_from.q_flags |= QDONTSEND;
        */
 
        CurEnv->e_from.q_flags |= QDONTSEND;
+       if (tTd(1, 5))
+       {
+               printf("main: QDONTSEND ");
+               printaddr(&CurEnv->e_from, FALSE);
+       }
        CurEnv->e_to = NULL;
        sendall(CurEnv, SM_DEFAULT);
 
        /*
        CurEnv->e_to = NULL;
        sendall(CurEnv, SM_DEFAULT);
 
        /*
-       ** All done.
+       **  All done.
+       **      Don't send return error message if in VERIFY mode.
        */
 
        finis();
        */
 
        finis();
@@ -772,14 +1047,22 @@ finis()
        CurEnv->e_to = NULL;
        dropenvelope(CurEnv);
 
        CurEnv->e_to = NULL;
        dropenvelope(CurEnv);
 
+       /* flush any cached connections */
+       mci_flush(TRUE, NULL);
+
        /* post statistics */
        poststats(StatFile);
 
        /* post statistics */
        poststats(StatFile);
 
+# ifdef XLA
+       /* clean up extended load average stuff */
+       xla_all_end();
+# endif
+
        /* and exit */
 # ifdef LOG
        /* and exit */
 # ifdef LOG
-       if (LogLevel > 11)
+       if (LogLevel > 78)
                syslog(LOG_DEBUG, "finis, pid=%d", getpid());
                syslog(LOG_DEBUG, "finis, pid=%d", getpid());
-# endif LOG
+# endif /* LOG */
        if (ExitStat == EX_TEMPFAIL)
                ExitStat = EX_OK;
        exit(ExitStat);
        if (ExitStat == EX_TEMPFAIL)
                ExitStat = EX_OK;
        exit(ExitStat);
@@ -805,6 +1088,9 @@ intsig()
 {
        FileName = NULL;
        unlockqueue(CurEnv);
 {
        FileName = NULL;
        unlockqueue(CurEnv);
+#ifdef XLA
+       xla_all_end();
+#endif
        exit(EX_OK);
 }
 \f/*
        exit(EX_OK);
 }
 \f/*
@@ -823,26 +1109,25 @@ intsig()
 **             initializes several macros to be themselves.
 */
 
 **             initializes several macros to be themselves.
 */
 
-struct metamac
-{
-       char    metaname;
-       char    metaval;
-};
-
 struct metamac MetaMacros[] =
 {
        /* LHS pattern matching characters */
 struct metamac MetaMacros[] =
 {
        /* LHS pattern matching characters */
-       '*', MATCHZANY, '+', MATCHANY,  '-', MATCHONE,  '=', MATCHCLASS,
-       '~', MATCHNCLASS,
+       '*', MATCHZANY,         '+', MATCHANY,          '-', MATCHONE,
+       '=', MATCHCLASS,        '~', MATCHNCLASS,
 
        /* these are RHS metasymbols */
 
        /* these are RHS metasymbols */
-       '#', CANONNET,  '@', CANONHOST, ':', CANONUSER, '>', CALLSUBR,
+       '#', CANONNET,          '@', CANONHOST,         ':', CANONUSER,
+       '>', CALLSUBR,
 
        /* the conditional operations */
 
        /* the conditional operations */
-       '?', CONDIF,    '|', CONDELSE,  '.', CONDFI,
+       '?', CONDIF,            '|', CONDELSE,          '.', CONDFI,
+
+       /* the hostname lookup characters */
+       '[', HOSTBEGIN,         ']', HOSTEND,
+       '(', LOOKUPBEGIN,       ')', LOOKUPEND,
 
 
-       /* and finally the hostname lookup characters */
-       '[', HOSTBEGIN, ']', HOSTEND,
+       /* miscellaneous control characters */
+       '&', MACRODEXPAND,
 
        '\0'
 };
 
        '\0'
 };
@@ -882,6 +1167,8 @@ initmacros()
 **             Writes BSS and malloc'ed memory to freezefile
 */
 
 **             Writes BSS and malloc'ed memory to freezefile
 */
 
+# ifdef FROZENCONFIG
+
 union frz
 {
        char            frzpad[BUFSIZ]; /* insure we are on a BUFSIZ boundary */
 union frz
 {
        char            frzpad[BUFSIZ]; /* insure we are on a BUFSIZ boundary */
@@ -895,13 +1182,21 @@ union frz
        } frzinfo;
 };
 
        } frzinfo;
 };
 
+#if defined(__hpux) || defined(__alpha)
+#define BRK_TYPE        int
+#define SBRK_TYPE       void *
+#else
+#define BRK_TYPE        char *
+#define SBRK_TYPE       char *
+#endif
+
 freeze(freezefile)
        char *freezefile;
 {
        int f;
        union frz fhdr;
 freeze(freezefile)
        char *freezefile;
 {
        int f;
        union frz fhdr;
+       extern SBRK_TYPE sbrk();
        extern char edata, end;
        extern char edata, end;
-       extern char *sbrk();
        extern char Version[];
 
        if (freezefile == NULL)
        extern char Version[];
 
        if (freezefile == NULL)
@@ -939,6 +1234,7 @@ freeze(freezefile)
 **
 **     Parameters:
 **             freezefile -- the name of the file to thaw from.
 **
 **     Parameters:
 **             freezefile -- the name of the file to thaw from.
+**             binfile -- the name of the sendmail binary (ok to guess).
 **
 **     Returns:
 **             TRUE if it successfully read the freeze file.
 **
 **     Returns:
 **             TRUE if it successfully read the freeze file.
@@ -948,14 +1244,19 @@ freeze(freezefile)
 **             reads freezefile in to BSS area.
 */
 
 **             reads freezefile in to BSS area.
 */
 
-thaw(freezefile)
+thaw(freezefile, binfile)
        char *freezefile;
        char *freezefile;
+       char *binfile;
 {
        int f;
 {
        int f;
+       register char *p;
        union frz fhdr;
        union frz fhdr;
+       char hbuf[60];
+       struct stat fst, sst;
        extern char edata, end;
        extern char Version[];
        extern char edata, end;
        extern char Version[];
-       extern caddr_t brk();
+       extern char **myhostname();
+       extern BRK_TYPE brk();
 
        if (freezefile == NULL)
                return (FALSE);
 
        if (freezefile == NULL)
                return (FALSE);
@@ -964,30 +1265,45 @@ thaw(freezefile)
        f = open(freezefile, 0);
        if (f < 0)
        {
        f = open(freezefile, 0);
        if (f < 0)
        {
-               syslog(LOG_WARNING, "Cannot open frozen config file %s: %m",
-                       freezefile);
                errno = 0;
                return (FALSE);
        }
 
                errno = 0;
                return (FALSE);
        }
 
+       if (fstat(f, &fst) < 0 || stat(ConfFile, &sst) < 0 ||
+           fst.st_mtime < sst.st_mtime)
+       {
+               syslog(LOG_WARNING, "Freeze file older than config file");
+               (void) close(f);
+               return (FALSE);
+       }
+
+       if (strchr(binfile, '/') != NULL && stat(binfile, &sst) == 0 &&
+           fst.st_mtime < sst.st_mtime)
+       {
+               syslog(LOG_WARNING, "Freeze file older than binary file");
+               (void) close(f);
+               return (FALSE);
+       }
+
        /* read in the header */
        if (read(f, (char *) &fhdr, sizeof fhdr) < sizeof fhdr)
        {
        /* read in the header */
        if (read(f, (char *) &fhdr, sizeof fhdr) < sizeof fhdr)
        {
-               syserr("Cannot read frozen config file");
+               syslog(LOG_WARNING, "Cannot read frozen config file");
                (void) close(f);
                return (FALSE);
        }
                (void) close(f);
                return (FALSE);
        }
-       if ( fhdr.frzinfo.frzedata != &edata ||
+       if (fhdr.frzinfo.frzedata != &edata ||
            fhdr.frzinfo.frzend != &end ||
            strcmp(fhdr.frzinfo.frzver, Version) != 0)
        {
            fhdr.frzinfo.frzend != &end ||
            strcmp(fhdr.frzinfo.frzver, Version) != 0)
        {
+               fprintf(stderr, "Wrong version of frozen config file\n");
                syslog(LOG_WARNING, "Wrong version of frozen config file");
                (void) close(f);
                return (FALSE);
        }
 
        /* arrange to have enough space */
                syslog(LOG_WARNING, "Wrong version of frozen config file");
                (void) close(f);
                return (FALSE);
        }
 
        /* arrange to have enough space */
-       if (brk(fhdr.frzinfo.frzbrk) == (caddr_t) -1)
+       if (brk(fhdr.frzinfo.frzbrk) == (BRK_TYPE) -1)
        {
                syserr("Cannot break to %x", fhdr.frzinfo.frzbrk);
                (void) close(f);
        {
                syserr("Cannot break to %x", fhdr.frzinfo.frzbrk);
                (void) close(f);
@@ -1005,8 +1321,20 @@ thaw(freezefile)
        }
 
        (void) close(f);
        }
 
        (void) close(f);
-       return (TRUE);
+
+       /* verify that the host name was correct on the freeze */
+       (void) myhostname(hbuf, sizeof hbuf);
+       p = macvalue('w', CurEnv);
+       if (p == NULL)
+               p = "";
+       if (strcmp(hbuf, macvalue('w', CurEnv)) == 0)
+               return (TRUE);
+       syslog(LOG_WARNING, "Hostname changed since freeze (%s => %s)",
+               p, hbuf);
+       return (FALSE);
 }
 }
+
+# endif /* FROZENCONFIG */
 \f/*
 **  DISCONNECT -- remove our connection with any foreground process
 **
 \f/*
 **  DISCONNECT -- remove our connection with any foreground process
 **
@@ -1025,14 +1353,15 @@ thaw(freezefile)
 **             the controlling tty.
 */
 
 **             the controlling tty.
 */
 
-disconnect(fulldrop)
+disconnect(fulldrop, e)
        bool fulldrop;
        bool fulldrop;
+       register ENVELOPE *e;
 {
        int fd;
 
        if (tTd(52, 1))
 {
        int fd;
 
        if (tTd(52, 1))
-               printf("disconnect: In %d Out %d\n", fileno(InChannel),
-                                               fileno(OutChannel));
+               printf("disconnect: In %d Out %d, e=%x\n",
+                       fileno(InChannel), fileno(OutChannel), e);
        if (tTd(52, 5))
        {
                printf("don't\n");
        if (tTd(52, 5))
        {
                printf("don't\n");
@@ -1046,7 +1375,7 @@ disconnect(fulldrop)
 
        /* we can't communicate with our caller, so.... */
        HoldErrs = TRUE;
 
        /* we can't communicate with our caller, so.... */
        HoldErrs = TRUE;
-       ErrorMode = EM_MAIL;
+       CurEnv->e_errormode = EM_MAIL;
        Verbose = FALSE;
 
        /* all input from /dev/null */
        Verbose = FALSE;
 
        /* all input from /dev/null */
@@ -1063,20 +1392,20 @@ disconnect(fulldrop)
                (void) fclose(OutChannel);
                OutChannel = stdout;
        }
                (void) fclose(OutChannel);
                OutChannel = stdout;
        }
-       if (CurEnv->e_xfp == NULL)
-               CurEnv->e_xfp = fopen("/dev/null", "w");
+       if (e->e_xfp == NULL)
+               fd = open("/dev/null", O_WRONLY, 0666);
+       else
+               fd = fileno(e->e_xfp);
        (void) fflush(stdout);
        (void) fflush(stdout);
-       (void) close(1);
-       (void) close(2);
-       while ((fd = dup(fileno(CurEnv->e_xfp))) < 2 && fd > 0)
-               continue;
+       dup2(fd, STDOUT_FILENO);
+       dup2(fd, STDERR_FILENO);
+       if (e->e_xfp == NULL)
+               close(fd);
 
        /* drop our controlling TTY completely if possible */
        if (fulldrop)
        {
 
        /* drop our controlling TTY completely if possible */
        if (fulldrop)
        {
-#if BSD > 43
-               daemon(1, 1);
-#else
+               (void) setsid();
 #ifdef TIOCNOTTY
                fd = open("/dev/tty", 2);
                if (fd >= 0)
 #ifdef TIOCNOTTY
                fd = open("/dev/tty", 2);
                if (fd >= 0)
@@ -1086,14 +1415,90 @@ disconnect(fulldrop)
                }
                (void) setpgrp(0, 0);
 #endif /* TIOCNOTTY */
                }
                (void) setpgrp(0, 0);
 #endif /* TIOCNOTTY */
-#endif /* BSD */
                errno = 0;
        }
 
 # ifdef LOG
                errno = 0;
        }
 
 # ifdef LOG
-       if (LogLevel > 11)
+       if (LogLevel > 71)
                syslog(LOG_DEBUG, "in background, pid=%d", getpid());
                syslog(LOG_DEBUG, "in background, pid=%d", getpid());
-# endif LOG
+# endif /* LOG */
 
        errno = 0;
 }
 
        errno = 0;
 }
+
+static void
+obsolete(argv)
+       char *argv[];
+{
+       char *ap;
+
+       while ((ap = *++argv) != NULL)
+       {
+               /* Return if "--" or not an option of any form. */
+               if (ap[0] != '-' || ap[1] == '-')
+                       return;
+
+               /* If -C doesn't have an argument, use sendmail.cf. */
+#define        __DEFPATH       "sendmail.cf"
+               if (ap[1] == 'C' && ap[2] == '\0' &&
+                   (argv[1] == NULL || argv[1][0] == '-'))
+               {
+                       *argv = xalloc(sizeof(__DEFPATH) + 2);
+                       argv[0][0] = '-';
+                       argv[0][1] = 'C';
+                       (void)strcpy(&argv[0][2], __DEFPATH);
+               }
+
+               /* If -q doesn't have an argument, run it once. */
+               if (ap[1] == 'q' && ap[2] == '\0' &&
+                   (argv[1] == NULL || argv[1][0] == '-'))
+                       *argv = "-q0";
+
+               /* if -d doesn't have an argument, use 0-99.1 */
+               if (ap[1] == 'd' && ap[2] == '\0' &&
+                   (argv[1] == NULL || !isdigit(argv[1][0])))
+                       *argv = "-d0-99.1";
+       }
+}
+\f/*
+**  AUTH_WARNING -- specify authorization warning
+**
+**     Parameters:
+**             e -- the current envelope.
+**             msg -- the text of the message.
+**             args -- arguments to the message.
+**
+**     Returns:
+**             none.
+*/
+
+void
+#ifdef __STDC__
+auth_warning(register ENVELOPE *e, const char *msg, ...)
+#else
+auth_warning(e, msg, va_alist)
+       register ENVELOPE *e;
+       const char *msg;
+       va_dcl
+#endif
+{
+       char buf[MAXLINE];
+       VA_LOCAL_DECL
+
+       if (bitset(PRIV_AUTHWARNINGS, PrivacyFlags))
+       {
+               register char *p;
+               static char hostbuf[48];
+               extern char **myhostname();
+
+               if (hostbuf[0] == '\0')
+                       (void) myhostname(hostbuf, sizeof hostbuf);
+
+               (void) sprintf(buf, "%s: ", hostbuf);
+               p = &buf[strlen(buf)];
+               VA_START(msg);
+               vsprintf(p, msg, ap);
+               VA_END;
+               addheader("X-Authentication-Warning", buf, e);
+       }
+}
diff --git a/usr.sbin/sendmail/src/map.c b/usr.sbin/sendmail/src/map.c
new file mode 100644 (file)
index 0000000..ef53f23
--- /dev/null
@@ -0,0 +1,1149 @@
+/*
+ * Copyright (c) 1992 Eric P. Allman.
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)map.c      8.1 (Berkeley) 6/7/93";
+#endif /* not lint */
+
+#include "sendmail.h"
+
+#ifdef NDBM
+#include <ndbm.h>
+#endif
+#ifdef NEWDB
+#include <db.h>
+#endif
+#ifdef NIS
+#include <rpcsvc/ypclnt.h>
+#endif
+
+/*
+**  MAP.C -- implementations for various map classes.
+**
+**     Each map class implements a series of functions:
+**
+**     bool map_parse(MAP *map, char *args)
+**             Parse the arguments from the config file.  Return TRUE
+**             if they were ok, FALSE otherwise.  Fill in map with the
+**             values.
+**
+**     char *map_lookup(MAP *map, char *key, char **args, int *pstat)
+**             Look up the key in the given map.  If found, do any
+**             rewriting the map wants (including "args" if desired)
+**             and return the value.  Set *pstat to the appropriate status
+**             on error and return NULL.  Args will be NULL if called
+**             from the alias routines, although this should probably
+**             not be relied upon.  It is suggested you call map_rewrite
+**             to return the results -- it takes care of null termination
+**             and uses a dynamically expanded buffer as needed.
+**
+**     void map_store(MAP *map, char *key, char *value)
+**             Store the key:value pair in the map.
+**
+**     bool map_open(MAP *map, int mode)
+**             Open the map for the indicated mode.  Mode should
+**             be either O_RDONLY or O_RDWR.  Return TRUE if it
+**             was opened successfully, FALSE otherwise.  If the open
+**             failed an the MF_OPTIONAL flag is not set, it should
+**             also print an error.  If the MF_ALIAS bit is set
+**             and this map class understands the @:@ convention, it
+**             should call aliaswait() before returning.
+**
+**     void map_close(MAP *map)
+**             Close the map.
+*/
+
+#define DBMMODE                0644
+\f/*
+**  MAP_PARSEARGS -- parse config line arguments for database lookup
+**
+**     This is a generic version of the map_parse method.
+**
+**     Parameters:
+**             map -- the map being initialized.
+**             ap -- a pointer to the args on the config line.
+**
+**     Returns:
+**             TRUE -- if everything parsed OK.
+**             FALSE -- otherwise.
+**
+**     Side Effects:
+**             null terminates the filename; stores it in map
+*/
+
+bool
+map_parseargs(map, ap)
+       MAP *map;
+       char *ap;
+{
+       register char *p = ap;
+
+       for (;;)
+       {
+               while (isascii(*p) && isspace(*p))
+                       p++;
+               if (*p != '-')
+                       break;
+               switch (*++p)
+               {
+                 case 'N':
+                       map->map_mflags |= MF_INCLNULL;
+                       break;
+
+                 case 'o':
+                       map->map_mflags |= MF_OPTIONAL;
+                       break;
+
+                 case 'f':
+                       map->map_mflags |= MF_NOFOLDCASE;
+                       break;
+
+                 case 'm':
+                       map->map_mflags |= MF_MATCHONLY;
+                       break;
+
+                 case 'a':
+                       map->map_app = ++p;
+                       break;
+               }
+               while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+                       p++;
+               if (*p != '\0')
+                       *p++ = '\0';
+       }
+       if (map->map_app != NULL)
+               map->map_app = newstr(map->map_app);
+
+       if (*p != '\0')
+       {
+               map->map_file = p;
+               while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+                       p++;
+               if (*p != '\0')
+                       *p++ = '\0';
+               map->map_file = newstr(map->map_file);
+       }
+
+       while (*p != '\0' && isascii(*p) && isspace(*p))
+               p++;
+       if (*p != '\0')
+               map->map_rebuild = newstr(p);
+
+       if (map->map_file == NULL)
+       {
+               syserr("No file name for %s map %s",
+                       map->map_class->map_cname, map->map_mname);
+               return FALSE;
+       }
+       return TRUE;
+}
+\f/*
+**  MAP_REWRITE -- rewrite a database key, interpolating %n indications.
+**
+**     It also adds the map_app string.  It can be used as a utility
+**     in the map_lookup method.
+**
+**     Parameters:
+**             map -- the map that causes this.
+**             s -- the string to rewrite, NOT necessarily null terminated.
+**             slen -- the length of s.
+**             av -- arguments to interpolate into buf.
+**
+**     Returns:
+**             Pointer to rewritten result.
+**
+**     Side Effects:
+**             none.
+*/
+
+struct rwbuf
+{
+       int     rwb_len;        /* size of buffer */
+       char    *rwb_buf;       /* ptr to buffer */
+};
+
+struct rwbuf   RwBufs[2];      /* buffers for rewriting output */
+
+char *
+map_rewrite(map, s, slen, av)
+       register MAP *map;
+       register char *s;
+       int slen;
+       char **av;
+{
+       register char *bp;
+       register char c;
+       char **avp;
+       register char *ap;
+       register struct rwbuf *rwb;
+       int i;
+       int len;
+
+       if (tTd(39, 1))
+       {
+               printf("map_rewrite(%.*s), av =", slen, s);
+               if (av == NULL)
+                       printf(" (nullv)");
+               else
+               {
+                       for (avp = av; *avp != NULL; avp++)
+                               printf("\n\t%s", *avp);
+               }
+               printf("\n");
+       }
+
+       rwb = RwBufs;
+       if (av == NULL)
+               rwb++;
+
+       /* count expected size of output (can safely overestimate) */
+       i = len = slen;
+       if (av != NULL)
+       {
+               bp = s;
+               for (i = slen; --i >= 0 && (c = *bp++) != 0; )
+               {
+                       if (c != '%')
+                               continue;
+                       if (--i < 0)
+                               break;
+                       c = *bp++;
+                       if (!(isascii(c) && isdigit(c)))
+                               continue;
+                       c -= 0;
+                       for (avp = av; --c >= 0 && *avp != NULL; avp++)
+                               continue;
+                       if (*avp == NULL)
+                               continue;
+                       len += strlen(*avp);
+               }
+       }
+       if (map->map_app != NULL)
+               len += strlen(map->map_app);
+       if (rwb->rwb_len < ++len)
+       {
+               /* need to malloc additional space */
+               rwb->rwb_len = len;
+               if (rwb->rwb_buf != NULL)
+                       free(rwb->rwb_buf);
+               rwb->rwb_buf = xalloc(rwb->rwb_len);
+       }
+
+       bp = rwb->rwb_buf;
+       if (av == NULL)
+       {
+               bcopy(s, bp, slen);
+               bp += slen;
+       }
+       else
+       {
+               while (--slen >= 0 && (c = *s++) != '\0')
+               {
+                       if (c != '%')
+                       {
+  pushc:
+                               *bp++ = c;
+                               continue;
+                       }
+                       if (--slen < 0 || (c = *s++) == '\0')
+                               c = '%';
+                       if (c == '%')
+                               goto pushc;
+                       if (!(isascii(c) && isdigit(c)))
+                       {
+                               *bp++ = '%';
+                               goto pushc;
+                       }
+                       c -= '0';
+                       for (avp = av; --c >= 0 && *avp != NULL; avp++)
+                               continue;
+                       if (*avp == NULL)
+                               continue;
+
+                       /* transliterate argument into output string */
+                       for (ap = *avp; (c = *ap++) != '\0'; )
+                               *bp++ = c;
+               }
+       }
+       if (map->map_app != NULL)
+               strcpy(bp, map->map_app);
+       else
+               *bp = '\0';
+       if (tTd(39, 1))
+               printf("map_rewrite => %s\n", rwb->rwb_buf);
+       return rwb->rwb_buf;
+}
+\f/*
+**  INITMAPS -- initialize for aliasing
+**
+**     Parameters:
+**             rebuild -- if TRUE, this rebuilds the cached versions.
+**             e -- current envelope.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             initializes aliases:
+**             if NDBM:  opens the database.
+**             if ~NDBM: reads the aliases into the symbol table.
+*/
+
+initmaps(rebuild, e)
+       bool rebuild;
+       register ENVELOPE *e;
+{
+       extern void map_init();
+
+       CurEnv = e;
+       stabapply(map_init, rebuild);
+}
+
+void
+map_init(s, rebuild)
+       register STAB *s;
+       int rebuild;
+{
+       register MAP *map;
+
+       /* has to be a map */
+       if (s->s_type != ST_MAP)
+               return;
+
+       map = &s->s_map;
+       if (!bitset(MF_VALID, map->map_mflags))
+               return;
+
+       if (tTd(38, 2))
+               printf("map_init(%s:%s)\n",
+                       map->map_class->map_cname, map->map_file);
+
+       /* if already open, close it (for nested open) */
+       if (bitset(MF_OPEN, map->map_mflags))
+       {
+               map->map_class->map_close(map);
+               map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
+       }
+
+       if (rebuild)
+       {
+               if (bitset(MF_ALIAS, map->map_mflags) &&
+                   bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
+                       rebuildaliases(map, FALSE);
+       }
+       else
+       {
+               if (map->map_class->map_open(map, O_RDONLY))
+               {
+                       if (tTd(38, 4))
+                               printf("%s:%s: valid\n",
+                                       map->map_class->map_cname,
+                                       map->map_file);
+                       map->map_mflags |= MF_OPEN;
+               }
+               else if (tTd(38, 4))
+                       printf("%s:%s: invalid: %s\n",
+                               map->map_class->map_cname,
+                               map->map_file,
+                               errstring(errno));
+       }
+}
+\f/*
+**  NDBM modules
+*/
+
+#ifdef NDBM
+
+/*
+**  DBM_MAP_OPEN -- DBM-style map open
+*/
+
+bool
+ndbm_map_open(map, mode)
+       MAP *map;
+       int mode;
+{
+       DBM *dbm;
+
+       if (tTd(38, 2))
+               printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
+
+       if (mode == O_RDWR)
+               mode |= O_CREAT|O_TRUNC;
+
+       /* open the database */
+       dbm = dbm_open(map->map_file, mode, DBMMODE);
+       if (dbm == NULL)
+       {
+               if (!bitset(MF_OPTIONAL, map->map_mflags))
+                       syserr("Cannot open DBM database %s", map->map_file);
+               return FALSE;
+       }
+       map->map_db1 = (void *) dbm;
+       if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
+               aliaswait(map, ".pag");
+       return TRUE;
+}
+
+
+/*
+**  DBM_MAP_LOOKUP -- look up a datum in a DBM-type map
+*/
+
+char *
+ndbm_map_lookup(map, name, av, statp)
+       MAP *map;
+       char *name;
+       char **av;
+       int *statp;
+{
+       datum key, val;
+       char keybuf[MAXNAME + 1];
+
+       if (tTd(38, 20))
+               printf("ndbm_map_lookup(%s)\n", name);
+
+       key.dptr = name;
+       key.dsize = strlen(name);
+       if (!bitset(MF_NOFOLDCASE, map->map_mflags))
+       {
+               if (key.dsize > sizeof keybuf - 1)
+                       key.dsize = sizeof keybuf - 1;
+               bcopy(key.dptr, keybuf, key.dsize + 1);
+               makelower(keybuf);
+               key.dptr = keybuf;
+       }
+       if (bitset(MF_INCLNULL, map->map_mflags))
+               key.dsize++;
+       (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
+       val = dbm_fetch((DBM *) map->map_db1, key);
+       (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
+       if (val.dptr == NULL)
+               return NULL;
+       if (bitset(MF_MATCHONLY, map->map_mflags))
+               av = NULL;
+       return map_rewrite(map, val.dptr, val.dsize, av);
+}
+
+
+/*
+**  DBM_MAP_STORE -- store a datum in the database
+*/
+
+void
+ndbm_map_store(map, lhs, rhs)
+       register MAP *map;
+       char *lhs;
+       char *rhs;
+{
+       datum key;
+       datum data;
+       int stat;
+
+       if (tTd(38, 12))
+               printf("ndbm_map_store(%s, %s)\n", lhs, rhs);
+
+       key.dsize = strlen(lhs);
+       key.dptr = lhs;
+
+       data.dsize = strlen(rhs);
+       data.dptr = rhs;
+
+       if (bitset(MF_INCLNULL, map->map_mflags))
+       {
+               key.dsize++;
+               data.dsize++;
+       }
+
+       stat = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT);
+       if (stat > 0)
+       {
+               usrerr("050 Warning: duplicate alias name %s", lhs);
+               stat = dbm_store((DBM *) map->map_db1, key, data, DBM_REPLACE);
+       }
+       if (stat != 0)
+               syserr("readaliases: dbm put (%s)", lhs);
+}
+
+
+/*
+**  NDBM_MAP_CLOSE -- close the database
+*/
+
+void
+ndbm_map_close(map)
+       register MAP  *map;
+{
+       if (bitset(MF_WRITABLE, map->map_mflags))
+       {
+#ifdef YPCOMPAT
+               char buf[200];
+
+               (void) sprintf(buf, "%010ld", curtime());
+               ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
+
+               (void) myhostname(buf, sizeof buf);
+               ndbm_map_store(map, "YP_MASTER_NAME", buf);
+#endif
+
+               /* write out the distinguished alias */
+               ndbm_map_store(map, "@", "@");
+       }
+       dbm_close((DBM *) map->map_db1);
+}
+
+#endif
+\f/*
+**  NEWDB (Hash and BTree) Modules
+*/
+
+#ifdef NEWDB
+
+/*
+**  BT_MAP_OPEN, HASH_MAP_OPEN -- database open primitives.
+**
+**     These do rather bizarre locking.  If you can lock on open,
+**     do that to avoid the condition of opening a database that
+**     is being rebuilt.  If you don't, we'll try to fake it, but
+**     there will be a race condition.  If opening for read-only,
+**     we immediately release the lock to avoid freezing things up.
+**     We really ought to hold the lock, but guarantee that we won't
+**     be pokey about it.  That's hard to do.
+*/
+
+bool
+bt_map_open(map, mode)
+       MAP *map;
+       int mode;
+{
+       DB *db;
+       int i;
+       int omode;
+       char buf[MAXNAME];
+
+       if (tTd(38, 2))
+               printf("bt_map_open(%s, %d)\n", map->map_file, mode);
+
+       omode = mode;
+       if (omode == O_RDWR)
+       {
+               omode |= O_CREAT|O_TRUNC;
+#if defined(O_EXLOCK) && !defined(LOCKF)
+               omode |= O_EXLOCK;
+# if !defined(OLD_NEWDB)
+       }
+       else
+       {
+               omode |= O_SHLOCK;
+# endif
+#endif
+       }
+
+       (void) strcpy(buf, map->map_file);
+       i = strlen(buf);
+       if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
+               (void) strcat(buf, ".db");
+       db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
+       if (db == NULL)
+       {
+               if (!bitset(MF_OPTIONAL, map->map_mflags))
+                       syserr("Cannot open BTREE database %s", map->map_file);
+               return FALSE;
+       }
+#if !defined(OLD_NEWDB) && !defined(LOCKF)
+# if !defined(O_EXLOCK)
+       if (mode == O_RDWR)
+               (void) lockfile(db->fd(db), map->map_file, LOCK_EX);
+# else
+       if (mode == O_RDONLY)
+               (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
+# endif
+#endif
+
+       /* try to make sure that at least the database header is on disk */
+       if (mode == O_RDWR)
+               (void) db->sync(db, 0);
+
+       map->map_db2 = (void *) db;
+       if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
+               aliaswait(map, ".db");
+       return TRUE;
+}
+
+
+/*
+**  HASH_MAP_INIT -- HASH-style map initialization
+*/
+
+bool
+hash_map_open(map, mode)
+       MAP *map;
+       int mode;
+{
+       DB *db;
+       int i;
+       int omode;
+       char buf[MAXNAME];
+
+       if (tTd(38, 2))
+               printf("hash_map_open(%s, %d)\n", map->map_file, mode);
+
+       omode = mode;
+       if (omode == O_RDWR)
+       {
+               omode |= O_CREAT|O_TRUNC;
+#if defined(O_EXLOCK) && !defined(LOCKF)
+               omode |= O_EXLOCK;
+# if !defined(OLD_NEWDB)
+       }
+       else
+       {
+               omode |= O_SHLOCK;
+# endif
+#endif
+       }
+
+       (void) strcpy(buf, map->map_file);
+       i = strlen(buf);
+       if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
+               (void) strcat(buf, ".db");
+       db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
+       if (db == NULL)
+       {
+               if (!bitset(MF_OPTIONAL, map->map_mflags))
+                       syserr("Cannot open HASH database %s", map->map_file);
+               return FALSE;
+       }
+#if !defined(OLD_NEWDB) && !defined(LOCKF)
+# if !defined(O_EXLOCK)
+       if (mode == O_RDWR)
+               (void) lockfile(db->fd(db), map->map_file, LOCK_EX);
+# else
+       if (mode == O_RDONLY)
+               (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
+# endif
+#endif
+
+       /* try to make sure that at least the database header is on disk */
+       if (mode == O_RDWR)
+               (void) db->sync(db, 0);
+
+       map->map_db2 = (void *) db;
+       if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
+               aliaswait(map, ".db");
+       return TRUE;
+}
+
+
+/*
+**  DB_MAP_LOOKUP -- look up a datum in a BTREE- or HASH-type map
+*/
+
+char *
+db_map_lookup(map, name, av, statp)
+       MAP *map;
+       char *name;
+       char **av;
+       int *statp;
+{
+       DBT key, val;
+       register DB *db = (DB *) map->map_db2;
+       int st;
+       int saveerrno;
+       char keybuf[MAXNAME + 1];
+
+       if (tTd(38, 20))
+               printf("db_map_lookup(%s)\n", name);
+
+       key.size = strlen(name);
+       if (key.size > sizeof keybuf - 1)
+               key.size = sizeof keybuf - 1;
+       key.data = keybuf;
+       bcopy(name, keybuf, key.size + 1);
+       if (!bitset(MF_NOFOLDCASE, map->map_mflags))
+               makelower(keybuf);
+       if (bitset(MF_INCLNULL, map->map_mflags))
+               key.size++;
+#ifndef OLD_NEWDB
+       (void) lockfile(db->fd(db), map->map_file, LOCK_SH);
+#endif
+       st = db->get(db, &key, &val, 0);
+       saveerrno = errno;
+#ifndef OLD_NEWDB
+       (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
+#endif
+       if (st != 0)
+       {
+               errno = saveerrno;
+               if (st < 0)
+                       syserr("db_map_lookup: get (%s)", name);
+               return NULL;
+       }
+       if (bitset(MF_MATCHONLY, map->map_mflags))
+               av = NULL;
+       return map_rewrite(map, val.data, val.size, av);
+}
+
+
+/*
+**  DB_MAP_STORE -- store a datum in the NEWDB database
+*/
+
+void
+db_map_store(map, lhs, rhs)
+       register MAP *map;
+       char *lhs;
+       char *rhs;
+{
+       int stat;
+       DBT key;
+       DBT data;
+       register DB *db = map->map_db2;
+
+       if (tTd(38, 20))
+               printf("db_map_store(%s, %s)\n", lhs, rhs);
+
+       key.size = strlen(lhs);
+       key.data = lhs;
+
+       data.size = strlen(rhs);
+       data.data = rhs;
+
+       if (bitset(MF_INCLNULL, map->map_mflags))
+       {
+               key.size++;
+               data.size++;
+       }
+
+       stat = db->put(db, &key, &data, R_NOOVERWRITE);
+       if (stat > 0)
+       {
+               usrerr("050 Warning: duplicate alias name %s", lhs);
+               stat = db->put(db, &key, &data, 0);
+       }
+       if (stat != 0)
+               syserr("readaliases: db put (%s)", lhs);
+}
+
+
+/*
+**  DB_MAP_CLOSE -- add distinguished entries and close the database
+*/
+
+void
+db_map_close(map)
+       MAP *map;
+{
+       register DB *db = map->map_db2;
+
+       if (tTd(38, 9))
+               printf("db_map_close(%s, %x)\n", map->map_file, map->map_mflags);
+
+       if (bitset(MF_WRITABLE, map->map_mflags))
+       {
+               /* write out the distinguished alias */
+               db_map_store(map, "@", "@");
+       }
+
+       if (db->close(db) != 0)
+               syserr("readaliases: db close failure");
+}
+
+#endif
+\f/*
+**  NIS Modules
+*/
+
+# ifdef NIS
+
+/*
+**  NIS_MAP_OPEN -- open DBM map
+*/
+
+bool
+nis_map_open(map, mode)
+       MAP *map;
+       int mode;
+{
+       int yperr;
+       register char *p;
+       auto char *vp;
+       auto int vsize;
+       char *master;
+
+       if (tTd(38, 2))
+               printf("nis_map_open(%s)\n", map->map_file);
+
+       if (mode != O_RDONLY)
+       {
+               errno = ENODEV;
+               return FALSE;
+       }
+
+       p = strchr(map->map_file, '@');
+       if (p != NULL)
+       {
+               *p++ = '\0';
+               if (*p != '\0')
+                       map->map_domain = p;
+       }
+
+       if (map->map_domain == NULL)
+               yp_get_default_domain(&map->map_domain);
+
+       if (*map->map_file == '\0')
+               map->map_file = "mail.aliases";
+
+       /* check to see if this map actually exists */
+       yperr = yp_match(map->map_domain, map->map_file, "@", 1,
+                       &vp, &vsize);
+       if (tTd(38, 10))
+               printf("nis_map_open: yp_match(%s, %s) => %s\n",
+                       map->map_domain, map->map_file, yperr_string(yperr));
+       if (yperr == 0 || yperr == YPERR_KEY || yperr == YPERR_BUSY)
+               return TRUE;
+
+       if (!bitset(MF_OPTIONAL, map->map_mflags))
+               syserr("Cannot bind to domain %s: %s", map->map_domain,
+                       yperr_string(yperr));
+
+       return FALSE;
+}
+
+
+/*
+**  NIS_MAP_LOOKUP -- look up a datum in a NIS map
+*/
+
+char *
+nis_map_lookup(map, name, av, statp)
+       MAP *map;
+       char *name;
+       char **av;
+       int *statp;
+{
+       char *vp;
+       auto int vsize;
+       int buflen;
+       int yperr;
+       char keybuf[MAXNAME + 1];
+
+       if (tTd(38, 20))
+               printf("nis_map_lookup(%s)\n", name);
+
+       buflen = strlen(name);
+       if (buflen > sizeof keybuf - 1)
+               buflen = sizeof keybuf - 1;
+       bcopy(name, keybuf, buflen + 1);
+       if (!bitset(MF_NOFOLDCASE, map->map_mflags))
+               makelower(keybuf);
+       if (bitset(MF_INCLNULL, map->map_mflags))
+               buflen++;
+       yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
+                    &vp, &vsize);
+       if (yperr != 0)
+       {
+               if (yperr != YPERR_KEY && yperr != YPERR_BUSY)
+                       map->map_mflags &= ~(MF_VALID|MF_OPEN);
+               return NULL;
+       }
+       if (bitset(MF_MATCHONLY, map->map_mflags))
+               av = NULL;
+       return map_rewrite(map, vp, vsize, av);
+}
+
+
+/*
+**  NIS_MAP_STORE
+*/
+
+void
+nis_map_store(map, lhs, rhs)
+       MAP *map;
+       char *lhs;
+       char *rhs;
+{
+       /* nothing */
+}
+
+
+/*
+**  NIS_MAP_CLOSE
+*/
+
+void
+nis_map_close(map)
+       MAP *map;
+{
+       /* nothing */
+}
+
+#endif /* NIS */
+\f/*
+**  STAB (Symbol Table) Modules
+*/
+
+
+/*
+**  STAB_MAP_LOOKUP -- look up alias in symbol table
+*/
+
+char *
+stab_map_lookup(map, name, av, pstat)
+       register MAP *map;
+       char *name;
+       char **av;
+       int *pstat;
+{
+       register STAB *s;
+
+       if (tTd(38, 20))
+               printf("stab_lookup(%s)\n", name);
+
+       s = stab(name, ST_ALIAS, ST_FIND);
+       if (s != NULL)
+               return (s->s_alias);
+       return (NULL);
+}
+
+
+/*
+**  STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
+*/
+
+void
+stab_map_store(map, lhs, rhs)
+       register MAP *map;
+       char *lhs;
+       char *rhs;
+{
+       register STAB *s;
+
+       s = stab(lhs, ST_ALIAS, ST_ENTER);
+       s->s_alias = newstr(rhs);
+}
+
+
+/*
+**  STAB_MAP_OPEN -- initialize (reads data file)
+**
+**     This is a wierd case -- it is only intended as a fallback for
+**     aliases.  For this reason, opens for write (only during a
+**     "newaliases") always fails, and opens for read open the
+**     actual underlying text file instead of the database.
+*/
+
+bool
+stab_map_open(map, mode)
+       register MAP *map;
+       int mode;
+{
+       if (tTd(38, 2))
+               printf("stab_map_open(%s)\n", map->map_file);
+
+       if (mode != O_RDONLY)
+       {
+               errno = ENODEV;
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+
+/*
+**  STAB_MAP_CLOSE -- close symbol table (???)
+*/
+
+void
+stab_map_close(map)
+       MAP *map;
+{
+       /* ignore it */
+}
+\f/*
+**  Implicit Modules
+**
+**     Tries several types.  For back compatibility of aliases.
+*/
+
+
+/*
+**  IMPL_MAP_LOOKUP -- lookup in best open database
+*/
+
+char *
+impl_map_lookup(map, name, av, pstat)
+       MAP *map;
+       char *name;
+       char **av;
+       int *pstat;
+{
+       if (tTd(38, 20))
+               printf("impl_map_lookup(%s)\n", name);
+
+#ifdef NEWDB
+       if (bitset(MF_IMPL_HASH, map->map_mflags))
+               return db_map_lookup(map, name, av, pstat);
+#endif
+#ifdef NDBM
+       if (bitset(MF_IMPL_NDBM, map->map_mflags))
+               return ndbm_map_lookup(map, name, av, pstat);
+#endif
+       return stab_map_lookup(map, name, av, pstat);
+}
+
+/*
+**  IMPL_MAP_STORE -- store in open databases
+*/
+
+void
+impl_map_store(map, lhs, rhs)
+       MAP *map;
+       char *lhs;
+       char *rhs;
+{
+#ifdef NEWDB
+       if (bitset(MF_IMPL_HASH, map->map_mflags))
+               db_map_store(map, lhs, rhs);
+#endif
+#ifdef NDBM
+       if (bitset(MF_IMPL_NDBM, map->map_mflags))
+               ndbm_map_store(map, lhs, rhs);
+#endif
+       stab_map_store(map, lhs, rhs);
+}
+
+/*
+**  IMPL_MAP_OPEN -- implicit database open
+*/
+
+bool
+impl_map_open(map, mode)
+       MAP *map;
+       int mode;
+{
+       struct stat stb;
+
+       if (tTd(38, 2))
+               printf("impl_map_open(%s)\n", map->map_file);
+
+       if (stat(map->map_file, &stb) < 0)
+       {
+               /* no alias file at all */
+               return FALSE;
+       }
+
+#ifdef NEWDB
+       map->map_mflags |= MF_IMPL_HASH;
+       if (hash_map_open(map, mode))
+       {
+#if defined(NDBM) && defined(YPCOMPAT)
+               if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
+#endif
+                       return TRUE;
+       }
+       else
+               map->map_mflags &= ~MF_IMPL_HASH;
+#endif
+#ifdef NDBM
+       map->map_mflags |= MF_IMPL_NDBM;
+       if (ndbm_map_open(map, mode))
+       {
+               return TRUE;
+       }
+       else
+               map->map_mflags &= ~MF_IMPL_NDBM;
+#endif
+
+#if !defined(NEWDB) && !defined(NDBM)
+       if (Verbose)
+               message("WARNING: cannot open alias database %s", map->map_file);
+#endif
+
+       return stab_map_open(map, mode);
+}
+
+
+/*
+**  IMPL_MAP_CLOSE -- close any open database(s)
+*/
+
+void
+impl_map_close(map)
+       MAP *map;
+{
+#ifdef NEWDB
+       if (bitset(MF_IMPL_HASH, map->map_mflags))
+       {
+               db_map_close(map);
+               map->map_mflags &= ~MF_IMPL_HASH;
+       }
+#endif
+
+#ifdef NDBM
+       if (bitset(MF_IMPL_NDBM, map->map_mflags))
+       {
+               ndbm_map_close(map);
+               map->map_mflags &= ~MF_IMPL_NDBM;
+       }
+#endif
+}
+\f/*
+**  NULL stubs
+*/
+
+bool
+null_map_open(map, mode)
+       MAP *map;
+       int mode;
+{
+       return TRUE;
+}
+
+void
+null_map_close(map)
+       MAP *map;
+{
+       return;
+}
+
+void
+null_map_store(map, key, val)
+       MAP *map;
+       char *key;
+       char *val;
+{
+       return;
+}
diff --git a/usr.sbin/sendmail/src/mci.c b/usr.sbin/sendmail/src/mci.c
new file mode 100644 (file)
index 0000000..7b4eb0f
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 1983 Eric P. Allman
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)mci.c      8.1 (Berkeley) 6/7/93";
+#endif /* not lint */
+
+#include "sendmail.h"
+
+/*
+**  Mail Connection Information (MCI) Caching Module.
+**
+**     There are actually two separate things cached.  The first is
+**     the set of all open connections -- these are stored in a
+**     (small) list.  The second is stored in the symbol table; it
+**     has the overall status for all hosts, whether or not there
+**     is a connection open currently.
+**
+**     There should never be too many connections open (since this
+**     could flood the socket table), nor should a connection be
+**     allowed to sit idly for too long.
+**
+**     MaxMciCache is the maximum number of open connections that
+**     will be supported.
+**
+**     MciCacheTimeout is the time (in seconds) that a connection
+**     is permitted to survive without activity.
+**
+**     We actually try any cached connections by sending a NOOP
+**     before we use them; if the NOOP fails we close down the
+**     connection and reopen it.  Note that this means that a
+**     server SMTP that doesn't support NOOP will hose the
+**     algorithm -- but that doesn't seem too likely.
+*/
+
+MCI    **MciCache;             /* the open connection cache */
+\f/*
+**  MCI_CACHE -- enter a connection structure into the open connection cache
+**
+**     This may cause something else to be flushed.
+**
+**     Parameters:
+**             mci -- the connection to cache.
+**
+**     Returns:
+**             none.
+*/
+
+mci_cache(mci)
+       register MCI *mci;
+{
+       register MCI **mcislot;
+       extern MCI **mci_scan();
+
+       if (MaxMciCache <= 0)
+       {
+               /* we don't support caching */
+               return;
+       }
+
+       /*
+       **  Find the best slot.  This may cause expired connections
+       **  to be closed.
+       */
+
+       mcislot = mci_scan(mci);
+
+       /* if this is already cached, we are done */
+       if (bitset(MCIF_CACHED, mci->mci_flags))
+               return;
+
+       /* otherwise we may have to clear the slot */
+       if (*mcislot != NULL)
+               mci_uncache(mcislot, TRUE);
+
+       *mcislot = mci;
+       mci->mci_flags |= MCIF_CACHED;
+}
+\f/*
+**  MCI_SCAN -- scan the cache, flush junk, and return best slot
+**
+**     Parameters:
+**             savemci -- never flush this one.  Can be null.
+**
+**     Returns:
+**             The LRU (or empty) slot.
+*/
+
+MCI **
+mci_scan(savemci)
+       MCI *savemci;
+{
+       time_t now;
+       register MCI **bestmci;
+       register MCI *mci;
+       register int i;
+
+       if (MciCache == NULL)
+       {
+               /* first call */
+               MciCache = (MCI **) xalloc(MaxMciCache * sizeof *MciCache);
+               bzero((char *) MciCache, MaxMciCache * sizeof *MciCache);
+               return (&MciCache[0]);
+       }
+
+       now = curtime();
+       bestmci = &MciCache[0];
+       for (i = 0; i < MaxMciCache; i++)
+       {
+               mci = MciCache[i];
+               if (mci == NULL || mci->mci_state == MCIS_CLOSED)
+               {
+                       bestmci = &MciCache[i];
+                       continue;
+               }
+               if (mci->mci_lastuse + MciCacheTimeout < now && mci != savemci)
+               {
+                       /* connection idle too long -- close it */
+                       bestmci = &MciCache[i];
+                       mci_uncache(bestmci, TRUE);
+                       continue;
+               }
+               if (*bestmci == NULL)
+                       continue;
+               if (mci->mci_lastuse < (*bestmci)->mci_lastuse)
+                       bestmci = &MciCache[i];
+       }
+       return bestmci;
+}
+\f/*
+**  MCI_UNCACHE -- remove a connection from a slot.
+**
+**     May close a connection.
+**
+**     Parameters:
+**             mcislot -- the slot to empty.
+**             doquit -- if TRUE, send QUIT protocol on this connection.
+**                       if FALSE, we are assumed to be in a forked child;
+**                             all we want to do is close the file(s).
+**
+**     Returns:
+**             none.
+*/
+
+mci_uncache(mcislot, doquit)
+       register MCI **mcislot;
+       bool doquit;
+{
+       register MCI *mci;
+       extern ENVELOPE BlankEnvelope;
+
+       mci = *mcislot;
+       if (mci == NULL)
+               return;
+       *mcislot = NULL;
+
+       if (doquit)
+       {
+               message("Closing connection to %s", mci->mci_host);
+
+               mci->mci_flags &= ~MCIF_CACHED;
+
+               /* only uses the envelope to flush the transcript file */
+               if (mci->mci_state != MCIS_CLOSED)
+                       smtpquit(mci->mci_mailer, mci, &BlankEnvelope);
+#ifdef XLA
+               xla_host_end(mci->mci_host);
+#endif
+       }
+       else
+       {
+               if (mci->mci_in != NULL)
+                       xfclose(mci->mci_in, "mci_uncache", "mci_in");
+               if (mci->mci_out != NULL)
+                       xfclose(mci->mci_out, "mci_uncache", "mci_out");
+               mci->mci_in = mci->mci_out = NULL;
+               mci->mci_state = MCIS_CLOSED;
+               mci->mci_exitstat = EX_OK;
+               mci->mci_errno = 0;
+               mci->mci_flags = 0;
+       }
+}
+\f/*
+**  MCI_FLUSH -- flush the entire cache
+**
+**     Parameters:
+**             doquit -- if TRUE, send QUIT protocol.
+**                       if FALSE, just close the connection.
+**             allbut -- but leave this one open.
+**
+**     Returns:
+**             none.
+*/
+
+mci_flush(doquit, allbut)
+       bool doquit;
+       MCI *allbut;
+{
+       register int i;
+
+       if (MciCache == NULL)
+               return;
+
+       for (i = 0; i < MaxMciCache; i++)
+               if (allbut != MciCache[i])
+                       mci_uncache(&MciCache[i], doquit);
+}
+\f/*
+**  MCI_GET -- get information about a particular host
+*/
+
+MCI *
+mci_get(host, m)
+       char *host;
+       MAILER *m;
+{
+       register MCI *mci;
+       register STAB *s;
+
+#ifdef DAEMON
+       extern SOCKADDR CurHostAddr;
+
+       /* clear CurHostAddr so we don't get a bogus address with this name */
+       bzero(&CurHostAddr, sizeof CurHostAddr);
+#endif DAEMON
+
+       s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
+       mci = &s->s_mci;
+       mci->mci_host = s->s_name;
+
+       if (tTd(42, 2))
+       {
+               printf("mci_get(%s %s): mci_state=%d, _flags=%x, _exitstat=%d, _errno=%d\n",
+                       host, m->m_name, mci->mci_state, mci->mci_flags,
+                       mci->mci_exitstat, mci->mci_errno);
+       }
+
+       if (mci->mci_state == MCIS_OPEN)
+       {
+               /* poke the connection to see if it's still alive */
+               smtpprobe(mci);
+
+               /* reset the stored state in the event of a timeout */
+               if (mci->mci_state != MCIS_OPEN)
+               {
+                       mci->mci_errno = 0;
+                       mci->mci_exitstat = EX_OK;
+                       mci->mci_state = MCIS_CLOSED;
+               }
+       }
+
+       return mci;
+}
+\f/*
+**  MCI_DUMP -- dump the contents of an MCI structure.
+**
+**     Parameters:
+**             mci -- the MCI structure to dump.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             none.
+*/
+
+mci_dump(mci)
+       register MCI *mci;
+{
+       extern char *ctime();
+
+       printf("MCI@%x: ", mci);
+       if (mci == NULL)
+       {
+               printf("NULL\n");
+               return;
+       }
+       printf("flags=%o, errno=%d, exitstat=%d, state=%d, pid=%d, maxsize=%ld\n",
+               mci->mci_flags, mci->mci_errno, mci->mci_exitstat,
+               mci->mci_state, mci->mci_pid, mci->mci_maxsize);
+       printf("\tphase=%s, mailer=%s,\n",
+               mci->mci_phase == NULL ? "NULL" : mci->mci_phase,
+               mci->mci_mailer == NULL ? "NULL" : mci->mci_mailer->m_name);
+       printf("\thost=%s, lastuse=%s\n",
+               mci->mci_host == NULL ? "NULL" : mci->mci_host,
+               ctime(&mci->mci_lastuse));
+}
index 1d14a01..65cfc5f 100644 (file)
@@ -1,5 +1,5 @@
-.\" Copyright (c) 1985, 1990 The Regents of the University of California.
-.\" All rights reserved.
+.\" Copyright (c) 1985, 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
@@ -29,9 +29,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"     @(#)newaliases.1       6.7 (Berkeley) 7/30/91
+.\"     @(#)newaliases.1       8.1 (Berkeley) 6/7/93
 .\"
 .\"
-.Dd July 30, 1991
+.Dd June 7, 1993
 .Dt NEWALIASES 1
 .Os BSD 4
 .Sh NAME
 .Dt NEWALIASES 1
 .Os BSD 4
 .Sh NAME
index 2ee24e0..3e4beb5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)parseaddr.c        5.13 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)parseaddr.c        8.1 (Berkeley) 6/27/93";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -66,6 +66,9 @@ static char sccsid[] = "@(#)parseaddr.c       5.13 (Berkeley) 6/1/90";
 **                     +1 -- copy everything.
 **             delim -- the character to terminate the address, passed
 **                     to prescan.
 **                     +1 -- copy everything.
 **             delim -- the character to terminate the address, passed
 **                     to prescan.
+**             delimptr -- if non-NULL, set to the location of the
+**                     delim character that was found.
+**             e -- the envelope that will contain this address.
 **
 **     Returns:
 **             A pointer to the address descriptor header (`a' if
 **
 **     Returns:
 **             A pointer to the address descriptor header (`a' if
@@ -77,49 +80,69 @@ static char sccsid[] = "@(#)parseaddr.c     5.13 (Berkeley) 6/1/90";
 */
 
 /* following delimiters are inherent to the internal algorithms */
 */
 
 /* following delimiters are inherent to the internal algorithms */
-# define DELIMCHARS    "\001()<>,;\\\"\r\n"    /* word delimiters */
+# define DELIMCHARS    "()<>,;\r\n"    /* default word delimiters */
 
 ADDRESS *
 
 ADDRESS *
-parseaddr(addr, a, copyf, delim)
+parseaddr(addr, a, copyf, delim, delimptr, e)
        char *addr;
        register ADDRESS *a;
        int copyf;
        char *addr;
        register ADDRESS *a;
        int copyf;
-       char delim;
+       int delim;
+       char **delimptr;
+       register ENVELOPE *e;
 {
        register char **pvp;
 {
        register char **pvp;
-       register struct mailer *m;
+       auto char *delimptrbuf;
+       bool queueup;
        char pvpbuf[PSBUFSIZE];
        char pvpbuf[PSBUFSIZE];
-       extern char **prescan();
        extern ADDRESS *buildaddr();
        extern ADDRESS *buildaddr();
+       extern bool invalidaddr();
 
        /*
        **  Initialize and prescan address.
        */
 
 
        /*
        **  Initialize and prescan address.
        */
 
-       CurEnv->e_to = addr;
+       e->e_to = addr;
        if (tTd(20, 1))
                printf("\n--parseaddr(%s)\n", addr);
 
        if (tTd(20, 1))
                printf("\n--parseaddr(%s)\n", addr);
 
-       pvp = prescan(addr, delim, pvpbuf);
+       if (invalidaddr(addr))
+       {
+               if (tTd(20, 1))
+                       printf("parseaddr-->bad address\n");
+               return NULL;
+       }
+
+       if (delimptr == NULL)
+               delimptr = &delimptrbuf;
+
+       pvp = prescan(addr, delim, pvpbuf, delimptr);
        if (pvp == NULL)
        if (pvp == NULL)
+       {
+               if (tTd(20, 1))
+                       printf("parseaddr-->NULL\n");
                return (NULL);
                return (NULL);
+       }
 
        /*
        **  Apply rewriting rules.
        **      Ruleset 0 does basic parsing.  It must resolve.
        */
 
 
        /*
        **  Apply rewriting rules.
        **      Ruleset 0 does basic parsing.  It must resolve.
        */
 
-       rewrite(pvp, 3);
-       rewrite(pvp, 0);
+       queueup = FALSE;
+       if (rewrite(pvp, 3, e) == EX_TEMPFAIL)
+               queueup = TRUE;
+       if (rewrite(pvp, 0, e) == EX_TEMPFAIL)
+               queueup = TRUE;
 
        /*
        **  See if we resolved to a real mailer.
        */
 
 
        /*
        **  See if we resolved to a real mailer.
        */
 
-       if (pvp[0][0] != CANONNET)
+       if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
        {
                setstat(EX_USAGE);
        {
                setstat(EX_USAGE);
-               usrerr("cannot resolve name");
+               syserr("554 cannot resolve name");
                return (NULL);
        }
 
                return (NULL);
        }
 
@@ -127,47 +150,32 @@ parseaddr(addr, a, copyf, delim)
        **  Build canonical address from pvp.
        */
 
        **  Build canonical address from pvp.
        */
 
-       a = buildaddr(pvp, a);
+       a = buildaddr(pvp, a, e);
        if (a == NULL)
                return (NULL);
        if (a == NULL)
                return (NULL);
-       m = a->q_mailer;
 
        /*
        **  Make local copies of the host & user and then
        **  transport them out.
        */
 
 
        /*
        **  Make local copies of the host & user and then
        **  transport them out.
        */
 
-       if (copyf > 0)
-       {
-               extern char *DelimChar;
-               char savec = *DelimChar;
-
-               *DelimChar = '\0';
-               a->q_paddr = newstr(addr);
-               *DelimChar = savec;
-       }
-       else
-               a->q_paddr = addr;
-
-       if (a->q_user == NULL)
-               a->q_user = "";
-       if (a->q_host == NULL)
-               a->q_host = "";
-
-       if (copyf >= 0)
-       {
-               a->q_host = newstr(a->q_host);
-               if (a->q_user != a->q_paddr)
-                       a->q_user = newstr(a->q_user);
-       }
+       allocaddr(a, copyf, addr, *delimptr);
 
        /*
 
        /*
-       **  Convert host name to lower case if requested.
-       **      User name will be done later.
+       **  If there was a parsing failure, mark it for queueing.
        */
 
        */
 
-       if (!bitnset(M_HST_UPPER, m->m_flags))
-               makelower(a->q_host);
+       if (queueup)
+       {
+               char *msg = "Transient parse error -- message queued for future delivery";
+
+               if (tTd(20, 1))
+                       printf("parseaddr: queuing message\n");
+               message(msg);
+               if (e->e_message == NULL)
+                       e->e_message = newstr(msg);
+               a->q_flags |= QQUEUEUP;
+       }
 
        /*
        **  Compute return value.
 
        /*
        **  Compute return value.
@@ -182,25 +190,84 @@ parseaddr(addr, a, copyf, delim)
        return (a);
 }
 \f/*
        return (a);
 }
 \f/*
-**  LOWERADDR -- map UPPER->lower case on addresses as requested.
+**  INVALIDADDR -- check for address containing meta-characters
 **
 **     Parameters:
 **
 **     Parameters:
-**             a -- address to be mapped.
+**             addr -- the address to check.
+**
+**     Returns:
+**             TRUE -- if the address has any "wierd" characters
+**             FALSE -- otherwise.
+*/
+
+bool
+invalidaddr(addr)
+       register char *addr;
+{
+       for (; *addr != '\0'; addr++)
+       {
+               if ((*addr & 0340) != 0200)
+                       continue;
+               setstat(EX_USAGE);
+               usrerr("553 Address contained invalid control characters");
+               return TRUE;
+       }
+       return FALSE;
+}
+\f/*
+**  ALLOCADDR -- do local allocations of address on demand.
+**
+**     Also lowercases the host name if requested.
+**
+**     Parameters:
+**             a -- the address to reallocate.
+**             copyf -- the copy flag (see parseaddr for description).
+**             paddr -- the printname of the address.
+**             delimptr -- a pointer to the address delimiter.  Must be set.
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
 **
 **     Returns:
 **             none.
 **
 **     Side Effects:
-**             none.
+**             Copies portions of a into local buffers as requested.
 */
 
 */
 
-loweraddr(a)
+allocaddr(a, copyf, paddr, delimptr)
        register ADDRESS *a;
        register ADDRESS *a;
+       int copyf;
+       char *paddr;
+       char *delimptr;
 {
 {
-       register MAILER *m = a->q_mailer;
+       if (tTd(24, 4))
+               printf("allocaddr(copyf=%d, paddr=%s)\n", copyf, paddr);
 
 
-       if (!bitnset(M_USR_UPPER, m->m_flags))
-               makelower(a->q_user);
+       if (copyf > 0 && paddr != NULL)
+       {
+               char savec = *delimptr;
+
+               if (savec != '\0')
+                       *delimptr = '\0';
+               a->q_paddr = newstr(paddr);
+               if (savec != '\0')
+                       *delimptr = savec;
+       }
+       else
+               a->q_paddr = paddr;
+
+       if (a->q_user == NULL)
+               a->q_user = "";
+       if (a->q_host == NULL)
+               a->q_host = "";
+
+       if (copyf >= 0)
+       {
+               a->q_host = newstr(a->q_host);
+               if (a->q_user != a->q_paddr)
+                       a->q_user = newstr(a->q_user);
+       }
+
+       if (a->q_paddr == NULL)
+               a->q_paddr = a->q_user;
 }
 \f/*
 **  PRESCAN -- Prescan name and make it canonical
 }
 \f/*
 **  PRESCAN -- Prescan name and make it canonical
@@ -225,13 +292,12 @@ loweraddr(a)
 **                     If '\t' then we are reading the .cf file.
 **             pvpbuf -- place to put the saved text -- note that
 **                     the pointers are static.
 **                     If '\t' then we are reading the .cf file.
 **             pvpbuf -- place to put the saved text -- note that
 **                     the pointers are static.
+**             delimptr -- if non-NULL, set to the location of the
+**                     terminating delimiter.
 **
 **     Returns:
 **             A pointer to a vector of tokens.
 **             NULL on error.
 **
 **     Returns:
 **             A pointer to a vector of tokens.
 **             NULL on error.
-**
-**     Side Effects:
-**             sets DelimChar to point to the character matching 'delim'.
 */
 
 /* states and character types */
 */
 
 /* states and character types */
@@ -261,13 +327,12 @@ static short StateTab[NSTATES][NSTATES] =
 
 # define NOCHAR                -1      /* signal nothing in lookahead token */
 
 
 # define NOCHAR                -1      /* signal nothing in lookahead token */
 
-char   *DelimChar;             /* set to point to the delimiter */
-
 char **
 char **
-prescan(addr, delim, pvpbuf)
+prescan(addr, delim, pvpbuf, delimptr)
        char *addr;
        char delim;
        char pvpbuf[];
        char *addr;
        char delim;
        char pvpbuf[];
+       char **delimptr;
 {
        register char *p;
        register char *q;
 {
        register char *p;
        register char *q;
@@ -279,6 +344,7 @@ prescan(addr, delim, pvpbuf)
        char *tok;
        int state;
        int newstate;
        char *tok;
        int state;
        int newstate;
+       char *saveto = CurEnv->e_to;
        static char *av[MAXATOM+1];
        extern int errno;
 
        static char *av[MAXATOM+1];
        extern int errno;
 
@@ -290,10 +356,11 @@ prescan(addr, delim, pvpbuf)
        cmntcnt = 0;
        anglecnt = 0;
        avp = av;
        cmntcnt = 0;
        anglecnt = 0;
        avp = av;
-       state = OPR;
+       state = ATM;
        c = NOCHAR;
        p = addr;
        c = NOCHAR;
        p = addr;
-       if (tTd(22, 45))
+       CurEnv->e_to = p;
+       if (tTd(22, 11))
        {
                printf("prescan: ");
                xputs(p);
        {
                printf("prescan: ");
                xputs(p);
@@ -307,13 +374,15 @@ prescan(addr, delim, pvpbuf)
                for (;;)
                {
                        /* store away any old lookahead character */
                for (;;)
                {
                        /* store away any old lookahead character */
-                       if (c != NOCHAR)
+                       if (c != NOCHAR && !bslashmode)
                        {
                                /* see if there is room */
                                if (q >= &pvpbuf[PSBUFSIZE - 5])
                                {
                        {
                                /* see if there is room */
                                if (q >= &pvpbuf[PSBUFSIZE - 5])
                                {
-                                       usrerr("Address too long");
-                                       DelimChar = p;
+                                       usrerr("553 Address too long");
+                                       if (delimptr != NULL)
+                                               *delimptr = p;
+                                       CurEnv->e_to = saveto;
                                        return (NULL);
                                }
 
                                        return (NULL);
                                }
 
@@ -324,8 +393,31 @@ prescan(addr, delim, pvpbuf)
                        /* read a new input character */
                        c = *p++;
                        if (c == '\0')
                        /* read a new input character */
                        c = *p++;
                        if (c == '\0')
+                       {
+                               /* diagnose and patch up bad syntax */
+                               if (state == QST)
+                               {
+                                       usrerr("553 Unbalanced '\"'");
+                                       c = '"';
+                               }
+                               else if (cmntcnt > 0)
+                               {
+                                       usrerr("553 Unbalanced '('");
+                                       c = ')';
+                               }
+                               else if (anglecnt > 0)
+                               {
+                                       c = '>';
+                                       usrerr("553 Unbalanced '<'");
+                               }
+                               else
+                                       break;
+
+                               p--;
+                       }
+                       else if (c == delim && anglecnt <= 0 &&
+                                       cmntcnt <= 0 && state != QST)
                                break;
                                break;
-                       c &= ~0200;
 
                        if (tTd(22, 101))
                                printf("c=%c, s=%d; ", c, state);
 
                        if (tTd(22, 101))
                                printf("c=%c, s=%d; ", c, state);
@@ -334,15 +426,24 @@ prescan(addr, delim, pvpbuf)
                        *q = '\0';
                        if (bslashmode)
                        {
                        *q = '\0';
                        if (bslashmode)
                        {
-                               /* kludge \! for naive users */
-                               if (c != '!')
-                                       c |= 0200;
                                bslashmode = FALSE;
                                bslashmode = FALSE;
+
+                               /* kludge \! for naive users */
+                               if (cmntcnt > 0)
+                               {
+                                       c = NOCHAR;
+                                       continue;
+                               }
+                               else if (c != '!' || state == QST)
+                               {
+                                       *q++ = '\\';
+                                       continue;
+                               }
                        }
                        }
-                       else if (c == '\\')
+
+                       if (c == '\\')
                        {
                                bslashmode = TRUE;
                        {
                                bslashmode = TRUE;
-                               c = NOCHAR;
                        }
                        else if (state == QST)
                        {
                        }
                        else if (state == QST)
                        {
@@ -357,8 +458,10 @@ prescan(addr, delim, pvpbuf)
                        {
                                if (cmntcnt <= 0)
                                {
                        {
                                if (cmntcnt <= 0)
                                {
-                                       usrerr("Unbalanced ')'");
-                                       DelimChar = p;
+                                       usrerr("553 Unbalanced ')'");
+                                       if (delimptr != NULL)
+                                               *delimptr = p;
+                                       CurEnv->e_to = saveto;
                                        return (NULL);
                                }
                                else
                                        return (NULL);
                                }
                                else
@@ -372,13 +475,15 @@ prescan(addr, delim, pvpbuf)
                        {
                                if (anglecnt <= 0)
                                {
                        {
                                if (anglecnt <= 0)
                                {
-                                       usrerr("Unbalanced '>'");
-                                       DelimChar = p;
+                                       usrerr("553 Unbalanced '>'");
+                                       if (delimptr != NULL)
+                                               *delimptr = p;
+                                       CurEnv->e_to = saveto;
                                        return (NULL);
                                }
                                anglecnt--;
                        }
                                        return (NULL);
                                }
                                anglecnt--;
                        }
-                       else if (delim == ' ' && isspace(c))
+                       else if (delim == ' ' && isascii(c) && isspace(c))
                                c = ' ';
 
                        if (c == NOCHAR)
                                c = ' ';
 
                        if (c == NOCHAR)
@@ -410,24 +515,28 @@ prescan(addr, delim, pvpbuf)
                        }
                        if (avp >= &av[MAXATOM])
                        {
                        }
                        if (avp >= &av[MAXATOM])
                        {
-                               syserr("prescan: too many tokens");
-                               DelimChar = p;
+                               syserr("553 prescan: too many tokens");
+                               if (delimptr != NULL)
+                                       *delimptr = p;
+                               CurEnv->e_to = saveto;
                                return (NULL);
                        }
                        *avp++ = tok;
                }
        } while (c != '\0' && (c != delim || anglecnt > 0));
        *avp = NULL;
                                return (NULL);
                        }
                        *avp++ = tok;
                }
        } while (c != '\0' && (c != delim || anglecnt > 0));
        *avp = NULL;
-       DelimChar = --p;
-       if (cmntcnt > 0)
-               usrerr("Unbalanced '('");
-       else if (anglecnt > 0)
-               usrerr("Unbalanced '<'");
-       else if (state == QST)
-               usrerr("Unbalanced '\"'");
-       else if (av[0] != NULL)
-               return (av);
-       return (NULL);
+       p--;
+       if (delimptr != NULL)
+               *delimptr = p;
+       if (tTd(22, 12))
+       {
+               printf("prescan==>");
+               printav(av);
+       }
+       CurEnv->e_to = saveto;
+       if (av[0] == NULL)
+               return (NULL);
+       return (av);
 }
 \f/*
 **  TOKTYPE -- return token type
 }
 \f/*
 **  TOKTYPE -- return token type
@@ -443,7 +552,7 @@ prescan(addr, delim, pvpbuf)
 */
 
 toktype(c)
 */
 
 toktype(c)
-       register char c;
+       register int c;
 {
        static char buf[50];
        static bool firstime = TRUE;
 {
        static char buf[50];
        static bool firstime = TRUE;
@@ -451,18 +560,23 @@ toktype(c)
        if (firstime)
        {
                firstime = FALSE;
        if (firstime)
        {
                firstime = FALSE;
-               expand("\001o", buf, &buf[sizeof buf - 1], CurEnv);
+               expand("\201o", buf, &buf[sizeof buf - 1], CurEnv);
                (void) strcat(buf, DELIMCHARS);
        }
                (void) strcat(buf, DELIMCHARS);
        }
+       c &= 0377;
        if (c == MATCHCLASS || c == MATCHREPL || c == MATCHNCLASS)
                return (ONE);
        if (c == MATCHCLASS || c == MATCHREPL || c == MATCHNCLASS)
                return (ONE);
+       if (c == MACRODEXPAND)
+               return (ONE);
        if (c == '"')
                return (QST);
        if (c == '"')
                return (QST);
+       if ((c & 0340) == 0200)
+               return (OPR);
        if (!isascii(c))
                return (ATM);
        if (isspace(c) || c == ')')
                return (SPC);
        if (!isascii(c))
                return (ATM);
        if (isspace(c) || c == ')')
                return (SPC);
-       if (iscntrl(c) || index(buf, c) != NULL)
+       if (strchr(buf, c) != NULL)
                return (OPR);
        return (ATM);
 }
                return (OPR);
        return (ATM);
 }
@@ -490,9 +604,12 @@ toktype(c)
 **
 **     Parameters:
 **             pvp -- pointer to token vector.
 **
 **     Parameters:
 **             pvp -- pointer to token vector.
+**             ruleset -- the ruleset to use for rewriting.
+**             e -- the current envelope.
 **
 **     Returns:
 **
 **     Returns:
-**             none.
+**             A status code.  If EX_TEMPFAIL, higher level code should
+**                     attempt recovery.
 **
 **     Side Effects:
 **             pvp is modified.
 **
 **     Side Effects:
 **             pvp is modified.
@@ -502,14 +619,17 @@ struct match
 {
        char    **first;        /* first token matched */
        char    **last;         /* last token matched */
 {
        char    **first;        /* first token matched */
        char    **last;         /* last token matched */
+       char    **pattern;      /* pointer to pattern */
 };
 
 # define MAXMATCH      9       /* max params per rewrite */
 
 
 };
 
 # define MAXMATCH      9       /* max params per rewrite */
 
 
-rewrite(pvp, ruleset)
+int
+rewrite(pvp, ruleset, e)
        char **pvp;
        int ruleset;
        char **pvp;
        int ruleset;
+       register ENVELOPE *e;
 {
        register char *ap;              /* address pointer */
        register char *rp;              /* rewrite pointer */
 {
        register char *ap;              /* address pointer */
        register char *rp;              /* rewrite pointer */
@@ -517,6 +637,8 @@ rewrite(pvp, ruleset)
        register char **rvp;            /* rewrite vector pointer */
        register struct match *mlp;     /* cur ptr into mlist */
        register struct rewrite *rwr;   /* pointer to current rewrite rule */
        register char **rvp;            /* rewrite vector pointer */
        register struct match *mlp;     /* cur ptr into mlist */
        register struct rewrite *rwr;   /* pointer to current rewrite rule */
+       int ruleno;                     /* current rule number */
+       int rstat = EX_OK;              /* return status */
        struct match mlist[MAXMATCH];   /* stores match on LHS */
        char *npvp[MAXATOM+1];          /* temporary space for rebuild */
 
        struct match mlist[MAXMATCH];   /* stores match on LHS */
        char *npvp[MAXATOM+1];          /* temporary space for rebuild */
 
@@ -525,16 +647,24 @@ rewrite(pvp, ruleset)
                printf("rewrite: ruleset %2d   input:", ruleset);
                printav(pvp);
        }
                printf("rewrite: ruleset %2d   input:", ruleset);
                printav(pvp);
        }
+       if (ruleset < 0 || ruleset >= MAXRWSETS)
+       {
+               syserr("554 rewrite: illegal ruleset number %d", ruleset);
+               return EX_CONFIG;
+       }
        if (pvp == NULL)
        if (pvp == NULL)
-               return;
+               return EX_USAGE;
 
        /*
        **  Run through the list of rewrite rules, applying
        **      any that match.
        */
 
 
        /*
        **  Run through the list of rewrite rules, applying
        **      any that match.
        */
 
+       ruleno = 1;
        for (rwr = RewriteRules[ruleset]; rwr != NULL; )
        {
        for (rwr = RewriteRules[ruleset]; rwr != NULL; )
        {
+               int loopcount = 0;
+
                if (tTd(21, 12))
                {
                        printf("-----trying rule:");
                if (tTd(21, 12))
                {
                        printf("-----trying rule:");
@@ -545,15 +675,27 @@ rewrite(pvp, ruleset)
                mlp = mlist;
                rvp = rwr->r_lhs;
                avp = pvp;
                mlp = mlist;
                rvp = rwr->r_lhs;
                avp = pvp;
+               if (++loopcount > 100)
+               {
+                       syserr("554 Infinite loop in ruleset %d, rule %d",
+                               ruleset, ruleno);
+                       if (tTd(21, 1))
+                       {
+                               printf("workspace: ");
+                               printav(pvp);
+                       }
+                       break;
+               }
+
                while ((ap = *avp) != NULL || *rvp != NULL)
                {
                        rp = *rvp;
                        if (tTd(21, 35))
                        {
                while ((ap = *avp) != NULL || *rvp != NULL)
                {
                        rp = *rvp;
                        if (tTd(21, 35))
                        {
-                               printf("ap=");
-                               xputs(ap);
-                               printf(", rp=");
+                               printf("ADVANCE rp=");
                                xputs(rp);
                                xputs(rp);
+                               printf(", ap=");
+                               xputs(ap);
                                printf("\n");
                        }
                        if (rp == NULL)
                                printf("\n");
                        }
                        if (rp == NULL)
@@ -561,33 +703,58 @@ rewrite(pvp, ruleset)
                                /* end-of-pattern before end-of-address */
                                goto backup;
                        }
                                /* end-of-pattern before end-of-address */
                                goto backup;
                        }
-                       if (ap == NULL && *rp != MATCHZANY)
+                       if (ap == NULL && (*rp & 0377) != MATCHZANY &&
+                           (*rp & 0377) != MATCHZERO)
                        {
                        {
-                               /* end-of-input */
-                               break;
+                               /* end-of-input with patterns left */
+                               goto backup;
                        }
 
                        }
 
-                       switch (*rp)
+                       switch (*rp & 0377)
                        {
                                register STAB *s;
                        {
                                register STAB *s;
+                               char buf[MAXLINE];
 
                          case MATCHCLASS:
 
                          case MATCHCLASS:
-                         case MATCHNCLASS:
-                               /* match any token in (not in) a class */
-                               s = stab(ap, ST_CLASS, ST_FIND);
+                               /* match any phrase in a class */
+                               mlp->pattern = rvp;
+                               mlp->first = avp;
+       extendclass:
+                               ap = *avp;
+                               if (ap == NULL)
+                                       goto backup;
+                               mlp->last = avp++;
+                               cataddr(mlp->first, mlp->last, buf, sizeof buf, '\0');
+                               s = stab(buf, ST_CLASS, ST_FIND);
                                if (s == NULL || !bitnset(rp[1], s->s_class))
                                {
                                if (s == NULL || !bitnset(rp[1], s->s_class))
                                {
-                                       if (*rp == MATCHCLASS)
-                                               goto backup;
+                                       if (tTd(21, 36))
+                                       {
+                                               printf("EXTEND  rp=");
+                                               xputs(rp);
+                                               printf(", ap=");
+                                               xputs(ap);
+                                               printf("\n");
+                                       }
+                                       goto extendclass;
                                }
                                }
-                               else if (*rp == MATCHNCLASS)
+                               if (tTd(21, 36))
+                                       printf("CLMATCH\n");
+                               mlp++;
+                               break;
+
+                         case MATCHNCLASS:
+                               /* match any token not in a class */
+                               s = stab(ap, ST_CLASS, ST_FIND);
+                               if (s != NULL && bitnset(rp[1], s->s_class))
                                        goto backup;
 
                                        goto backup;
 
-                               /* explicit fall-through */
+                               /* fall through */
 
                          case MATCHONE:
                          case MATCHANY:
                                /* match exactly one token */
 
                          case MATCHONE:
                          case MATCHANY:
                                /* match exactly one token */
+                               mlp->pattern = rvp;
                                mlp->first = avp;
                                mlp->last = avp++;
                                mlp++;
                                mlp->first = avp;
                                mlp->last = avp++;
                                mlp++;
@@ -595,11 +762,49 @@ rewrite(pvp, ruleset)
 
                          case MATCHZANY:
                                /* match zero or more tokens */
 
                          case MATCHZANY:
                                /* match zero or more tokens */
+                               mlp->pattern = rvp;
                                mlp->first = avp;
                                mlp->last = avp - 1;
                                mlp++;
                                break;
 
                                mlp->first = avp;
                                mlp->last = avp - 1;
                                mlp++;
                                break;
 
+                         case MATCHZERO:
+                               /* match zero tokens */
+                               break;
+
+                         case MACRODEXPAND:
+                               /*
+                               **  Match against run-time macro.
+                               **  This algorithm is broken for the
+                               **  general case (no recursive macros,
+                               **  improper tokenization) but should
+                               **  work for the usual cases.
+                               */
+
+                               ap = macvalue(rp[1], e);
+                               mlp->first = avp;
+                               if (tTd(21, 2))
+                                       printf("rewrite: LHS $&%c => \"%s\"\n",
+                                               rp[1],
+                                               ap == NULL ? "(NULL)" : ap);
+
+                               if (ap == NULL)
+                                       break;
+                               while (*ap != '\0')
+                               {
+                                       if (*avp == NULL ||
+                                           strncasecmp(ap, *avp, strlen(*avp)) != 0)
+                                       {
+                                               /* no match */
+                                               avp = mlp->first;
+                                               goto backup;
+                                       }
+                                       ap += strlen(*avp++);
+                               }
+
+                               /* match */
+                               break;
+
                          default:
                                /* must have exact match */
                                if (strcasecmp(rp, ap))
                          default:
                                /* must have exact match */
                                if (strcasecmp(rp, ap))
@@ -612,29 +817,47 @@ rewrite(pvp, ruleset)
                        rvp++;
                        continue;
 
                        rvp++;
                        continue;
 
-                 backup:
+         backup:
                        /* match failed -- back up */
                        /* match failed -- back up */
-                       while (--rvp >= rwr->r_lhs)
+                       while (--mlp >= mlist)
                        {
                        {
+                               rvp = mlp->pattern;
                                rp = *rvp;
                                rp = *rvp;
-                               if (*rp == MATCHANY || *rp == MATCHZANY)
+                               avp = mlp->last + 1;
+                               ap = *avp;
+
+                               if (tTd(21, 36))
+                               {
+                                       printf("BACKUP  rp=");
+                                       xputs(rp);
+                                       printf(", ap=");
+                                       xputs(ap);
+                                       printf("\n");
+                               }
+
+                               if (ap == NULL)
+                               {
+                                       /* run off the end -- back up again */
+                                       continue;
+                               }
+                               if ((*rp & 0377) == MATCHANY ||
+                                   (*rp & 0377) == MATCHZANY)
                                {
                                        /* extend binding and continue */
                                {
                                        /* extend binding and continue */
-                                       avp = ++mlp[-1].last;
-                                       avp++;
+                                       mlp->last = avp++;
                                        rvp++;
                                        rvp++;
+                                       mlp++;
                                        break;
                                }
                                        break;
                                }
-                               avp--;
-                               if (*rp == MATCHONE || *rp == MATCHCLASS ||
-                                   *rp == MATCHNCLASS)
+                               if ((*rp & 0377) == MATCHCLASS)
                                {
                                {
-                                       /* back out binding */
-                                       mlp--;
+                                       /* extend binding and try again */
+                                       mlp->last = avp;
+                                       goto extendclass;
                                }
                        }
 
                                }
                        }
 
-                       if (rvp < rwr->r_lhs)
+                       if (mlp < mlist)
                        {
                                /* total failure to match */
                                break;
                        {
                                /* total failure to match */
                                break;
@@ -645,11 +868,12 @@ rewrite(pvp, ruleset)
                **  See if we successfully matched
                */
 
                **  See if we successfully matched
                */
 
-               if (rvp < rwr->r_lhs || *rvp != NULL)
+               if (mlp < mlist || *rvp != NULL)
                {
                        if (tTd(21, 10))
                                printf("----- rule fails\n");
                        rwr = rwr->r_next;
                {
                        if (tTd(21, 10))
                                printf("----- rule fails\n");
                        rwr = rwr->r_next;
+                       ruleno++;
                        continue;
                }
 
                        continue;
                }
 
@@ -661,17 +885,18 @@ rewrite(pvp, ruleset)
                }
 
                rp = *rvp;
                }
 
                rp = *rvp;
-               if (*rp == CANONUSER)
+               if ((*rp & 0377) == CANONUSER)
                {
                        rvp++;
                        rwr = rwr->r_next;
                {
                        rvp++;
                        rwr = rwr->r_next;
+                       ruleno++;
                }
                }
-               else if (*rp == CANONHOST)
+               else if ((*rp & 0377) == CANONHOST)
                {
                        rvp++;
                        rwr = NULL;
                }
                {
                        rvp++;
                        rwr = NULL;
                }
-               else if (*rp == CANONNET)
+               else if ((*rp & 0377) == CANONNET)
                        rwr = NULL;
 
                /* substitute */
                        rwr = NULL;
 
                /* substitute */
@@ -681,14 +906,15 @@ rewrite(pvp, ruleset)
                        register char **pp;
 
                        rp = *rvp;
                        register char **pp;
 
                        rp = *rvp;
-                       if (*rp == MATCHREPL)
+                       if ((*rp & 0377) == MATCHREPL)
                        {
                                /* substitute from LHS */
                                m = &mlist[rp[1] - '1'];
                        {
                                /* substitute from LHS */
                                m = &mlist[rp[1] - '1'];
-                               if (m >= mlp)
+                               if (m < mlist || m >= mlp)
                                {
                                {
-                                       syserr("rewrite: ruleset %d: replacement out of bounds", ruleset);
-                                       return;
+                                       syserr("554 rewrite: ruleset %d: replacement $%c out of bounds",
+                                               ruleset, rp[1]);
+                                       return EX_CONFIG;
                                }
                                if (tTd(21, 15))
                                {
                                }
                                if (tTd(21, 15))
                                {
@@ -707,8 +933,8 @@ rewrite(pvp, ruleset)
                                {
                                        if (avp >= &npvp[MAXATOM])
                                        {
                                {
                                        if (avp >= &npvp[MAXATOM])
                                        {
-                                               syserr("rewrite: expansion too long");
-                                               return;
+                                               syserr("554 rewrite: expansion too long");
+                                               return EX_DATAERR;
                                        }
                                        *avp++ = *pp++;
                                }
                                        }
                                        *avp++ = *pp++;
                                }
@@ -719,16 +945,27 @@ rewrite(pvp, ruleset)
                                if (avp >= &npvp[MAXATOM])
                                {
        toolong:
                                if (avp >= &npvp[MAXATOM])
                                {
        toolong:
-                                       syserr("rewrite: expansion too long");
-                                       return;
+                                       syserr("554 rewrite: expansion too long");
+                                       return EX_DATAERR;
+                               }
+                               if ((*rp & 0377) != MACRODEXPAND)
+                                       *avp++ = rp;
+                               else
+                               {
+                                       *avp = macvalue(rp[1], e);
+                                       if (tTd(21, 2))
+                                               printf("rewrite: RHS $&%c => \"%s\"\n",
+                                                       rp[1],
+                                                       *avp == NULL ? "(NULL)" : *avp);
+                                       if (*avp != NULL)
+                                               avp++;
                                }
                                }
-                               *avp++ = rp;
                        }
                }
                *avp++ = NULL;
 
                /*
                        }
                }
                *avp++ = NULL;
 
                /*
-               **  Check for any hostname lookups.
+               **  Check for any hostname/keyword lookups.
                */
 
                for (rvp = npvp; *rvp != NULL; rvp++)
                */
 
                for (rvp = npvp; *rvp != NULL; rvp++)
@@ -736,49 +973,147 @@ rewrite(pvp, ruleset)
                        char **hbrvp;
                        char **xpvp;
                        int trsize;
                        char **hbrvp;
                        char **xpvp;
                        int trsize;
-                       char *olddelimchar;
+                       char *replac;
+                       int endtoken;
+                       STAB *map;
+                       char *mapname;
+                       char **key_rvp;
+                       char **arg_rvp;
+                       char **default_rvp;
                        char buf[MAXNAME + 1];
                        char *pvpb1[MAXATOM + 1];
                        char buf[MAXNAME + 1];
                        char *pvpb1[MAXATOM + 1];
+                       char *argvect[10];
                        char pvpbuf[PSBUFSIZE];
                        char pvpbuf[PSBUFSIZE];
-                       extern char *DelimChar;
 
 
-                       if (**rvp != HOSTBEGIN)
+                       if ((**rvp & 0377) != HOSTBEGIN &&
+                           (**rvp & 0377) != LOOKUPBEGIN)
                                continue;
 
                        /*
                                continue;
 
                        /*
-                       **  Got a hostname lookup.
+                       **  Got a hostname/keyword lookup.
                        **
                        **      This could be optimized fairly easily.
                        */
 
                        hbrvp = rvp;
                        **
                        **      This could be optimized fairly easily.
                        */
 
                        hbrvp = rvp;
+                       if ((**rvp & 0377) == HOSTBEGIN)
+                       {
+                               endtoken = HOSTEND;
+                               mapname = "host";
+                       }
+                       else
+                       {
+                               endtoken = LOOKUPEND;
+                               mapname = *++rvp;
+                       }
+                       map = stab(mapname, ST_MAP, ST_FIND);
+                       if (map == NULL)
+                               syserr("554 rewrite: map %s not found", mapname);
 
                        /* extract the match part */
 
                        /* extract the match part */
-                       while (*++rvp != NULL && **rvp != HOSTEND)
-                               continue;
+                       key_rvp = ++rvp;
+                       default_rvp = NULL;
+                       arg_rvp = argvect;
+                       xpvp = NULL;
+                       replac = pvpbuf;
+                       while (*rvp != NULL && (**rvp & 0377) != endtoken)
+                       {
+                               int nodetype = **rvp & 0377;
+
+                               if (nodetype != CANONHOST && nodetype != CANONUSER)
+                               {
+                                       rvp++;
+                                       continue;
+                               }
+
+                               *rvp++ = NULL;
+
+                               if (xpvp != NULL)
+                               {
+                                       cataddr(xpvp, NULL, replac,
+                                               &pvpbuf[sizeof pvpbuf] - replac,
+                                               '\0');
+                                       *++arg_rvp = replac;
+                                       replac += strlen(replac) + 1;
+                                       xpvp = NULL;
+                               }
+                               switch (nodetype)
+                               {
+                                 case CANONHOST:
+                                       xpvp = rvp;
+                                       break;
+
+                                 case CANONUSER:
+                                       default_rvp = rvp;
+                                       break;
+                               }
+                       }
                        if (*rvp != NULL)
                                *rvp++ = NULL;
                        if (*rvp != NULL)
                                *rvp++ = NULL;
+                       if (xpvp != NULL)
+                       {
+                               cataddr(xpvp, NULL, replac,
+                                       &pvpbuf[sizeof pvpbuf] - replac, 
+                                       '\0');
+                               *++arg_rvp = replac;
+                       }
+                       *++arg_rvp = NULL;
 
                        /* save the remainder of the input string */
                        trsize = (int) (avp - rvp + 1) * sizeof *rvp;
                        bcopy((char *) rvp, (char *) pvpb1, trsize);
 
                        /* look it up */
 
                        /* save the remainder of the input string */
                        trsize = (int) (avp - rvp + 1) * sizeof *rvp;
                        bcopy((char *) rvp, (char *) pvpb1, trsize);
 
                        /* look it up */
-                       cataddr(++hbrvp, buf, sizeof buf);
-                       maphostname(buf, sizeof buf);
-
-                       /* scan the new host name */
-                       olddelimchar = DelimChar;
-                       xpvp = prescan(buf, '\0', pvpbuf);
-                       DelimChar = olddelimchar;
-                       if (xpvp == NULL)
+                       cataddr(key_rvp, NULL, buf, sizeof buf, '\0');
+                       argvect[0] = buf;
+                       if (map != NULL && bitset(MF_OPEN, map->s_map.map_mflags))
                        {
                        {
-                               syserr("rewrite: cannot prescan canonical hostname: %s", buf);
-                               return;
+                               auto int stat = EX_OK;
+
+                               /* XXX should try to auto-open the map here */
+
+                               if (tTd(60, 1))
+                                       printf("map_lookup(%s, %s) => ",
+                                               mapname, buf);
+                               replac = (*map->s_map.map_class->map_lookup)(&map->s_map,
+                                               buf, argvect, &stat);
+                               if (tTd(60, 1))
+                                       printf("%s (%d)\n",
+                                               replac ? replac : "NOT FOUND",
+                                               stat);
+
+                               /* should recover if stat == EX_TEMPFAIL */
+                               if (stat == EX_TEMPFAIL)
+                                       rstat = stat;
+                       }
+                       else
+                               replac = NULL;
+
+                       /* if no replacement, use default */
+                       if (replac == NULL && default_rvp != NULL)
+                       {
+                               /* create the default */
+                               cataddr(default_rvp, NULL, buf, sizeof buf, '\0');
+                               replac = buf;
+                       }
+
+                       if (replac == NULL)
+                       {
+                               xpvp = key_rvp;
+                       }
+                       else
+                       {
+                               /* scan the new replacement */
+                               xpvp = prescan(replac, '\0', pvpbuf, NULL);
+                               if (xpvp == NULL)
+                               {
+                                       /* prescan already printed error */
+                                       return EX_DATAERR;
+                               }
                        }
 
                        /* append it to the token list */
                        }
 
                        /* append it to the token list */
-                       for (avp = --hbrvp; *xpvp != NULL; xpvp++)
+                       for (avp = hbrvp; *xpvp != NULL; xpvp++)
                        {
                                *avp++ = newstr(*xpvp);
                                if (avp >= &npvp[MAXATOM])
                        {
                                *avp++ = newstr(*xpvp);
                                if (avp >= &npvp[MAXATOM])
@@ -797,13 +1132,19 @@ rewrite(pvp, ruleset)
                **  Check for subroutine calls.
                */
 
                **  Check for subroutine calls.
                */
 
-               if (*npvp != NULL && **npvp == CALLSUBR)
+               if (*npvp != NULL && (**npvp & 0377) == CALLSUBR)
                {
                {
+                       int stat;
+
                        bcopy((char *) &npvp[2], (char *) pvp,
                                (int) (avp - npvp - 2) * sizeof *avp);
                        if (tTd(21, 3))
                                printf("-----callsubr %s\n", npvp[1]);
                        bcopy((char *) &npvp[2], (char *) pvp,
                                (int) (avp - npvp - 2) * sizeof *avp);
                        if (tTd(21, 3))
                                printf("-----callsubr %s\n", npvp[1]);
-                       rewrite(pvp, atoi(npvp[1]));
+                       stat = rewrite(pvp, atoi(npvp[1]), e);
+                       if (rstat == EX_OK || stat == EX_TEMPFAIL)
+                               rstat = stat;
+                       if ((**pvp & 0377) == CANONNET)
+                               rwr = NULL;
                }
                else
                {
                }
                else
                {
@@ -822,6 +1163,8 @@ rewrite(pvp, ruleset)
                printf("rewrite: ruleset %2d returns:", ruleset);
                printav(pvp);
        }
                printf("rewrite: ruleset %2d returns:", ruleset);
                printav(pvp);
        }
+
+       return rstat;
 }
 \f/*
 **  BUILDADDR -- build address from token vector.
 }
 \f/*
 **  BUILDADDR -- build address from token vector.
@@ -830,6 +1173,7 @@ rewrite(pvp, ruleset)
 **             tv -- token vector.
 **             a -- pointer to address descriptor to fill.
 **                     If NULL, one will be allocated.
 **             tv -- token vector.
 **             a -- pointer to address descriptor to fill.
 **                     If NULL, one will be allocated.
+**             e -- the current envelope.
 **
 **     Returns:
 **             NULL if there was an error.
 **
 **     Returns:
 **             NULL if there was an error.
@@ -839,91 +1183,181 @@ rewrite(pvp, ruleset)
 **             fills in 'a'
 */
 
 **             fills in 'a'
 */
 
+struct errcodes
+{
+       char    *ec_name;               /* name of error code */
+       int     ec_code;                /* numeric code */
+} ErrorCodes[] =
+{
+       "usage",        EX_USAGE,
+       "nouser",       EX_NOUSER,
+       "nohost",       EX_NOHOST,
+       "unavailable",  EX_UNAVAILABLE,
+       "software",     EX_SOFTWARE,
+       "tempfail",     EX_TEMPFAIL,
+       "protocol",     EX_PROTOCOL,
+#ifdef EX_CONFIG
+       "config",       EX_CONFIG,
+#endif
+       NULL,           EX_UNAVAILABLE,
+};
+
 ADDRESS *
 ADDRESS *
-buildaddr(tv, a)
+buildaddr(tv, a, e)
        register char **tv;
        register ADDRESS *a;
        register char **tv;
        register ADDRESS *a;
+       register ENVELOPE *e;
 {
 {
-       static char buf[MAXNAME];
        struct mailer **mp;
        register struct mailer *m;
        struct mailer **mp;
        register struct mailer *m;
+       char *bp;
+       int spaceleft;
+       static char buf[MAXNAME];
 
        if (a == NULL)
                a = (ADDRESS *) xalloc(sizeof *a);
        bzero((char *) a, sizeof *a);
 
        /* figure out what net/mailer to use */
 
        if (a == NULL)
                a = (ADDRESS *) xalloc(sizeof *a);
        bzero((char *) a, sizeof *a);
 
        /* figure out what net/mailer to use */
-       if (**tv != CANONNET)
+       if ((**tv & 0377) != CANONNET)
        {
        {
-               syserr("buildaddr: no net");
+               syserr("554 buildaddr: no net");
                return (NULL);
        }
        tv++;
                return (NULL);
        }
        tv++;
-       if (!strcasecmp(*tv, "error"))
+       if (strcasecmp(*tv, "error") == 0)
        {
        {
-               if (**++tv == CANONHOST)
+               if ((**++tv & 0377) == CANONHOST)
                {
                {
-                       setstat(atoi(*++tv));
+                       register struct errcodes *ep;
+
+                       if (isascii(**++tv) && isdigit(**tv))
+                       {
+                               setstat(atoi(*tv));
+                       }
+                       else
+                       {
+                               for (ep = ErrorCodes; ep->ec_name != NULL; ep++)
+                                       if (strcasecmp(ep->ec_name, *tv) == 0)
+                                               break;
+                               setstat(ep->ec_code);
+                       }
                        tv++;
                }
                        tv++;
                }
-               if (**tv != CANONUSER)
-                       syserr("buildaddr: error: no user");
-               buf[0] = '\0';
-               while (*++tv != NULL)
-               {
-                       if (buf[0] != '\0')
-                               (void) strcat(buf, " ");
-                       (void) strcat(buf, *tv);
-               }
+               if ((**tv & 0377) != CANONUSER)
+                       syserr("554 buildaddr: error: no user");
+               cataddr(++tv, NULL, buf, sizeof buf, ' ');
+               stripquotes(buf);
                usrerr(buf);
                return (NULL);
        }
                usrerr(buf);
                return (NULL);
        }
+
        for (mp = Mailer; (m = *mp++) != NULL; )
        {
        for (mp = Mailer; (m = *mp++) != NULL; )
        {
-               if (!strcasecmp(m->m_name, *tv))
+               if (strcasecmp(m->m_name, *tv) == 0)
                        break;
        }
        if (m == NULL)
        {
                        break;
        }
        if (m == NULL)
        {
-               syserr("buildaddr: unknown mailer %s", *tv);
+               syserr("554 buildaddr: unknown mailer %s", *tv);
                return (NULL);
        }
        a->q_mailer = m;
 
        /* figure out what host (if any) */
        tv++;
                return (NULL);
        }
        a->q_mailer = m;
 
        /* figure out what host (if any) */
        tv++;
-       if (!bitnset(M_LOCAL, m->m_flags))
+       if ((**tv & 0377) == CANONHOST)
        {
        {
-               if (**tv++ != CANONHOST)
+               bp = buf;
+               spaceleft = sizeof buf - 1;
+               while (*++tv != NULL && (**tv & 0377) != CANONUSER)
                {
                {
-                       syserr("buildaddr: no host");
-                       return (NULL);
+                       int i = strlen(*tv);
+
+                       if (i > spaceleft)
+                       {
+                               /* out of space for this address */
+                               if (spaceleft >= 0)
+                                       syserr("554 buildaddr: host too long (%.40s...)",
+                                               buf);
+                               i = spaceleft;
+                               spaceleft = 0;
+                       }
+                       if (i <= 0)
+                               continue;
+                       bcopy(*tv, bp, i);
+                       bp += i;
+                       spaceleft -= i;
                }
                }
-               buf[0] = '\0';
-               while (*tv != NULL && **tv != CANONUSER)
-                       (void) strcat(buf, *tv++);
+               *bp = '\0';
                a->q_host = newstr(buf);
        }
        else
                a->q_host = newstr(buf);
        }
        else
+       {
+               if (!bitnset(M_LOCALMAILER, m->m_flags))
+               {
+                       syserr("554 buildaddr: no host");
+                       return (NULL);
+               }
                a->q_host = NULL;
                a->q_host = NULL;
+       }
 
        /* figure out the user */
 
        /* figure out the user */
-       if (*tv == NULL || **tv != CANONUSER)
+       if (*tv == NULL || (**tv & 0377) != CANONUSER)
        {
        {
-               syserr("buildaddr: no user");
+               syserr("554 buildaddr: no user");
                return (NULL);
        }
                return (NULL);
        }
+       tv++;
 
 
-       /* rewrite according recipient mailer rewriting rules */
-       rewrite(++tv, 2);
-       if (m->m_r_rwset > 0)
-               rewrite(tv, m->m_r_rwset);
-       rewrite(tv, 4);
+       /* do special mapping for local mailer */
+       if (m == LocalMailer && *tv != NULL)
+       {
+               register char *p = *tv;
+
+               if (*p == '"')
+                       p++;
+               if (*p == '|')
+                       a->q_mailer = m = ProgMailer;
+               else if (*p == '/')
+                       a->q_mailer = m = FileMailer;
+               else if (*p == ':')
+               {
+                       /* may be :include: */
+                       cataddr(tv, NULL, buf, sizeof buf, '\0');
+                       stripquotes(buf);
+                       if (strncasecmp(buf, ":include:", 9) == 0)
+                       {
+                               /* if :include:, don't need further rewriting */
+                               a->q_mailer = m = InclMailer;
+                               a->q_user = &buf[9];
+                               return (a);
+                       }
+               }
+       }
+
+       if (m == LocalMailer && *tv != NULL && strcmp(*tv, "@") == 0)
+       {
+               tv++;
+               a->q_flags |= QNOTREMOTE;
+       }
+
+       /* do cleanup of final address */
+       (void) rewrite(tv, 4, e);
 
        /* save the result for the command line/RCPT argument */
 
        /* save the result for the command line/RCPT argument */
-       cataddr(tv, buf, sizeof buf);
+       cataddr(tv, NULL, buf, sizeof buf, '\0');
        a->q_user = buf;
 
        a->q_user = buf;
 
+       /*
+       **  Do mapping to lower case as requested by mailer
+       */
+
+       if (a->q_host != NULL && !bitnset(M_HST_UPPER, m->m_flags))
+               makelower(a->q_host);
+       if (!bitnset(M_USR_UPPER, m->m_flags))
+               makelower(a->q_user);
+
        return (a);
 }
 \f/*
        return (a);
 }
 \f/*
@@ -931,8 +1365,12 @@ buildaddr(tv, a)
 **
 **     Parameters:
 **             pvp -- parameter vector to rebuild.
 **
 **     Parameters:
 **             pvp -- parameter vector to rebuild.
+**             evp -- last parameter to include.  Can be NULL to
+**                     use entire pvp.
 **             buf -- buffer to build the string into.
 **             sz -- size of buf.
 **             buf -- buffer to build the string into.
 **             sz -- size of buf.
+**             spacesub -- the space separator character; if null,
+**                     use SpaceSub.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -941,16 +1379,21 @@ buildaddr(tv, a)
 **             Destroys buf.
 */
 
 **             Destroys buf.
 */
 
-cataddr(pvp, buf, sz)
+cataddr(pvp, evp, buf, sz, spacesub)
        char **pvp;
        char **pvp;
+       char **evp;
        char *buf;
        register int sz;
        char *buf;
        register int sz;
+       char spacesub;
 {
        bool oatomtok = FALSE;
        bool natomtok = FALSE;
        register int i;
        register char *p;
 
 {
        bool oatomtok = FALSE;
        bool natomtok = FALSE;
        register int i;
        register char *p;
 
+       if (spacesub == '\0')
+               spacesub = SpaceSub;
+
        if (pvp == NULL)
        {
                (void) strcpy(buf, "");
        if (pvp == NULL)
        {
                (void) strcpy(buf, "");
@@ -962,12 +1405,13 @@ cataddr(pvp, buf, sz)
        {
                natomtok = (toktype(**pvp) == ATM);
                if (oatomtok && natomtok)
        {
                natomtok = (toktype(**pvp) == ATM);
                if (oatomtok && natomtok)
-                       *p++ = SpaceSub;
+                       *p++ = spacesub;
                (void) strcpy(p, *pvp);
                oatomtok = natomtok;
                p += i;
                sz -= i + 1;
                (void) strcpy(p, *pvp);
                oatomtok = natomtok;
                p += i;
                sz -= i + 1;
-               pvp++;
+               if (pvp++ == evp)
+                       break;
        }
        *p = '\0';
 }
        }
        *p = '\0';
 }
@@ -1001,13 +1445,21 @@ sameaddr(a, b)
        if (strcmp(a->q_user, b->q_user) != 0)
                return (FALSE);
 
        if (strcmp(a->q_user, b->q_user) != 0)
                return (FALSE);
 
-       /* if the mailer ignores hosts, we have succeeded! */
-       if (bitnset(M_LOCAL, a->q_mailer->m_flags))
-               return (TRUE);
+       /* if we have good uids for both but the differ, these are different */
+       if (bitset(QGOODUID, a->q_flags & b->q_flags) && a->q_uid != b->q_uid)
+               return (FALSE);
 
        /* otherwise compare hosts (but be careful for NULL ptrs) */
 
        /* otherwise compare hosts (but be careful for NULL ptrs) */
+       if (a->q_host == b->q_host)
+       {
+               /* probably both null pointers */
+               return (TRUE);
+       }
        if (a->q_host == NULL || b->q_host == NULL)
        if (a->q_host == NULL || b->q_host == NULL)
+       {
+               /* only one is a null pointer */
                return (FALSE);
                return (FALSE);
+       }
        if (strcmp(a->q_host, b->q_host) != 0)
                return (FALSE);
 
        if (strcmp(a->q_host, b->q_host) != 0)
                return (FALSE);
 
@@ -1032,19 +1484,32 @@ printaddr(a, follow)
        bool follow;
 {
        bool first = TRUE;
        bool follow;
 {
        bool first = TRUE;
+       register MAILER *m;
+       MAILER pseudomailer;
 
        while (a != NULL)
        {
                first = FALSE;
                printf("%x=", a);
                (void) fflush(stdout);
 
        while (a != NULL)
        {
                first = FALSE;
                printf("%x=", a);
                (void) fflush(stdout);
-               printf("%s: mailer %d (%s), host `%s', user `%s', ruser `%s'\n",
-                      a->q_paddr, a->q_mailer->m_mno, a->q_mailer->m_name,
+
+               /* find the mailer -- carefully */
+               m = a->q_mailer;
+               if (m == NULL)
+               {
+                       m = &pseudomailer;
+                       m->m_mno = -1;
+                       m->m_name = "NULL";
+               }
+
+               printf("%s:\n\tmailer %d (%s), host `%s', user `%s', ruser `%s'\n",
+                      a->q_paddr, m->m_mno, m->m_name,
                       a->q_host, a->q_user, a->q_ruser? a->q_ruser: "<null>");
                       a->q_host, a->q_user, a->q_ruser? a->q_ruser: "<null>");
-               printf("\tnext=%x, flags=%o, alias %x\n", a->q_next, a->q_flags,
-                      a->q_alias);
-               printf("\thome=\"%s\", fullname=\"%s\"\n", a->q_home,
-                      a->q_fullname);
+               printf("\tnext=%x, flags=%o, alias %x, uid %d, gid %d\n",
+                      a->q_next, a->q_flags, a->q_alias, a->q_uid, a->q_gid);
+               printf("\towner=%s, home=\"%s\", fullname=\"%s\"\n",
+                      a->q_owner == NULL ? "(none)" : a->q_owner,
+                      a->q_home, a->q_fullname);
 
                if (!follow)
                        return;
 
                if (!follow)
                        return;
@@ -1061,10 +1526,9 @@ printaddr(a, follow)
 **             name -- the name to translate.
 **             m -- the mailer that we want to do rewriting relative
 **                     to.
 **             name -- the name to translate.
 **             m -- the mailer that we want to do rewriting relative
 **                     to.
-**             senderaddress -- if set, uses the sender rewriting rules
-**                     rather than the recipient rewriting rules.
-**             canonical -- if set, strip out any comment information,
-**                     etc.
+**             flags -- fine tune operations.
+**             pstat -- pointer to status word.
+**             e -- the current envelope.
 **
 **     Returns:
 **             the text string representing this address relative to
 **
 **     Returns:
 **             the text string representing this address relative to
@@ -1079,27 +1543,33 @@ printaddr(a, follow)
 */
 
 char *
 */
 
 char *
-remotename(name, m, senderaddress, canonical)
+remotename(name, m, flags, pstat, e)
        char *name;
        struct mailer *m;
        char *name;
        struct mailer *m;
-       bool senderaddress;
-       bool canonical;
+       int flags;
+       int *pstat;
+       register ENVELOPE *e;
 {
        register char **pvp;
        char *fancy;
 {
        register char **pvp;
        char *fancy;
-       extern char *macvalue();
-       char *oldg = macvalue('g', CurEnv);
+       char *oldg = macvalue('g', e);
+       int rwset;
        static char buf[MAXNAME];
        char lbuf[MAXNAME];
        char pvpbuf[PSBUFSIZE];
        static char buf[MAXNAME];
        char lbuf[MAXNAME];
        char pvpbuf[PSBUFSIZE];
-       extern char **prescan();
        extern char *crackaddr();
 
        if (tTd(12, 1))
                printf("remotename(%s)\n", name);
 
        /* don't do anything if we are tagging it as special */
        extern char *crackaddr();
 
        if (tTd(12, 1))
                printf("remotename(%s)\n", name);
 
        /* don't do anything if we are tagging it as special */
-       if ((senderaddress ? m->m_s_rwset : m->m_r_rwset) < 0)
+       if (bitset(RF_SENDERADDR, flags))
+               rwset = bitset(RF_HEADERADDR, flags) ? m->m_sh_rwset
+                                                    : m->m_se_rwset;
+       else
+               rwset = bitset(RF_HEADERADDR, flags) ? m->m_rh_rwset
+                                                    : m->m_re_rwset;
+       if (rwset < 0)
                return (name);
 
        /*
                return (name);
 
        /*
@@ -1107,8 +1577,8 @@ remotename(name, m, senderaddress, canonical)
        **      This will leave the name as a comment and a $g macro.
        */
 
        **      This will leave the name as a comment and a $g macro.
        */
 
-       if (canonical)
-               fancy = "\001g";
+       if (bitset(RF_CANONICAL, flags) || bitnset(M_NOCOMMENT, m->m_flags))
+               fancy = "\201g";
        else
                fancy = crackaddr(name);
 
        else
                fancy = crackaddr(name);
 
@@ -1120,11 +1590,12 @@ remotename(name, m, senderaddress, canonical)
        **      domain will be appended.
        */
 
        **      domain will be appended.
        */
 
-       pvp = prescan(name, '\0', pvpbuf);
+       pvp = prescan(name, '\0', pvpbuf, NULL);
        if (pvp == NULL)
                return (name);
        if (pvp == NULL)
                return (name);
-       rewrite(pvp, 3);
-       if (CurEnv->e_fromdomain != NULL)
+       if (rewrite(pvp, 3, e) == EX_TEMPFAIL)
+               *pstat = EX_TEMPFAIL;
+       if (bitset(RF_ADDDOMAIN, flags) && e->e_fromdomain != NULL)
        {
                /* append from domain to this address */
                register char **pxp = pvp;
        {
                /* append from domain to this address */
                register char **pxp = pvp;
@@ -1135,11 +1606,12 @@ remotename(name, m, senderaddress, canonical)
                if (*pxp == NULL)
                {
                        /* no.... append the "@domain" from the sender */
                if (*pxp == NULL)
                {
                        /* no.... append the "@domain" from the sender */
-                       register char **qxq = CurEnv->e_fromdomain;
+                       register char **qxq = e->e_fromdomain;
 
                        while ((*pxp++ = *qxq++) != NULL)
                                continue;
 
                        while ((*pxp++ = *qxq++) != NULL)
                                continue;
-                       rewrite(pvp, 3);
+                       if (rewrite(pvp, 3, e) == EX_TEMPFAIL)
+                               *pstat = EX_TEMPFAIL;
                }
        }
 
                }
        }
 
@@ -1150,17 +1622,20 @@ remotename(name, m, senderaddress, canonical)
        **      Then run it through any receiving-mailer-specific rulesets.
        */
 
        **      Then run it through any receiving-mailer-specific rulesets.
        */
 
-       if (senderaddress)
+       if (bitset(RF_SENDERADDR, flags))
        {
        {
-               rewrite(pvp, 1);
-               if (m->m_s_rwset > 0)
-                       rewrite(pvp, m->m_s_rwset);
+               if (rewrite(pvp, 1, e) == EX_TEMPFAIL)
+                       *pstat = EX_TEMPFAIL;
        }
        else
        {
        }
        else
        {
-               rewrite(pvp, 2);
-               if (m->m_r_rwset > 0)
-                       rewrite(pvp, m->m_r_rwset);
+               if (rewrite(pvp, 2, e) == EX_TEMPFAIL)
+                       *pstat = EX_TEMPFAIL;
+       }
+       if (rwset > 0)
+       {
+               if (rewrite(pvp, rwset, e) == EX_TEMPFAIL)
+                       *pstat = EX_TEMPFAIL;
        }
 
        /*
        }
 
        /*
@@ -1170,18 +1645,211 @@ remotename(name, m, senderaddress, canonical)
        **      may be used as a default to the above rules.
        */
 
        **      may be used as a default to the above rules.
        */
 
-       rewrite(pvp, 4);
+       if (rewrite(pvp, 4, e) == EX_TEMPFAIL)
+               *pstat = EX_TEMPFAIL;
 
        /*
        **  Now restore the comment information we had at the beginning.
        */
 
 
        /*
        **  Now restore the comment information we had at the beginning.
        */
 
-       cataddr(pvp, lbuf, sizeof lbuf);
-       define('g', lbuf, CurEnv);
-       expand(fancy, buf, &buf[sizeof buf - 1], CurEnv);
-       define('g', oldg, CurEnv);
+       cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0');
+       define('g', lbuf, e);
+       expand(fancy, buf, &buf[sizeof buf - 1], e);
+       define('g', oldg, e);
 
        if (tTd(12, 1))
                printf("remotename => `%s'\n", buf);
        return (buf);
 }
 
        if (tTd(12, 1))
                printf("remotename => `%s'\n", buf);
        return (buf);
 }
+\f/*
+**  MAPLOCALUSER -- run local username through ruleset 5 for final redirection
+**
+**     Parameters:
+**             a -- the address to map (but just the user name part).
+**             sendq -- the sendq in which to install any replacement
+**                     addresses.
+**
+**     Returns:
+**             none.
+*/
+
+maplocaluser(a, sendq, e)
+       register ADDRESS *a;
+       ADDRESS **sendq;
+       ENVELOPE *e;
+{
+       register char **pvp;
+       register ADDRESS *a1 = NULL;
+       auto char *delimptr;
+       char pvpbuf[PSBUFSIZE];
+
+       if (tTd(29, 1))
+       {
+               printf("maplocaluser: ");
+               printaddr(a, FALSE);
+       }
+       pvp = prescan(a->q_user, '\0', pvpbuf, &delimptr);
+       if (pvp == NULL)
+               return;
+
+       (void) rewrite(pvp, 5, e);
+       if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
+               return;
+
+       /* if non-null, mailer destination specified -- has it changed? */
+       a1 = buildaddr(pvp, NULL, e);
+       if (a1 == NULL || sameaddr(a, a1))
+               return;
+
+       /* mark old address as dead; insert new address */
+       a->q_flags |= QDONTSEND;
+       if (tTd(29, 5))
+       {
+               printf("maplocaluser: QDONTSEND ");
+               printaddr(a, FALSE);
+       }
+       a1->q_alias = a;
+       allocaddr(a1, 1, NULL, delimptr);
+       (void) recipient(a1, sendq, e);
+}
+\f/*
+**  DEQUOTE_INIT -- initialize dequote map
+**
+**     This is a no-op.
+**
+**     Parameters:
+**             map -- the internal map structure.
+**             args -- arguments.
+**
+**     Returns:
+**             TRUE.
+*/
+
+bool
+dequote_init(map, args)
+       MAP *map;
+       char *args;
+{
+       register char *p = args;
+
+       for (;;)
+       {
+               while (isascii(*p) && isspace(*p))
+                       p++;
+               if (*p != '-')
+                       break;
+               switch (*++p)
+               {
+                 case 'a':
+                       map->map_app = ++p;
+                       break;
+               }
+               while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+                       p++;
+               if (*p != '\0')
+                       *p = '\0';
+       }
+       if (map->map_app != NULL)
+               map->map_app = newstr(map->map_app);
+
+       return TRUE;
+}
+\f/*
+**  DEQUOTE_MAP -- unquote an address
+**
+**     Parameters:
+**             map -- the internal map structure (ignored).
+**             name -- the name to dequote.
+**             av -- arguments (ignored).
+**             statp -- pointer to status out-parameter.
+**
+**     Returns:
+**             NULL -- if there were no quotes, or if the resulting
+**                     unquoted buffer would not be acceptable to prescan.
+**             else -- The dequoted buffer.
+*/
+
+char *
+dequote_map(map, name, av, statp)
+       MAP *map;
+       char *name;
+       char **av;
+       int *statp;
+{
+       register char *p;
+       register char *q;
+       register char c;
+       int anglecnt;
+       int cmntcnt;
+       int quotecnt;
+       int spacecnt;
+       bool quotemode;
+       bool bslashmode;
+
+       anglecnt = 0;
+       cmntcnt = 0;
+       quotecnt = 0;
+       spacecnt = 0;
+       quotemode = FALSE;
+       bslashmode = FALSE;
+
+       for (p = q = name; (c = *p++) != '\0'; )
+       {
+               if (bslashmode)
+               {
+                       bslashmode = FALSE;
+                       *q++ = c;
+                       continue;
+               }
+
+               switch (c)
+               {
+                 case '\\':
+                       bslashmode = TRUE;
+                       break;
+
+                 case '(':
+                       cmntcnt++;
+                       break;
+
+                 case ')':
+                       if (cmntcnt-- <= 0)
+                               return NULL;
+                       break;
+
+                 case ' ':
+                       spacecnt++;
+                       break;
+               }
+
+               if (cmntcnt > 0)
+               {
+                       *q++ = c;
+                       continue;
+               }
+
+               switch (c)
+               {
+                 case '"':
+                       quotemode = !quotemode;
+                       quotecnt++;
+                       continue;
+
+                 case '<':
+                       anglecnt++;
+                       break;
+
+                 case '>':
+                       if (anglecnt-- <= 0)
+                               return NULL;
+                       break;
+               }
+               *q++ = c;
+       }
+
+       if (anglecnt != 0 || cmntcnt != 0 || bslashmode ||
+           quotemode || quotecnt <= 0 || spacecnt != 0)
+               return NULL;
+       *q++ = '\0';
+       return name;
+}
index 588a648..be9a072 100644 (file)
@@ -1,6 +1,6 @@
 /*-
 /*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)pathnames.h 5.1 (Berkeley) 4/19/90
+ *     @(#)pathnames.h 8.1 (Berkeley) 6/7/93
  */
 
  */
 
-#define        _PATH_SENDMAILCF        "/etc/sendmail.cf";
-#define        _PATH_SENDMAILFC        "/etc/sendmail.fc";
+#ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF      "/etc/sendmail.cf"
+#endif
+
+#ifndef _PATH_SENDMAILFC
+# define _PATH_SENDMAILFC      "/etc/sendmail.fc"
+#endif
+
+#ifndef _PATH_SENDMAILPID
+# ifdef BSD4_4
+#  define _PATH_SENDMAILPID    "/var/run/sendmail.pid"
+# else
+#  define _PATH_SENDMAILPID    "/etc/sendmail.pid"
+# endif
+#endif
index 03b226a..c9cd073 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 
 #ifndef lint
 #ifdef QUEUE
 
 #ifndef lint
 #ifdef QUEUE
-static char sccsid[] = "@(#)queue.c    5.32 (Berkeley) 3/12/91 (with queueing)";
+static char sccsid[] = "@(#)queue.c    8.1 (Berkeley) 6/7/93 (with queueing)";
 #else
 #else
-static char sccsid[] = "@(#)queue.c    5.32 (Berkeley) 3/12/91 (without queueing)";
+static char sccsid[] = "@(#)queue.c    8.1 (Berkeley) 6/7/93 (without queueing)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
-# include <sys/stat.h>
-# include <sys/dir.h>
-# include <sys/file.h>
 # include <signal.h>
 # include <errno.h>
 # include <pwd.h>
 # include <signal.h>
 # include <errno.h>
 # include <pwd.h>
+# include <dirent.h>
 
 # ifdef QUEUE
 
 
 # ifdef QUEUE
 
@@ -64,7 +62,6 @@ struct work
 };
 
 typedef struct work    WORK;
 };
 
 typedef struct work    WORK;
-extern int la;
 
 WORK   *WorkQ;                 /* queue of things to be done */
 \f/*
 
 WORK   *WorkQ;                 /* queue of things to be done */
 \f/*
@@ -77,50 +74,67 @@ WORK        *WorkQ;                 /* queue of things to be done */
 **             announce -- if TRUE, tell when you are queueing up.
 **
 **     Returns:
 **             announce -- if TRUE, tell when you are queueing up.
 **
 **     Returns:
-**             locked FILE* to q file
+**             none.
 **
 **     Side Effects:
 **             The current request are saved in a control file.
 **
 **     Side Effects:
 **             The current request are saved in a control file.
+**             The queue file is left locked.
 */
 
 */
 
-FILE *
 queueup(e, queueall, announce)
        register ENVELOPE *e;
        bool queueall;
        bool announce;
 {
        char *qf;
 queueup(e, queueall, announce)
        register ENVELOPE *e;
        bool queueall;
        bool announce;
 {
        char *qf;
-       char buf[MAXLINE], tf[MAXLINE];
        register FILE *tfp;
        register HDR *h;
        register ADDRESS *q;
        register FILE *tfp;
        register HDR *h;
        register ADDRESS *q;
+       int fd;
+       int i;
+       bool newid;
+       register char *p;
        MAILER nullmailer;
        MAILER nullmailer;
-       int fd, ret;
+       char buf[MAXLINE], tf[MAXLINE];
 
        /*
        **  Create control file.
        */
 
 
        /*
        **  Create control file.
        */
 
-       do {
-               strcpy(tf, queuename(e, 't'));
-               fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode);
-               if (fd < 0) {
-                       if ( errno != EEXIST) {
-                               syserr("queueup: cannot create temp file %s",
-                                       tf);
-                               return NULL;
-                       }
-               } else {
-                       if (flock(fd, LOCK_EX|LOCK_NB) < 0) {
-                               if (errno != EWOULDBLOCK)
-                                       syserr("cannot flock(%s)", tf);
-                               close(fd);
-                               fd = -1;
+       newid = (e->e_id == NULL);
+       strcpy(tf, queuename(e, 't'));
+       tfp = e->e_lockfp;
+       if (tfp == NULL)
+               newid = FALSE;
+       if (newid)
+       {
+               tfp = e->e_lockfp;
+       }
+       else
+       {
+               /* get a locked tf file */
+               for (i = 100; --i >= 0; )
+               {
+                       fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode);
+                       if (fd < 0)
+                       {
+                               if (errno == EEXIST)
+                                       continue;
+notemp:
+                               syserr("!queueup: cannot create temp file %s", tf);
                        }
                        }
+
+                       if (lockfile(fd, tf, LOCK_EX|LOCK_NB))
+                               break;
+
+                       close(fd);
+                       sleep(i);
                }
                }
-       } while (fd < 0);
+               if (fd < 0)
+                       goto notemp;
 
 
-       tfp = fdopen(fd, "w");
+               tfp = fdopen(fd, "w");
+       }
 
        if (tTd(40, 1))
                printf("queueing %s\n", e->e_id);
 
        if (tTd(40, 1))
                printf("queueing %s\n", e->e_id);
@@ -137,14 +151,10 @@ queueup(e, queueall, announce)
                e->e_df = newstr(queuename(e, 'd'));
                fd = open(e->e_df, O_WRONLY|O_CREAT, FileMode);
                if (fd < 0)
                e->e_df = newstr(queuename(e, 'd'));
                fd = open(e->e_df, O_WRONLY|O_CREAT, FileMode);
                if (fd < 0)
-               {
-                       syserr("queueup: cannot create %s", e->e_df);
-                       (void) fclose(tfp);
-                       return NULL;
-               }
+                       syserr("!queueup: cannot create %s", e->e_df);
                dfp = fdopen(fd, "w");
                dfp = fdopen(fd, "w");
-               (*e->e_putbody)(dfp, ProgMailer, e);
-               (void) fclose(dfp);
+               (*e->e_putbody)(dfp, FileMailer, e, NULL);
+               (void) xfclose(dfp, "queueup dfp", e->e_id);
                e->e_putbody = putbody;
        }
 
                e->e_putbody = putbody;
        }
 
@@ -160,33 +170,61 @@ queueup(e, queueall, announce)
        /* output creation time */
        fprintf(tfp, "T%ld\n", e->e_ctime);
 
        /* output creation time */
        fprintf(tfp, "T%ld\n", e->e_ctime);
 
-       /* output name of data file */
+       /* output type and name of data file */
+       if (e->e_bodytype != NULL)
+               fprintf(tfp, "B%s\n", e->e_bodytype);
        fprintf(tfp, "D%s\n", e->e_df);
 
        /* message from envelope, if it exists */
        if (e->e_message != NULL)
                fprintf(tfp, "M%s\n", e->e_message);
 
        fprintf(tfp, "D%s\n", e->e_df);
 
        /* message from envelope, if it exists */
        if (e->e_message != NULL)
                fprintf(tfp, "M%s\n", e->e_message);
 
+       /* send various flag bits through */
+       p = buf;
+       if (bitset(EF_WARNING, e->e_flags))
+               *p++ = 'w';
+       if (bitset(EF_RESPONSE, e->e_flags))
+               *p++ = 'r';
+       *p++ = '\0';
+       if (buf[0] != '\0')
+               fprintf(tfp, "F%s\n", buf);
+
+       /* $r and $s and $_ macro values */
+       if ((p = macvalue('r', e)) != NULL)
+               fprintf(tfp, "$r%s\n", p);
+       if ((p = macvalue('s', e)) != NULL)
+               fprintf(tfp, "$s%s\n", p);
+       if ((p = macvalue('_', e)) != NULL)
+               fprintf(tfp, "$_%s\n", p);
+
        /* output name of sender */
        fprintf(tfp, "S%s\n", e->e_from.q_paddr);
 
        /* output name of sender */
        fprintf(tfp, "S%s\n", e->e_from.q_paddr);
 
+       /* output list of error recipients */
+       printctladdr(NULL, NULL);
+       for (q = e->e_errorqueue; q != NULL; q = q->q_next)
+       {
+               if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
+               {
+                       printctladdr(q, tfp);
+                       fprintf(tfp, "E%s\n", q->q_paddr);
+               }
+       }
+
        /* output list of recipient addresses */
        for (q = e->e_sendqueue; q != NULL; q = q->q_next)
        {
        /* output list of recipient addresses */
        for (q = e->e_sendqueue; q != NULL; q = q->q_next)
        {
-               if (queueall ? !bitset(QDONTSEND|QSENT, q->q_flags) :
-                              bitset(QQUEUEUP, q->q_flags))
+               if (bitset(QQUEUEUP, q->q_flags) ||
+                   (queueall && !bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags)))
                {
                {
-                       char *ctluser, *getctluser();
-
-                       if ((ctluser = getctluser(q)) != NULL)
-                               fprintf(tfp, "C%s\n", ctluser);
+                       printctladdr(q, tfp);
                        fprintf(tfp, "R%s\n", q->q_paddr);
                        if (announce)
                        {
                                e->e_to = q->q_paddr;
                        fprintf(tfp, "R%s\n", q->q_paddr);
                        if (announce)
                        {
                                e->e_to = q->q_paddr;
-                               message(Arpa_Info, "queued");
-                               if (LogLevel > 4)
-                                       logdelivery("queued");
+                               message("queued");
+                               if (LogLevel > 8)
+                                       logdelivery(NULL, NULL, "queued", e);
                                e->e_to = NULL;
                        }
                        if (tTd(40, 1))
                                e->e_to = NULL;
                        }
                        if (tTd(40, 1))
@@ -197,19 +235,6 @@ queueup(e, queueall, announce)
                }
        }
 
                }
        }
 
-       /* output list of error recipients */
-       for (q = e->e_errorqueue; q != NULL; q = q->q_next)
-       {
-               if (!bitset(QDONTSEND, q->q_flags))
-               {
-                       char *ctluser, *getctluser();
-
-                       if ((ctluser = getctluser(q)) != NULL)
-                               fprintf(tfp, "C%s\n", ctluser);
-                       fprintf(tfp, "E%s\n", q->q_paddr);
-               }
-       }
-
        /*
        **  Output headers for this message.
        **      Expand macros completely here.  Queue run will deal with
        /*
        **  Output headers for this message.
        **      Expand macros completely here.  Queue run will deal with
@@ -221,10 +246,11 @@ queueup(e, queueall, announce)
        */
 
        bzero((char *) &nullmailer, sizeof nullmailer);
        */
 
        bzero((char *) &nullmailer, sizeof nullmailer);
-       nullmailer.m_r_rwset = nullmailer.m_s_rwset = -1;
+       nullmailer.m_re_rwset = nullmailer.m_rh_rwset =
+                       nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1;
        nullmailer.m_eol = "\n";
 
        nullmailer.m_eol = "\n";
 
-       define('g', "\001f", e);
+       define('g', "\201f", e);
        for (h = e->e_header; h != NULL; h = h->h_link)
        {
                extern bool bitzerop();
        for (h = e->e_header; h != NULL; h = h->h_link)
        {
                extern bool bitzerop();
@@ -260,8 +286,13 @@ queueup(e, queueall, announce)
                }
                else if (bitset(H_FROM|H_RCPT, h->h_flags))
                {
                }
                else if (bitset(H_FROM|H_RCPT, h->h_flags))
                {
-                       commaize(h, h->h_value, tfp, bitset(EF_OLDSTYLE, e->e_flags),
-                                &nullmailer);
+                       bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
+
+                       if (bitset(H_FROM, h->h_flags))
+                               oldstyle = FALSE;
+
+                       commaize(h, h->h_value, tfp, oldstyle,
+                                &nullmailer, e);
                }
                else
                        fprintf(tfp, "%s: %s\n", h->h_field, h->h_value);
                }
                else
                        fprintf(tfp, "%s: %s\n", h->h_field, h->h_value);
@@ -271,19 +302,84 @@ queueup(e, queueall, announce)
        **  Clean up.
        */
 
        **  Clean up.
        */
 
-       qf = queuename(e, 'q');
-       if (rename(tf, qf) < 0)
-               syserr("cannot rename(%s, %s), df=%s", tf, qf, e->e_df);
+       fflush(tfp);
+       fsync(fileno(tfp));
+       if (ferror(tfp))
+       {
+               if (newid)
+                       syserr("!552 Error writing control file %s", tf);
+               else
+                       syserr("!452 Error writing control file %s", tf);
+       }
+
+       if (!newid)
+       {
+               qf = queuename(e, 'q');
+               if (rename(tf, qf) < 0)
+                       syserr("cannot rename(%s, %s), df=%s", tf, qf, e->e_df);
+               if (e->e_lockfp != NULL)
+                       (void) xfclose(e->e_lockfp, "queueup lockfp", e->e_id);
+               e->e_lockfp = tfp;
+       }
+       else
+               qf = tf;
        errno = 0;
 
 # ifdef LOG
        /* save log info */
        errno = 0;
 
 # ifdef LOG
        /* save log info */
-       if (LogLevel > 15)
+       if (LogLevel > 79)
                syslog(LOG_DEBUG, "%s: queueup, qf=%s, df=%s\n", e->e_id, qf, e->e_df);
                syslog(LOG_DEBUG, "%s: queueup, qf=%s, df=%s\n", e->e_id, qf, e->e_df);
-# endif LOG
-       fflush(tfp);
-       return tfp;
+# endif /* LOG */
+       return;
+}
+
+printctladdr(a, tfp)
+       register ADDRESS *a;
+       FILE *tfp;
+{
+       char *uname;
+       register struct passwd *pw;
+       register ADDRESS *q;
+       uid_t uid;
+       static ADDRESS *lastctladdr;
+       static uid_t lastuid;
+
+       /* initialization */
+       if (a == NULL || tfp == NULL)
+       {
+               if (lastctladdr != NULL && tfp != NULL)
+                       fprintf(tfp, "C\n");
+               lastctladdr = NULL;
+               lastuid = 0;
+               return;
+       }
+
+       /* find the active uid */
+       q = getctladdr(a);
+       if (q == NULL)
+               uid = 0;
+       else
+               uid = q->q_uid;
+
+       /* if a is an alias, use that for printing */
+       if (a->q_alias != NULL)
+               a = a->q_alias;
+
+       /* check to see if this is the same as last time */
+       if (lastctladdr != NULL && uid == lastuid &&
+           strcmp(lastctladdr->q_paddr, a->q_paddr) == 0)
+               return;
+       lastuid = uid;
+       lastctladdr = a;
+
+       if (uid == 0 || (pw = getpwuid(uid)) == NULL)
+               uname = "";
+       else
+               uname = pw->pw_name;
+
+       fprintf(tfp, "C%s:%s\n", uname, a->q_paddr);
 }
 }
+
 \f/*
 **  RUNQUEUE -- run the jobs in the queue.
 **
 \f/*
 **  RUNQUEUE -- run the jobs in the queue.
 **
@@ -302,26 +398,28 @@ queueup(e, queueall, announce)
 **             runs things in the mail queue.
 */
 
 **             runs things in the mail queue.
 */
 
+ENVELOPE       QueueEnvelope;          /* the queue run envelope */
+
 runqueue(forkflag)
        bool forkflag;
 {
 runqueue(forkflag)
        bool forkflag;
 {
-       extern bool shouldqueue();
+       register ENVELOPE *e;
+       extern ENVELOPE BlankEnvelope;
 
        /*
        **  If no work will ever be selected, don't even bother reading
        **  the queue.
        */
 
 
        /*
        **  If no work will ever be selected, don't even bother reading
        **  the queue.
        */
 
-       la = getla();   /* get load average */
+       CurrentLA = getla();    /* get load average */
 
 
-       if (shouldqueue(-100000000L))
+       if (shouldqueue(0L, curtime()))
        {
                if (Verbose)
                        printf("Skipping queue run -- load average too high\n");
        {
                if (Verbose)
                        printf("Skipping queue run -- load average too high\n");
-
-               if (forkflag)
-                       return;
-               finis();
+               if (forkflag && QueueIntvl != 0)
+                       (void) setevent(QueueIntvl, runqueue, TRUE);
+               return;
        }
 
        /*
        }
 
        /*
@@ -340,9 +438,9 @@ runqueue(forkflag)
                        /* parent -- pick up intermediate zombie */
 #ifndef SIGCHLD
                        (void) waitfor(pid);
                        /* parent -- pick up intermediate zombie */
 #ifndef SIGCHLD
                        (void) waitfor(pid);
-#else SIGCHLD
+#else /* SIGCHLD */
                        (void) signal(SIGCHLD, reapchild);
                        (void) signal(SIGCHLD, reapchild);
-#endif SIGCHLD
+#endif /* SIGCHLD */
                        if (QueueIntvl != 0)
                                (void) setevent(QueueIntvl, runqueue, TRUE);
                        return;
                        if (QueueIntvl != 0)
                                (void) setevent(QueueIntvl, runqueue, TRUE);
                        return;
@@ -351,17 +449,18 @@ runqueue(forkflag)
 #ifndef SIGCHLD
                if (fork() != 0)
                        exit(EX_OK);
 #ifndef SIGCHLD
                if (fork() != 0)
                        exit(EX_OK);
-#else SIGCHLD
+#else /* SIGCHLD */
                (void) signal(SIGCHLD, SIG_DFL);
                (void) signal(SIGCHLD, SIG_DFL);
-#endif SIGCHLD
+#endif /* SIGCHLD */
        }
 
        setproctitle("running queue: %s", QueueDir);
 
 # ifdef LOG
        }
 
        setproctitle("running queue: %s", QueueDir);
 
 # ifdef LOG
-       if (LogLevel > 11)
-               syslog(LOG_DEBUG, "runqueue %s, pid=%d", QueueDir, getpid());
-# endif LOG
+       if (LogLevel > 69)
+               syslog(LOG_DEBUG, "runqueue %s, pid=%d, forkflag=%d",
+                       QueueDir, getpid(), forkflag);
+# endif /* LOG */
 
        /*
        **  Release any resources used by the daemon code.
 
        /*
        **  Release any resources used by the daemon code.
@@ -369,13 +468,21 @@ runqueue(forkflag)
 
 # ifdef DAEMON
        clrdaemon();
 
 # ifdef DAEMON
        clrdaemon();
-# endif DAEMON
+# endif /* DAEMON */
+
+       /*
+       **  Create ourselves an envelope
+       */
+
+       CurEnv = &QueueEnvelope;
+       e = newenvelope(&QueueEnvelope, CurEnv);
+       e->e_flags = BlankEnvelope.e_flags;
 
        /*
        **  Make sure the alias database is open.
        */
 
 
        /*
        **  Make sure the alias database is open.
        */
 
-       initaliases(AliasFile, FALSE);
+       initmaps(FALSE, e);
 
        /*
        **  Start making passes through the queue.
 
        /*
        **  Start making passes through the queue.
@@ -393,13 +500,27 @@ runqueue(forkflag)
                WORK *w = WorkQ;
 
                WorkQ = WorkQ->w_next;
                WORK *w = WorkQ;
 
                WorkQ = WorkQ->w_next;
-               dowork(w);
+
+               /*
+               **  Ignore jobs that are too expensive for the moment.
+               */
+
+               if (shouldqueue(w->w_pri, w->w_ctime))
+               {
+                       if (Verbose)
+                               printf("\nSkipping %s\n", w->w_name + 2);
+               }
+               else
+               {
+                       dowork(w->w_name + 2, ForkQueueRuns, FALSE, e);
+               }
                free(w->w_name);
                free((char *) w);
        }
 
        /* exit without the usual cleanup */
                free(w->w_name);
                free((char *) w);
        }
 
        /* exit without the usual cleanup */
-       exit(ExitStat);
+       e->e_id = NULL;
+       finis();
 }
 \f/*
 **  ORDERQ -- order the work queue.
 }
 \f/*
 **  ORDERQ -- order the work queue.
@@ -420,11 +541,13 @@ runqueue(forkflag)
 
 # define NEED_P                001
 # define NEED_T                002
 
 # define NEED_P                001
 # define NEED_T                002
+# define NEED_R                004
+# define NEED_S                010
 
 orderq(doall)
        bool doall;
 {
 
 orderq(doall)
        bool doall;
 {
-       register struct direct *d;
+       register struct dirent *d;
        register WORK *w;
        DIR *f;
        register int i;
        register WORK *w;
        DIR *f;
        register int i;
@@ -432,6 +555,17 @@ orderq(doall)
        int wn = -1;
        extern workcmpf();
 
        int wn = -1;
        extern workcmpf();
 
+       if (tTd(41, 1))
+       {
+               printf("orderq:\n");
+               if (QueueLimitId != NULL)
+                       printf("\tQueueLimitId = %s\n", QueueLimitId);
+               if (QueueLimitSender != NULL)
+                       printf("\tQueueLimitSender = %s\n", QueueLimitSender);
+               if (QueueLimitRecipient != NULL)
+                       printf("\tQueueLimitRecipient = %s\n", QueueLimitRecipient);
+       }
+
        /* clear out old WorkQ */
        for (w = WorkQ; w != NULL; )
        {
        /* clear out old WorkQ */
        for (w = WorkQ; w != NULL; )
        {
@@ -459,14 +593,43 @@ orderq(doall)
        {
                FILE *cf;
                char lbuf[MAXNAME];
        {
                FILE *cf;
                char lbuf[MAXNAME];
+               extern bool strcontainedin();
 
                /* is this an interesting entry? */
                if (d->d_name[0] != 'q' || d->d_name[1] != 'f')
                        continue;
 
 
                /* is this an interesting entry? */
                if (d->d_name[0] != 'q' || d->d_name[1] != 'f')
                        continue;
 
+               if (QueueLimitId != NULL &&
+                   !strcontainedin(QueueLimitId, d->d_name))
+                       continue;
+
+               /*
+               **  Check queue name for plausibility.  This handles
+               **  both old and new type ids.
+               */
+
+               i = strlen(d->d_name);
+               if (i != 9 && i != 10)
+               {
+                       if (Verbose)
+                               printf("orderq: bogus qf name %s\n", d->d_name);
+#ifdef LOG
+                       if (LogLevel > 3)
+                               syslog(LOG_CRIT, "orderq: bogus qf name %s",
+                                       d->d_name);
+#endif
+                       if (strlen(d->d_name) >= MAXNAME)
+                               d->d_name[MAXNAME - 1] = '\0';
+                       strcpy(lbuf, d->d_name);
+                       lbuf[0] = 'Q';
+                       (void) rename(d->d_name, lbuf);
+                       continue;
+               }
+
                /* yes -- open control file (if not too many files) */
                if (++wn >= QUEUESIZE)
                        continue;
                /* yes -- open control file (if not too many files) */
                if (++wn >= QUEUESIZE)
                        continue;
+
                cf = fopen(d->d_name, "r");
                if (cf == NULL)
                {
                cf = fopen(d->d_name, "r");
                if (cf == NULL)
                {
@@ -488,9 +651,14 @@ orderq(doall)
 
                /* extract useful information */
                i = NEED_P | NEED_T;
 
                /* extract useful information */
                i = NEED_P | NEED_T;
+               if (QueueLimitSender != NULL)
+                       i |= NEED_S;
+               if (QueueLimitRecipient != NULL)
+                       i |= NEED_R;
                while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
                {
                        extern long atol();
                while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
                {
                        extern long atol();
+                       extern bool strcontainedin();
 
                        switch (lbuf[0])
                        {
 
                        switch (lbuf[0])
                        {
@@ -503,11 +671,24 @@ orderq(doall)
                                w->w_ctime = atol(&lbuf[1]);
                                i &= ~NEED_T;
                                break;
                                w->w_ctime = atol(&lbuf[1]);
                                i &= ~NEED_T;
                                break;
+
+                         case 'R':
+                               if (QueueLimitRecipient != NULL &&
+                                   strcontainedin(QueueLimitRecipient, &lbuf[1]))
+                                       i &= ~NEED_R;
+                               break;
+
+                         case 'S':
+                               if (QueueLimitSender != NULL &&
+                                   strcontainedin(QueueLimitSender, &lbuf[1]))
+                                       i &= ~NEED_S;
+                               break;
                        }
                }
                (void) fclose(cf);
 
                        }
                }
                (void) fclose(cf);
 
-               if (!doall && shouldqueue(w->w_pri))
+               if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) ||
+                   bitset(NEED_R|NEED_S, i))
                {
                        /* don't even bother sorting this job in */
                        wn--;
                {
                        /* don't even bother sorting this job in */
                        wn--;
@@ -566,8 +747,8 @@ workcmpf(a, b)
        register WORK *a;
        register WORK *b;
 {
        register WORK *a;
        register WORK *b;
 {
-       long pa = a->w_pri + a->w_ctime;
-       long pb = b->w_pri + b->w_ctime;
+       long pa = a->w_pri;
+       long pb = b->w_pri;
 
        if (pa == pb)
                return (0);
 
        if (pa == pb)
                return (0);
@@ -580,7 +761,13 @@ workcmpf(a, b)
 **  DOWORK -- do a work request.
 **
 **     Parameters:
 **  DOWORK -- do a work request.
 **
 **     Parameters:
-**             w -- the work request to be satisfied.
+**             id -- the ID of the job to run.
+**             forkflag -- if set, run this in background.
+**             requeueflag -- if set, reinstantiate the queue quickly.
+**                     This is used when expanding aliases in the queue.
+**                     If forkflag is also set, it doesn't wait for the
+**                     child.
+**             e - the envelope in which to run it.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -589,31 +776,23 @@ workcmpf(a, b)
 **             The work request is satisfied if possible.
 */
 
 **             The work request is satisfied if possible.
 */
 
-dowork(w)
-       register WORK *w;
+dowork(id, forkflag, requeueflag, e)
+       char *id;
+       bool forkflag;
+       bool requeueflag;
+       register ENVELOPE *e;
 {
        register int i;
 {
        register int i;
-       extern bool shouldqueue();
+       extern bool readqf();
 
        if (tTd(40, 1))
 
        if (tTd(40, 1))
-               printf("dowork: %s pri %ld\n", w->w_name, w->w_pri);
-
-       /*
-       **  Ignore jobs that are too expensive for the moment.
-       */
-
-       if (shouldqueue(w->w_pri))
-       {
-               if (Verbose)
-                       printf("\nSkipping %s\n", w->w_name + 2);
-               return;
-       }
+               printf("dowork(%s)\n", id);
 
        /*
        **  Fork for work.
        */
 
 
        /*
        **  Fork for work.
        */
 
-       if (ForkQueueRuns)
+       if (forkflag)
        {
                i = fork();
                if (i < 0)
        {
                i = fork();
                if (i < 0)
@@ -629,7 +808,6 @@ dowork(w)
 
        if (i == 0)
        {
 
        if (i == 0)
        {
-               FILE *qflock, *readqf();
                /*
                **  CHILD
                **      Lock the control file to avoid duplicate deliveries.
                /*
                **  CHILD
                **      Lock the control file to avoid duplicate deliveries.
@@ -640,44 +818,46 @@ dowork(w)
 
                /* set basic modes, etc. */
                (void) alarm(0);
 
                /* set basic modes, etc. */
                (void) alarm(0);
-               clearenvelope(CurEnv, FALSE);
-               QueueRun = TRUE;
-               ErrorMode = EM_MAIL;
-               CurEnv->e_id = &w->w_name[2];
+               clearenvelope(e, FALSE);
+               e->e_flags |= EF_QUEUERUN;
+               e->e_errormode = EM_MAIL;
+               e->e_id = id;
 # ifdef LOG
 # ifdef LOG
-               if (LogLevel > 11)
-                       syslog(LOG_DEBUG, "%s: dowork, pid=%d", CurEnv->e_id,
+               if (LogLevel > 76)
+                       syslog(LOG_DEBUG, "%s: dowork, pid=%d", e->e_id,
                               getpid());
                               getpid());
-# endif LOG
+# endif /* LOG */
 
                /* don't use the headers from sendmail.cf... */
 
                /* don't use the headers from sendmail.cf... */
-               CurEnv->e_header = NULL;
+               e->e_header = NULL;
 
 
-               /* read the queue control file */
-               /*  and lock the control file during processing */
-               if ((qflock=readqf(CurEnv, TRUE)) == NULL)
+               /* read the queue control file -- return if locked */
+               if (!readqf(e))
                {
                {
-                       if (ForkQueueRuns)
+                       if (tTd(40, 4))
+                               printf("readqf(%s) failed\n", e->e_id);
+                       if (forkflag)
                                exit(EX_OK);
                        else
                                return;
                }
 
                                exit(EX_OK);
                        else
                                return;
                }
 
-               CurEnv->e_flags |= EF_INQUEUE;
-               eatheader(CurEnv);
+               e->e_flags |= EF_INQUEUE;
+               eatheader(e, requeueflag);
+
+               if (requeueflag)
+                       queueup(e, TRUE, FALSE);
 
                /* do the delivery */
 
                /* do the delivery */
-               if (!bitset(EF_FATALERRS, CurEnv->e_flags))
-                       sendall(CurEnv, SM_DELIVER);
+               sendall(e, SM_DELIVER);
 
                /* finish up and exit */
 
                /* finish up and exit */
-               if (ForkQueueRuns)
+               if (forkflag)
                        finis();
                else
                        finis();
                else
-                       dropenvelope(CurEnv);
-               fclose(qflock);
+                       dropenvelope(e);
        }
        }
-       else
+       else if (!requeueflag)
        {
                /*
                **  Parent -- pick up results.
        {
                /*
                **  Parent -- pick up results.
@@ -692,137 +872,196 @@ dowork(w)
 **
 **     Parameters:
 **             e -- the envelope of the job to run.
 **
 **     Parameters:
 **             e -- the envelope of the job to run.
-**             full -- if set, read in all information.  Otherwise just
-**                     read in info needed for a queue print.
 **
 **     Returns:
 **
 **     Returns:
-**             FILE * pointing to flock()ed fd so it can be closed
-**             after the mail is delivered
+**             TRUE if it successfully read the queue file.
+**             FALSE otherwise.
 **
 **     Side Effects:
 **
 **     Side Effects:
-**             cf is read and created as the current job, as though
-**             we had been invoked by argument.
+**             The queue file is returned locked.
 */
 
 */
 
-FILE *
-readqf(e, full)
+bool
+readqf(e)
        register ENVELOPE *e;
        register ENVELOPE *e;
-       bool full;
 {
 {
-       char *qf;
        register FILE *qfp;
        register FILE *qfp;
-       char buf[MAXFIELD];
-       extern char *fgetfolded();
+       ADDRESS *ctladdr;
+       struct stat st;
+       char *bp;
+       char qf[20];
+       char buf[MAXLINE];
        extern long atol();
        extern long atol();
-       int gotctluser = 0;
-       int fd;
+       extern ADDRESS *setctluser();
 
        /*
        **  Read and process the file.
        */
 
 
        /*
        **  Read and process the file.
        */
 
-       qf = queuename(e, 'q');
-       qfp = fopen(qf, "r");
+       strcpy(qf, queuename(e, 'q'));
+       qfp = fopen(qf, "r+");
        if (qfp == NULL)
        {
        if (qfp == NULL)
        {
+               if (tTd(40, 8))
+                       printf("readqf(%s): fopen failure (%s)\n",
+                               qf, errstring(errno));
                if (errno != ENOENT)
                        syserr("readqf: no control file %s", qf);
                if (errno != ENOENT)
                        syserr("readqf: no control file %s", qf);
-               return NULL;
+               return FALSE;
        }
 
        }
 
-       if (flock(fileno(qfp), LOCK_EX|LOCK_NB) < 0)
+       /*
+       **  Check the queue file for plausibility to avoid attacks.
+       */
+
+       if (fstat(fileno(qfp), &st) < 0)
+       {
+               /* must have been being processed by someone else */
+               if (tTd(40, 8))
+                       printf("readqf(%s): fstat failure (%s)\n",
+                               qf, errstring(errno));
+               fclose(qfp);
+               return FALSE;
+       }
+
+       if (st.st_uid != geteuid() || (st.st_mode & 07777) != FileMode)
        {
 # ifdef LOG
        {
 # ifdef LOG
+               if (LogLevel > 0)
+               {
+                       syslog(LOG_ALERT, "%s: bogus queue file, uid=%d, mode=%o",
+                               e->e_id, st.st_uid, st.st_mode);
+               }
+# endif /* LOG */
+               if (tTd(40, 8))
+                       printf("readqf(%s): bogus file\n", qf);
+               fclose(qfp);
+               return FALSE;
+       }
+
+       if (!lockfile(fileno(qfp), qf, LOCK_EX|LOCK_NB))
+       {
                /* being processed by another queuer */
                /* being processed by another queuer */
+               if (tTd(40, 8))
+                       printf("readqf(%s): locked\n", qf);
                if (Verbose)
                if (Verbose)
-                       printf("%s: locked\n", CurEnv->e_id);
-# endif LOG
+                       printf("%s: locked\n", e->e_id);
+# ifdef LOG
+               if (LogLevel > 19)
+                       syslog(LOG_DEBUG, "%s: locked", e->e_id);
+# endif /* LOG */
                (void) fclose(qfp);
                (void) fclose(qfp);
-               return NULL;
+               return FALSE;
+       }
+
+       if (st.st_size == 0)
+       {
+               /* must be a bogus file -- just remove it */
+               (void) unlink(qf);
+               fclose(qfp);
+               return FALSE;
        }
 
        }
 
+       /* save this lock */
+       e->e_lockfp = qfp;
+
        /* do basic system initialization */
        /* do basic system initialization */
-       initsys();
+       initsys(e);
 
        FileName = qf;
        LineNumber = 0;
 
        FileName = qf;
        LineNumber = 0;
-       if (Verbose && full)
+       if (Verbose)
                printf("\nRunning %s\n", e->e_id);
                printf("\nRunning %s\n", e->e_id);
-       while (fgetfolded(buf, sizeof buf, qfp) != NULL)
+       ctladdr = NULL;
+       while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL)
        {
        {
+               register char *p;
+               struct stat st;
+
                if (tTd(40, 4))
                if (tTd(40, 4))
-                       printf("+++++ %s\n", buf);
-               switch (buf[0])
+                       printf("+++++ %s\n", bp);
+               switch (bp[0])
                {
                  case 'C':             /* specify controlling user */
                {
                  case 'C':             /* specify controlling user */
-                       setctluser(&buf[1]);
-                       gotctluser = 1;
+                       ctladdr = setctluser(&bp[1]);
                        break;
 
                  case 'R':             /* specify recipient */
                        break;
 
                  case 'R':             /* specify recipient */
-                       sendtolist(&buf[1], (ADDRESS *) NULL, &e->e_sendqueue);
+                       (void) sendtolist(&bp[1], ctladdr, &e->e_sendqueue, e);
                        break;
 
                  case 'E':             /* specify error recipient */
                        break;
 
                  case 'E':             /* specify error recipient */
-                       sendtolist(&buf[1], (ADDRESS *) NULL, &e->e_errorqueue);
+                       (void) sendtolist(&bp[1], ctladdr, &e->e_errorqueue, e);
                        break;
 
                  case 'H':             /* header */
                        break;
 
                  case 'H':             /* header */
-                       if (full)
-                               (void) chompheader(&buf[1], FALSE);
+                       (void) chompheader(&bp[1], FALSE, e);
                        break;
 
                  case 'M':             /* message */
                        break;
 
                  case 'M':             /* message */
-                       e->e_message = newstr(&buf[1]);
+                       e->e_message = newstr(&bp[1]);
                        break;
 
                  case 'S':             /* sender */
                        break;
 
                  case 'S':             /* sender */
-                       setsender(newstr(&buf[1]));
+                       setsender(newstr(&bp[1]), e, NULL, TRUE);
+                       break;
+
+                 case 'B':             /* body type */
+                       e->e_bodytype = newstr(&bp[1]);
                        break;
 
                  case 'D':             /* data file name */
                        break;
 
                  case 'D':             /* data file name */
-                       if (!full)
-                               break;
-                       e->e_df = newstr(&buf[1]);
+                       e->e_df = newstr(&bp[1]);
                        e->e_dfp = fopen(e->e_df, "r");
                        if (e->e_dfp == NULL)
                        e->e_dfp = fopen(e->e_df, "r");
                        if (e->e_dfp == NULL)
+                       {
                                syserr("readqf: cannot open %s", e->e_df);
                                syserr("readqf: cannot open %s", e->e_df);
+                               e->e_msgsize = -1;
+                       }
+                       else if (fstat(fileno(e->e_dfp), &st) >= 0)
+                               e->e_msgsize = st.st_size;
                        break;
 
                  case 'T':             /* init time */
                        break;
 
                  case 'T':             /* init time */
-                       e->e_ctime = atol(&buf[1]);
+                       e->e_ctime = atol(&bp[1]);
                        break;
 
                  case 'P':             /* message priority */
                        break;
 
                  case 'P':             /* message priority */
-                       e->e_msgpriority = atol(&buf[1]) + WkTimeFact;
+                       e->e_msgpriority = atol(&bp[1]) + WkTimeFact;
+                       break;
+
+                 case 'F':             /* flag bits */
+                       for (p = &bp[1]; *p != '\0'; p++)
+                       {
+                               switch (*p)
+                               {
+                                 case 'w':     /* warning sent */
+                                       e->e_flags |= EF_WARNING;
+                                       break;
+
+                                 case 'r':     /* response */
+                                       e->e_flags |= EF_RESPONSE;
+                                       break;
+                               }
+                       }
+                       break;
+
+                 case '$':             /* define macro */
+                       define(bp[1], newstr(&bp[2]), e);
                        break;
 
                  case '\0':            /* blank line; ignore */
                        break;
 
                  default:
                        break;
 
                  case '\0':            /* blank line; ignore */
                        break;
 
                  default:
-                       syserr("readqf(%s:%d): bad line \"%s\"", e->e_id,
-                               LineNumber, buf);
+                       syserr("readqf: bad line \"%s\"", e->e_id,
+                               LineNumber, bp);
                        break;
                }
                        break;
                }
-               /*
-               **  The `C' queue file command operates on the next line,
-               **  so we use "gotctluser" to maintain state as follows:
-               **      0 - no controlling user,
-               **      1 - controlling user has been set but not used,
-               **      2 - controlling user must be used on next iteration.
-               */
-               if (gotctluser == 1)
-                       gotctluser++;
-               else if (gotctluser == 2)
-               {
-                       clrctluser();
-                       gotctluser = 0;
-               }
-       }
 
 
-       /* clear controlling user in case we break out prematurely */
-       clrctluser();
+               if (bp != buf)
+                       free(bp);
+       }
 
        FileName = NULL;
 
 
        FileName = NULL;
 
@@ -836,7 +1075,7 @@ readqf(e, full)
                errno = 0;
                e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE;
        }
                errno = 0;
                e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE;
        }
-       return qfp;
+       return TRUE;
 }
 \f/*
 **  PRINTQUEUE -- print out a representation of the mail queue
 }
 \f/*
 **  PRINTQUEUE -- print out a representation of the mail queue
@@ -857,7 +1096,41 @@ printqueue()
        FILE *f;
        int nrequests;
        char buf[MAXLINE];
        FILE *f;
        int nrequests;
        char buf[MAXLINE];
-       char cbuf[MAXLINE];
+
+       /*
+       **  Check for permission to print the queue
+       */
+
+       if (bitset(PRIV_RESTRMAILQ, PrivacyFlags) && getuid() != 0)
+       {
+               struct stat st;
+# ifdef NGROUPS
+               int n;
+               int gidset[NGROUPS];
+# endif
+
+               if (stat(QueueDir, &st) < 0)
+               {
+                       syserr("Cannot stat %s", QueueDir);
+                       return;
+               }
+# ifdef NGROUPS
+               n = getgroups(NGROUPS, gidset);
+               while (--n >= 0)
+               {
+                       if (gidset[n] == st.st_gid)
+                               break;
+               }
+               if (n < 0)
+# else
+               if (getgid() != st.st_gid)
+# endif
+               {
+                       usrerr("510 You are not permitted to see the queue");
+                       setstat(EX_NOPERM);
+                       return;
+               }
+       }
 
        /*
        **  Read and order the queue.
 
        /*
        **  Read and order the queue.
@@ -876,22 +1149,23 @@ printqueue()
                return;
        }
 
                return;
        }
 
-       la = getla();   /* get load average */
+       CurrentLA = getla();    /* get load average */
 
        printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s");
        if (nrequests > QUEUESIZE)
                printf(", only %d printed", QUEUESIZE);
        if (Verbose)
 
        printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s");
        if (nrequests > QUEUESIZE)
                printf(", only %d printed", QUEUESIZE);
        if (Verbose)
-               printf(")\n--QID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n");
+               printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n");
        else
        else
-               printf(")\n--QID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n");
+               printf(")\n--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n");
        for (w = WorkQ; w != NULL; w = w->w_next)
        {
                struct stat st;
                auto time_t submittime = 0;
                long dfsize = -1;
        for (w = WorkQ; w != NULL; w = w->w_next)
        {
                struct stat st;
                auto time_t submittime = 0;
                long dfsize = -1;
+               int flags = 0;
                char message[MAXLINE];
                char message[MAXLINE];
-               extern bool shouldqueue();
+               char bodytype[MAXNAME];
 
                f = fopen(w->w_name, "r");
                if (f == NULL)
 
                f = fopen(w->w_name, "r");
                if (f == NULL)
@@ -899,58 +1173,68 @@ printqueue()
                        errno = 0;
                        continue;
                }
                        errno = 0;
                        continue;
                }
-               printf("%7s", w->w_name + 2);
-               if (flock(fileno(f), LOCK_SH|LOCK_NB) < 0)
+               printf("%8s", w->w_name + 2);
+               if (!lockfile(fileno(f), w->w_name, LOCK_SH|LOCK_NB))
                        printf("*");
                        printf("*");
-               else if (shouldqueue(w->w_pri))
+               else if (shouldqueue(w->w_pri, w->w_ctime))
                        printf("X");
                else
                        printf(" ");
                errno = 0;
 
                        printf("X");
                else
                        printf(" ");
                errno = 0;
 
-               message[0] = '\0';
-               cbuf[0] = '\0';
+               message[0] = bodytype[0] = '\0';
                while (fgets(buf, sizeof buf, f) != NULL)
                {
                while (fgets(buf, sizeof buf, f) != NULL)
                {
+                       register int i;
+                       register char *p;
+
                        fixcrlf(buf, TRUE);
                        switch (buf[0])
                        {
                          case 'M':     /* error message */
                        fixcrlf(buf, TRUE);
                        switch (buf[0])
                        {
                          case 'M':     /* error message */
-                               (void) strcpy(message, &buf[1]);
+                               if ((i = strlen(&buf[1])) >= sizeof message)
+                                       i = sizeof message - 1;
+                               bcopy(&buf[1], message, i);
+                               message[i] = '\0';
+                               break;
+
+                         case 'B':     /* body type */
+                               if ((i = strlen(&buf[1])) >= sizeof bodytype)
+                                       i = sizeof bodytype - 1;
+                               bcopy(&buf[1], bodytype, i);
+                               bodytype[i] = '\0';
                                break;
 
                          case 'S':     /* sender name */
                                if (Verbose)
                                break;
 
                          case 'S':     /* sender name */
                                if (Verbose)
-                                       printf("%8ld %10ld %.12s %.38s", dfsize,
-                                           w->w_pri, ctime(&submittime) + 4,
+                                       printf("%8ld %10ld%c%.12s %.38s",
+                                           dfsize,
+                                           w->w_pri,
+                                           bitset(EF_WARNING, flags) ? '+' : ' ',
+                                           ctime(&submittime) + 4,
                                            &buf[1]);
                                else
                                        printf("%8ld %.16s %.45s", dfsize,
                                            ctime(&submittime), &buf[1]);
                                            &buf[1]);
                                else
                                        printf("%8ld %.16s %.45s", dfsize,
                                            ctime(&submittime), &buf[1]);
-                               if (message[0] != '\0')
-                                       printf("\n\t\t (%.60s)", message);
+                               if (message[0] != '\0' || bodytype[0] != '\0')
+                               {
+                                       printf("\n    %10.10s", bodytype);
+                                       if (message[0] != '\0')
+                                               printf("   (%.60s)", message);
+                               }
                                break;
                                break;
+
                          case 'C':     /* controlling user */
                          case 'C':     /* controlling user */
-                               if (strlen(buf) < MAXLINE-3)    /* sanity */
-                                       (void) strcat(buf, ") ");
-                               cbuf[0] = cbuf[1] = '(';
-                               (void) strncpy(&cbuf[2], &buf[1], MAXLINE-1);
-                               cbuf[MAXLINE-1] = '\0';
+                               if (Verbose)
+                                       printf("\n\t\t\t\t      (---%.34s---)",
+                                               &buf[1]);
                                break;
 
                          case 'R':     /* recipient name */
                                break;
 
                          case 'R':     /* recipient name */
-                               if (cbuf[0] != '\0') {
-                                       /* prepend controlling user to `buf' */
-                                       (void) strncat(cbuf, &buf[1],
-                                                     MAXLINE-strlen(cbuf));
-                                       cbuf[MAXLINE-1] = '\0';
-                                       (void) strcpy(buf, cbuf);
-                                       cbuf[0] = '\0';
-                               }
                                if (Verbose)
                                if (Verbose)
-                                       printf("\n\t\t\t\t\t %.38s", &buf[1]);
+                                       printf("\n\t\t\t\t\t  %.38s", &buf[1]);
                                else
                                else
-                                       printf("\n\t\t\t\t  %.45s", &buf[1]);
+                                       printf("\n\t\t\t\t   %.45s", &buf[1]);
                                break;
 
                          case 'T':     /* creation time */
                                break;
 
                          case 'T':     /* creation time */
@@ -961,6 +1245,17 @@ printqueue()
                                if (stat(&buf[1], &st) >= 0)
                                        dfsize = st.st_size;
                                break;
                                if (stat(&buf[1], &st) >= 0)
                                        dfsize = st.st_size;
                                break;
+
+                         case 'F':     /* flag bits */
+                               for (p = &buf[1]; *p != '\0'; p++)
+                               {
+                                       switch (*p)
+                                       {
+                                         case 'w':
+                                               flags |= EF_WARNING;
+                                               break;
+                                       }
+                               }
                        }
                }
                if (submittime == (time_t) 0)
                        }
                }
                if (submittime == (time_t) 0)
@@ -970,7 +1265,7 @@ printqueue()
        }
 }
 
        }
 }
 
-# endif QUEUE
+# endif /* QUEUE */
 \f/*
 **  QUEUENAME -- build a file name in the queue directory for this envelope.
 **
 \f/*
 **  QUEUENAME -- build a file name in the queue directory for this envelope.
 **
@@ -987,20 +1282,23 @@ printqueue()
 **             a pointer to the new file name (in a static buffer).
 **
 **     Side Effects:
 **             a pointer to the new file name (in a static buffer).
 **
 **     Side Effects:
-**             Will create the qf file if no id code is
-**             already assigned.  This will cause the envelope
-**             to be modified.
+**             If no id code is already assigned, queuename will
+**             assign an id code, create a qf file, and leave a
+**             locked, open-for-write file pointer in the envelope.
 */
 
 char *
 queuename(e, type)
        register ENVELOPE *e;
 */
 
 char *
 queuename(e, type)
        register ENVELOPE *e;
-       char type;
+       int type;
 {
 {
-       static char buf[MAXNAME];
        static int pid = -1;
        static int pid = -1;
-       char c1 = 'A';
-       char c2 = 'A';
+       static char c0;
+       static char c1;
+       static char c2;
+       time_t now;
+       struct tm *tm;
+       static char buf[MAXNAME];
 
        if (e->e_id == NULL)
        {
 
        if (e->e_id == NULL)
        {
@@ -1011,10 +1309,13 @@ queuename(e, type)
                {
                        /* new process -- start back at "AA" */
                        pid = getpid();
                {
                        /* new process -- start back at "AA" */
                        pid = getpid();
+                       now = curtime();
+                       tm = localtime(&now);
+                       c0 = 'A' + tm->tm_hour;
                        c1 = 'A';
                        c2 = 'A' - 1;
                }
                        c1 = 'A';
                        c2 = 'A' - 1;
                }
-               (void) sprintf(qf, "qfAA%05d", pid);
+               (void) sprintf(qf, "qf%cAA%05d", c0, pid);
 
                while (c1 < '~' || c2 < 'Z')
                {
 
                while (c1 < '~' || c2 < 'Z')
                {
@@ -1025,22 +1326,28 @@ queuename(e, type)
                                c1++;
                                c2 = 'A' - 1;
                        }
                                c1++;
                                c2 = 'A' - 1;
                        }
-                       qf[2] = c1;
-                       qf[3] = ++c2;
+                       qf[3] = c1;
+                       qf[4] = ++c2;
                        if (tTd(7, 20))
                                printf("queuename: trying \"%s\"\n", qf);
 
                        i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode);
                        if (tTd(7, 20))
                                printf("queuename: trying \"%s\"\n", qf);
 
                        i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode);
-                       if (i < 0) {
-                               if (errno != EEXIST) {
-                                       syserr("queuename: Cannot create \"%s\" in \"%s\"",
-                                               qf, QueueDir);
-                                       exit(EX_UNAVAILABLE);
-                               }
-                       } else {
-                               (void) close(i);
+                       if (i < 0)
+                       {
+                               if (errno == EEXIST)
+                                       continue;
+                               syserr("queuename: Cannot create \"%s\" in \"%s\"",
+                                       qf, QueueDir);
+                               exit(EX_UNAVAILABLE);
+                       }
+                       if (lockfile(i, qf, LOCK_EX|LOCK_NB))
+                       {
+                               e->e_lockfp = fdopen(i, "w");
                                break;
                        }
                                break;
                        }
+
+                       /* a reader got the file; abandon it and try again */
+                       (void) close(i);
                }
                if (c1 >= '~' && c2 >= 'Z')
                {
                }
                if (c1 >= '~' && c2 >= 'Z')
                {
@@ -1053,9 +1360,9 @@ queuename(e, type)
                if (tTd(7, 1))
                        printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
 # ifdef LOG
                if (tTd(7, 1))
                        printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
 # ifdef LOG
-               if (LogLevel > 16)
+               if (LogLevel > 93)
                        syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
                        syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
-# endif LOG
+# endif /* LOG */
        }
 
        if (type == '\0')
        }
 
        if (type == '\0')
@@ -1081,155 +1388,86 @@ queuename(e, type)
 unlockqueue(e)
        ENVELOPE *e;
 {
 unlockqueue(e)
        ENVELOPE *e;
 {
+       if (tTd(51, 4))
+               printf("unlockqueue(%s)\n", e->e_id);
+
+       /* if there is a lock file in the envelope, close it */
+       if (e->e_lockfp != NULL)
+               xfclose(e->e_lockfp, "unlockqueue", e->e_id);
+       e->e_lockfp = NULL;
+
+       /* don't create a queue id if we don't already have one */
+       if (e->e_id == NULL)
+               return;
+
        /* remove the transcript */
 # ifdef LOG
        /* remove the transcript */
 # ifdef LOG
-       if (LogLevel > 19)
+       if (LogLevel > 87)
                syslog(LOG_DEBUG, "%s: unlock", e->e_id);
                syslog(LOG_DEBUG, "%s: unlock", e->e_id);
-# endif LOG
-       if (!tTd(51, 4))
+# endif /* LOG */
+       if (!tTd(51, 104))
                xunlink(queuename(e, 'x'));
 
 }
 \f/*
                xunlink(queuename(e, 'x'));
 
 }
 \f/*
-**  GETCTLUSER -- return controlling user if mailing to prog or file
+**  SETCTLUSER -- create a controlling address
 **
 **
-**     Check for a "|" or "/" at the beginning of the address.  If
-**     found, return a controlling username.
+**     Create a fake "address" given only a local login name; this is
+**     used as a "controlling user" for future recipient addresses.
 **
 **     Parameters:
 **
 **     Parameters:
-**             a - the address to check out
+**             user -- the user name of the controlling user.
 **
 **     Returns:
 **
 **     Returns:
-**             Either NULL, if we werent mailing to a program or file,
-**             or a controlling user name (possibly in getpwuid's
-**             static buffer).
+**             An address descriptor for the controlling user.
 **
 **     Side Effects:
 **             none.
 */
 
 **
 **     Side Effects:
 **             none.
 */
 
-char *
-getctluser(a)
-       ADDRESS *a;
+ADDRESS *
+setctluser(user)
+       char *user;
 {
 {
-       extern ADDRESS *getctladdr();
+       register ADDRESS *a;
        struct passwd *pw;
        struct passwd *pw;
-       char *retstr;
+       char *p;
 
        /*
 
        /*
-       **  Get unquoted user for file, program or user.name check.
-       **  N.B. remove this code block to always emit controlling
-       **  addresses (at the expense of backward compatibility).
+       **  See if this clears our concept of controlling user.
        */
 
        */
 
-       {
-               char buf[MAXNAME];
-               (void) strncpy(buf, a->q_paddr, MAXNAME);
-               buf[MAXNAME-1] = '\0';
-               stripquotes(buf, TRUE);
-
-               if (buf[0] != '|' && buf[0] != '/')
-                       return((char *)NULL);
-       }
-
-       a = getctladdr(a);              /* find controlling address */
-
-       if (a != NULL && a->q_uid != 0 && (pw = getpwuid(a->q_uid)) != NULL)
-               retstr = pw->pw_name;
-       else                            /* use default user */
-               retstr = DefUser;
-
-       if (tTd(40, 5))
-               printf("Set controlling user for `%s' to `%s'\n",
-                      (a == NULL)? "<null>": a->q_paddr, retstr);
-
-       return(retstr);
-}
-\f/*
-**  SETCTLUSER - sets `CtlUser' to controlling user
-**  CLRCTLUSER - clears controlling user (no params, nothing returned)
-**
-**     These routines manipulate `CtlUser'.
-**
-**     Parameters:
-**             str  - controlling user as passed to setctluser()
-**
-**     Returns:
-**             None.
-**
-**     Side Effects:
-**             `CtlUser' is changed.
-*/
-
-static char CtlUser[MAXNAME];
-
-setctluser(str)
-register char *str;
-{
-       (void) strncpy(CtlUser, str, MAXNAME);
-       CtlUser[MAXNAME-1] = '\0';
-}
-
-clrctluser()
-{
-       CtlUser[0] = '\0';
-}
-
-\f/*
-**  SETCTLADDR -- create a controlling address
-**
-**     If global variable `CtlUser' is set and we are given a valid
-**     address, make that address a controlling address; change the
-**     `q_uid', `q_gid', and `q_ruser' fields and set QGOODUID.
-**
-**     Parameters:
-**             a - address for which control uid/gid info may apply
-**
-**     Returns:
-**             None.   
-**
-**     Side Effects:
-**             Fills in uid/gid fields in address and sets QGOODUID
-**             flag if appropriate.
-*/
-
-setctladdr(a)
-       ADDRESS *a;
-{
-       struct passwd *pw;
+       if (user == NULL)
+               user = "";
 
        /*
 
        /*
-       **  If there is no current controlling user, or we were passed a
-       **  NULL addr ptr or we already have a controlling user, return.
+       **  Set up addr fields for controlling user.
        */
 
        */
 
-       if (CtlUser[0] == '\0' || a == NULL || a->q_ruser)
-               return;
+       a = (ADDRESS *) xalloc(sizeof *a);
+       bzero((char *) a, sizeof *a);
 
 
-       /*
-       **  Set up addr fields for controlling user.  If `CtlUser' is no
-       **  longer valid, use the default user/group.
-       */
-
-       if ((pw = getpwnam(CtlUser)) != NULL)
+       p = strchr(user, ':');
+       if (p != NULL)
+               *p++ = '\0';
+       if (*user != '\0' && (pw = getpwnam(user)) != NULL)
        {
        {
-               if (a->q_home)
-                       free(a->q_home);
                a->q_home = newstr(pw->pw_dir);
                a->q_uid = pw->pw_uid;
                a->q_gid = pw->pw_gid;
                a->q_home = newstr(pw->pw_dir);
                a->q_uid = pw->pw_uid;
                a->q_gid = pw->pw_gid;
-               a->q_ruser = newstr(CtlUser);
+               a->q_user = newstr(user);
+               a->q_flags |= QGOODUID;
        }
        else
        {
        }
        else
        {
-               a->q_uid = DefUid;
-               a->q_gid = DefGid;
-               a->q_ruser = newstr(DefUser);
+               a->q_user = newstr(DefUser);
        }
 
        }
 
-       a->q_flags |= QGOODUID;         /* flag as a "ctladdr"  */
-
-       if (tTd(40, 5))
-               printf("Restored controlling user for `%s' to `%s'\n",
-                      a->q_paddr, a->q_ruser);
+       a->q_flags |= QPRIMARY;         /* flag as a "ctladdr"  */
+       a->q_mailer = LocalMailer;
+       if (p == NULL)
+               a->q_paddr = a->q_user;
+       else
+               a->q_paddr = newstr(p);
+       return a;
 }
 }
index bd2bad7..8a53885 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)readcf.c   5.22 (Berkeley) 3/12/91";
+static char sccsid[] = "@(#)readcf.c   8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
+#ifdef NAMED_BIND
+# include <arpa/nameser.h>
+# include <resolv.h>
+#endif
 
 /*
 **  READCF -- read control file.
 
 /*
 **  READCF -- read control file.
@@ -64,9 +68,16 @@ static char sccsid[] = "@(#)readcf.c 5.22 (Berkeley) 3/12/91";
 **                             Args specify mailer parameters.
 **             Oxvalue         Set option x to value.
 **             Pname=value     Set precedence name to value.
 **                             Args specify mailer parameters.
 **             Oxvalue         Set option x to value.
 **             Pname=value     Set precedence name to value.
+**             Vversioncode    Version level of configuration syntax.
+**             Kmapname mapclass arguments....
+**                             Define keyed lookup of a given class.
+**                             Arguments are class dependent.
 **
 **     Parameters:
 **             cfname -- control file name.
 **
 **     Parameters:
 **             cfname -- control file name.
+**             safe -- TRUE if this is the system config file;
+**                     FALSE otherwise.
+**             e -- the main envelope.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -75,37 +86,106 @@ static char sccsid[] = "@(#)readcf.c       5.22 (Berkeley) 3/12/91";
 **             Builds several internal tables.
 */
 
 **             Builds several internal tables.
 */
 
-readcf(cfname)
+readcf(cfname, safe, e)
        char *cfname;
        char *cfname;
+       bool safe;
+       register ENVELOPE *e;
 {
        FILE *cf;
        int ruleset = 0;
        char *q;
 {
        FILE *cf;
        int ruleset = 0;
        char *q;
-       char **pv;
        struct rewrite *rwp = NULL;
        struct rewrite *rwp = NULL;
+       char *bp;
+       int nfuzzy;
        char buf[MAXLINE];
        register char *p;
        char buf[MAXLINE];
        register char *p;
-       extern char **prescan();
        extern char **copyplist();
        extern char **copyplist();
+       struct stat statb;
        char exbuf[MAXLINE];
        char pvpbuf[PSBUFSIZE];
        char exbuf[MAXLINE];
        char pvpbuf[PSBUFSIZE];
-       extern char *fgetfolded();
        extern char *munchstring();
        extern char *munchstring();
+       extern void makemapentry();
+
+       FileName = cfname;
+       LineNumber = 0;
 
        cf = fopen(cfname, "r");
        if (cf == NULL)
        {
 
        cf = fopen(cfname, "r");
        if (cf == NULL)
        {
-               syserr("cannot open %s", cfname);
+               syserr("cannot open");
                exit(EX_OSFILE);
        }
 
                exit(EX_OSFILE);
        }
 
-       FileName = cfname;
-       LineNumber = 0;
-       while (fgetfolded(buf, sizeof buf, cf) != NULL)
+       if (fstat(fileno(cf), &statb) < 0)
+       {
+               syserr("cannot fstat");
+               exit(EX_OSFILE);
+       }
+
+       if (!S_ISREG(statb.st_mode))
+       {
+               syserr("not a plain file");
+               exit(EX_OSFILE);
+       }
+
+       if (OpMode != MD_TEST && bitset(S_IWGRP|S_IWOTH, statb.st_mode))
+       {
+               if (OpMode == MD_DAEMON || OpMode == MD_FREEZE)
+                       fprintf(stderr, "%s: WARNING: dangerous write permissions\n",
+                               FileName);
+#ifdef LOG
+               if (LogLevel > 0)
+                       syslog(LOG_CRIT, "%s: WARNING: dangerous write permissions",
+                               FileName);
+#endif
+       }
+
+#ifdef XLA
+       xla_zero();
+#endif
+
+       while ((bp = fgetfolded(buf, sizeof buf, cf)) != NULL)
        {
        {
-               /* map $ into \001 (ASCII SOH) for macro expansion */
-               for (p = buf; *p != '\0'; p++)
+               if (bp[0] == '#')
                {
                {
+                       if (bp != buf)
+                               free(bp);
+                       continue;
+               }
+
+               /* map $ into \201 for macro expansion */
+               for (p = bp; *p != '\0'; p++)
+               {
+                       if (*p == '#' && p > bp && ConfigLevel >= 3)
+                       {
+                               /* this is an on-line comment */
+                               register char *e;
+
+                               switch (*--p & 0377)
+                               {
+                                 case MACROEXPAND:
+                                       /* it's from $# -- let it go through */
+                                       p++;
+                                       break;
+
+                                 case '\\':
+                                       /* it's backslash escaped */
+                                       (void) strcpy(p, p + 1);
+                                       break;
+
+                                 default:
+                                       /* delete preceeding white space */
+                                       while (isascii(*p) && isspace(*p) && p > bp)
+                                               p--;
+                                       if ((e = strchr(++p, '\n')) != NULL)
+                                               (void) strcpy(p, e);
+                                       else
+                                               p[0] = p[1] = '\0';
+                                       break;
+                               }
+                               continue;
+                       }
+
                        if (*p != '$')
                                continue;
 
                        if (*p != '$')
                                continue;
 
@@ -117,23 +197,23 @@ readcf(cfname)
                        }
 
                        /* convert to macro expansion character */
                        }
 
                        /* convert to macro expansion character */
-                       *p = '\001';
+                       *p = MACROEXPAND;
                }
 
                /* interpret this line */
                }
 
                /* interpret this line */
-               switch (buf[0])
+               switch (bp[0])
                {
                  case '\0':
                  case '#':             /* comment */
                        break;
 
                  case 'R':             /* rewriting rule */
                {
                  case '\0':
                  case '#':             /* comment */
                        break;
 
                  case 'R':             /* rewriting rule */
-                       for (p = &buf[1]; *p != '\0' && *p != '\t'; p++)
+                       for (p = &bp[1]; *p != '\0' && *p != '\t'; p++)
                                continue;
 
                        if (*p == '\0')
                        {
                                continue;
 
                        if (*p == '\0')
                        {
-                               syserr("invalid rewrite line \"%s\"", buf);
+                               syserr("invalid rewrite line \"%s\"", bp);
                                break;
                        }
 
                                break;
                        }
 
@@ -152,11 +232,83 @@ readcf(cfname)
 
                        /* expand and save the LHS */
                        *p = '\0';
 
                        /* expand and save the LHS */
                        *p = '\0';
-                       expand(&buf[1], exbuf, &exbuf[sizeof exbuf], CurEnv);
-                       rwp->r_lhs = prescan(exbuf, '\t', pvpbuf);
+                       expand(&bp[1], exbuf, &exbuf[sizeof exbuf], e);
+                       rwp->r_lhs = prescan(exbuf, '\t', pvpbuf, NULL);
+                       nfuzzy = 0;
                        if (rwp->r_lhs != NULL)
                        if (rwp->r_lhs != NULL)
+                       {
+                               register char **ap;
+
                                rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
 
                                rwp->r_lhs = copyplist(rwp->r_lhs, TRUE);
 
+                               /* count the number of fuzzy matches in LHS */
+                               for (ap = rwp->r_lhs; *ap != NULL; ap++)
+                               {
+                                       char *botch;
+
+                                       botch = NULL;
+                                       switch (**ap & 0377)
+                                       {
+                                         case MATCHZANY:
+                                         case MATCHANY:
+                                         case MATCHONE:
+                                         case MATCHCLASS:
+                                         case MATCHNCLASS:
+                                               nfuzzy++;
+                                               break;
+
+                                         case MATCHREPL:
+                                               botch = "$0-$9";
+                                               break;
+
+                                         case CANONNET:
+                                               botch = "$#";
+                                               break;
+
+                                         case CANONUSER:
+                                               botch = "$:";
+                                               break;
+
+                                         case CALLSUBR:
+                                               botch = "$>";
+                                               break;
+
+                                         case CONDIF:
+                                               botch = "$?";
+                                               break;
+
+                                         case CONDELSE:
+                                               botch = "$|";
+                                               break;
+
+                                         case CONDFI:
+                                               botch = "$.";
+                                               break;
+
+                                         case HOSTBEGIN:
+                                               botch = "$[";
+                                               break;
+
+                                         case HOSTEND:
+                                               botch = "$]";
+                                               break;
+
+                                         case LOOKUPBEGIN:
+                                               botch = "$(";
+                                               break;
+
+                                         case LOOKUPEND:
+                                               botch = "$)";
+                                               break;
+                                       }
+                                       if (botch != NULL)
+                                               syserr("Inappropriate use of %s on LHS",
+                                                       botch);
+                               }
+                       }
+                       else
+                               syserr("R line: null LHS");
+
                        /* expand and save the RHS */
                        while (*++p == '\t')
                                continue;
                        /* expand and save the RHS */
                        while (*++p == '\t')
                                continue;
@@ -164,14 +316,62 @@ readcf(cfname)
                        while (*p != '\0' && *p != '\t')
                                p++;
                        *p = '\0';
                        while (*p != '\0' && *p != '\t')
                                p++;
                        *p = '\0';
-                       expand(q, exbuf, &exbuf[sizeof exbuf], CurEnv);
-                       rwp->r_rhs = prescan(exbuf, '\t', pvpbuf);
+                       expand(q, exbuf, &exbuf[sizeof exbuf], e);
+                       rwp->r_rhs = prescan(exbuf, '\t', pvpbuf, NULL);
                        if (rwp->r_rhs != NULL)
                        if (rwp->r_rhs != NULL)
+                       {
+                               register char **ap;
+
                                rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);
                                rwp->r_rhs = copyplist(rwp->r_rhs, TRUE);
+
+                               /* check no out-of-bounds replacements */
+                               nfuzzy += '0';
+                               for (ap = rwp->r_rhs; *ap != NULL; ap++)
+                               {
+                                       char *botch;
+
+                                       botch = NULL;
+                                       switch (**ap & 0377)
+                                       {
+                                         case MATCHREPL:
+                                               if ((*ap)[1] <= '0' || (*ap)[1] > nfuzzy)
+                                               {
+                                                       syserr("replacement $%c out of bounds",
+                                                               (*ap)[1]);
+                                               }
+                                               break;
+
+                                         case MATCHZANY:
+                                               botch = "$*";
+                                               break;
+
+                                         case MATCHANY:
+                                               botch = "$+";
+                                               break;
+
+                                         case MATCHONE:
+                                               botch = "$-";
+                                               break;
+
+                                         case MATCHCLASS:
+                                               botch = "$=";
+                                               break;
+
+                                         case MATCHNCLASS:
+                                               botch = "$~";
+                                               break;
+                                       }
+                                       if (botch != NULL)
+                                               syserr("Inappropriate use of %s on RHS",
+                                                       botch);
+                               }
+                       }
+                       else
+                               syserr("R line: null RHS");
                        break;
 
                  case 'S':             /* select rewriting set */
                        break;
 
                  case 'S':             /* select rewriting set */
-                       ruleset = atoi(&buf[1]);
+                       ruleset = atoi(&bp[1]);
                        if (ruleset >= MAXRWSETS || ruleset < 0)
                        {
                                syserr("bad ruleset %d (%d max)", ruleset, MAXRWSETS);
                        if (ruleset >= MAXRWSETS || ruleset < 0)
                        {
                                syserr("bad ruleset %d (%d max)", ruleset, MAXRWSETS);
@@ -181,58 +381,68 @@ readcf(cfname)
                        break;
 
                  case 'D':             /* macro definition */
                        break;
 
                  case 'D':             /* macro definition */
-                       define(buf[1], newstr(munchstring(&buf[2])), CurEnv);
+                       define(bp[1], newstr(munchstring(&bp[2], NULL)), e);
                        break;
 
                  case 'H':             /* required header line */
                        break;
 
                  case 'H':             /* required header line */
-                       (void) chompheader(&buf[1], TRUE);
+                       (void) chompheader(&bp[1], TRUE, e);
                        break;
 
                  case 'C':             /* word class */
                        break;
 
                  case 'C':             /* word class */
-                 case 'F':             /* word class from file */
-                       /* read list of words from argument or file */
-                       if (buf[0] == 'F')
-                       {
-                               /* read from file */
-                               for (p = &buf[2]; *p != '\0' && !isspace(*p); p++)
-                                       continue;
-                               if (*p == '\0')
-                                       p = "%s";
-                               else
-                               {
-                                       *p = '\0';
-                                       while (isspace(*++p))
-                                               continue;
-                               }
-                               fileclass(buf[1], &buf[2], p);
-                               break;
-                       }
-
                        /* scan the list of words and set class for all */
                        /* scan the list of words and set class for all */
-                       for (p = &buf[2]; *p != '\0'; )
+                       for (p = &bp[2]; *p != '\0'; )
                        {
                                register char *wd;
                                char delim;
 
                        {
                                register char *wd;
                                char delim;
 
-                               while (*p != '\0' && isspace(*p))
+                               while (*p != '\0' && isascii(*p) && isspace(*p))
                                        p++;
                                wd = p;
                                        p++;
                                wd = p;
-                               while (*p != '\0' && !isspace(*p))
+                               while (*p != '\0' && !(isascii(*p) && isspace(*p)))
                                        p++;
                                delim = *p;
                                *p = '\0';
                                if (wd[0] != '\0')
                                        p++;
                                delim = *p;
                                *p = '\0';
                                if (wd[0] != '\0')
-                                       setclass(buf[1], wd);
+                               {
+                                       if (tTd(37, 2))
+                                               printf("setclass(%c, %s)\n",
+                                                       bp[1], wd);
+                                       setclass(bp[1], wd);
+                               }
                                *p = delim;
                        }
                        break;
 
                                *p = delim;
                        }
                        break;
 
+                 case 'F':             /* word class from file */
+                       /* read list of words from argument or file */
+                       /* read from file */
+                       for (p = &bp[2];
+                            *p != '\0' && !(isascii(*p) && isspace(*p));
+                            p++)
+                               continue;
+                       if (*p == '\0')
+                               p = "%s";
+                       else
+                       {
+                               *p = '\0';
+                               while (isascii(*++p) && isspace(*p))
+                                       continue;
+                       }
+                       fileclass(bp[1], &bp[2], p, safe);
+                       break;
+
+#ifdef XLA
+                 case 'L':             /* extended load average description */
+                       xla_init(&bp[1]);
+                       break;
+#endif
+
                  case 'M':             /* define mailer */
                  case 'M':             /* define mailer */
-                       makemailer(&buf[1]);
+                       makemailer(&bp[1]);
                        break;
 
                  case 'O':             /* set option */
                        break;
 
                  case 'O':             /* set option */
-                       setoption(buf[1], &buf[2], TRUE, FALSE);
+                       setoption(bp[1], &bp[2], safe, FALSE, e);
                        break;
 
                  case 'P':             /* set precedence */
                        break;
 
                  case 'P':             /* set precedence */
@@ -241,46 +451,51 @@ readcf(cfname)
                                toomany('P', MAXPRIORITIES);
                                break;
                        }
                                toomany('P', MAXPRIORITIES);
                                break;
                        }
-                       for (p = &buf[1]; *p != '\0' && *p != '=' && *p != '\t'; p++)
+                       for (p = &bp[1]; *p != '\0' && *p != '=' && *p != '\t'; p++)
                                continue;
                        if (*p == '\0')
                                goto badline;
                        *p = '\0';
                                continue;
                        if (*p == '\0')
                                goto badline;
                        *p = '\0';
-                       Priorities[NumPriorities].pri_name = newstr(&buf[1]);
+                       Priorities[NumPriorities].pri_name = newstr(&bp[1]);
                        Priorities[NumPriorities].pri_val = atoi(++p);
                        NumPriorities++;
                        break;
 
                  case 'T':             /* trusted user(s) */
                        Priorities[NumPriorities].pri_val = atoi(++p);
                        NumPriorities++;
                        break;
 
                  case 'T':             /* trusted user(s) */
-                       p = &buf[1];
-                       while (*p != '\0')
-                       {
-                               while (isspace(*p))
-                                       p++;
-                               q = p;
-                               while (*p != '\0' && !isspace(*p))
-                                       p++;
-                               if (*p != '\0')
-                                       *p++ = '\0';
-                               if (*q == '\0')
-                                       continue;
-                               for (pv = TrustedUsers; *pv != NULL; pv++)
-                                       continue;
-                               if (pv >= &TrustedUsers[MAXTRUST])
-                               {
-                                       toomany('T', MAXTRUST);
-                                       break;
-                               }
-                               *pv = newstr(q);
-                       }
+                       /* this option is obsolete, but will be ignored */
+                       break;
+
+                 case 'V':             /* configuration syntax version */
+                       ConfigLevel = atoi(&bp[1]);
+                       break;
+
+                 case 'K':
+                       makemapentry(&bp[1]);
                        break;
 
                  default:
                  badline:
                        break;
 
                  default:
                  badline:
-                       syserr("unknown control line \"%s\"", buf);
+                       syserr("unknown control line \"%s\"", bp);
                }
                }
+               if (bp != buf)
+                       free(bp);
        }
        }
+       if (ferror(cf))
+       {
+               syserr("I/O read error", cfname);
+               exit(EX_OSFILE);
+       }
+       fclose(cf);
        FileName = NULL;
        FileName = NULL;
+
+       if (stab("host", ST_MAP, ST_FIND) == NULL)
+       {
+               /* user didn't initialize: set up host map */
+               strcpy(buf, "host host");
+               if (ConfigLevel >= 2)
+                       strcat(buf, " -a.");
+               makemapentry(buf);
+       }
 }
 \f/*
 **  TOOMANY -- signal too many of some option
 }
 \f/*
 **  TOOMANY -- signal too many of some option
@@ -319,18 +534,35 @@ toomany(id, maxcnt)
 **                     the named class.
 */
 
 **                     the named class.
 */
 
-fileclass(class, filename, fmt)
+fileclass(class, filename, fmt, safe)
        int class;
        char *filename;
        char *fmt;
        int class;
        char *filename;
        char *fmt;
+       bool safe;
 {
        FILE *f;
 {
        FILE *f;
+       struct stat stbuf;
        char buf[MAXLINE];
 
        char buf[MAXLINE];
 
+       if (stat(filename, &stbuf) < 0)
+       {
+               syserr("fileclass: cannot stat %s", filename);
+               return;
+       }
+       if (!S_ISREG(stbuf.st_mode))
+       {
+               syserr("fileclass: %s not a regular file", filename);
+               return;
+       }
+       if (!safe && access(filename, R_OK) < 0)
+       {
+               syserr("fileclass: access denied on %s", filename);
+               return;
+       }
        f = fopen(filename, "r");
        if (f == NULL)
        {
        f = fopen(filename, "r");
        if (f == NULL)
        {
-               syserr("cannot open %s", filename);
+               syserr("fileclass: cannot open %s", filename);
                return;
        }
 
                return;
        }
 
@@ -344,9 +576,9 @@ fileclass(class, filename, fmt)
                if (sscanf(buf, fmt, wordbuf) != 1)
                        continue;
                p = wordbuf;
                if (sscanf(buf, fmt, wordbuf) != 1)
                        continue;
                p = wordbuf;
-# else SCANF
+# else /* SCANF */
                p = buf;
                p = buf;
-# endif SCANF
+# endif /* SCANF */
 
                /*
                **  Break up the match into words.
 
                /*
                **  Break up the match into words.
@@ -357,14 +589,14 @@ fileclass(class, filename, fmt)
                        register char *q;
 
                        /* strip leading spaces */
                        register char *q;
 
                        /* strip leading spaces */
-                       while (isspace(*p))
+                       while (isascii(*p) && isspace(*p))
                                p++;
                        if (*p == '\0')
                                break;
 
                        /* find the end of the word */
                        q = p;
                                p++;
                        if (*p == '\0')
                                break;
 
                        /* find the end of the word */
                        q = p;
-                       while (*p != '\0' && !isspace(*p))
+                       while (*p != '\0' && !(isascii(*p) && isspace(*p)))
                                p++;
                        if (*p != '\0')
                                *p++ = '\0';
                                p++;
                        if (*p != '\0')
                                *p++ = '\0';
@@ -406,20 +638,19 @@ makemailer(line)
        register STAB *s;
        int i;
        char fcode;
        register STAB *s;
        int i;
        char fcode;
+       auto char *endp;
        extern int NextMailer;
        extern char **makeargv();
        extern char *munchstring();
        extern int NextMailer;
        extern char **makeargv();
        extern char *munchstring();
-       extern char *DelimChar;
        extern long atol();
 
        /* allocate a mailer and set up defaults */
        m = (struct mailer *) xalloc(sizeof *m);
        bzero((char *) m, sizeof *m);
        extern long atol();
 
        /* allocate a mailer and set up defaults */
        m = (struct mailer *) xalloc(sizeof *m);
        bzero((char *) m, sizeof *m);
-       m->m_mno = NextMailer;
        m->m_eol = "\n";
 
        /* collect the mailer name */
        m->m_eol = "\n";
 
        /* collect the mailer name */
-       for (p = line; *p != '\0' && *p != ',' && !isspace(*p); p++)
+       for (p = line; *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); p++)
                continue;
        if (*p != '\0')
                *p++ = '\0';
                continue;
        if (*p != '\0')
                *p++ = '\0';
@@ -428,7 +659,9 @@ makemailer(line)
        /* now scan through and assign info from the fields */
        while (*p != '\0')
        {
        /* now scan through and assign info from the fields */
        while (*p != '\0')
        {
-               while (*p != '\0' && (*p == ',' || isspace(*p)))
+               auto char *delimptr;
+
+               while (*p != '\0' && (*p == ',' || (isascii(*p) && isspace(*p))))
                        p++;
 
                /* p now points to field code */
                        p++;
 
                /* p now points to field code */
@@ -437,14 +670,14 @@ makemailer(line)
                        p++;
                if (*p++ != '=')
                {
                        p++;
                if (*p++ != '=')
                {
-                       syserr("`=' expected");
+                       syserr("mailer %s: `=' expected", m->m_name);
                        return;
                }
                        return;
                }
-               while (isspace(*p))
+               while (isascii(*p) && isspace(*p))
                        p++;
 
                /* p now points to the field body */
                        p++;
 
                /* p now points to the field body */
-               p = munchstring(p);
+               p = munchstring(p, &delimptr);
 
                /* install the field into the mailer struct */
                switch (fcode)
 
                /* install the field into the mailer struct */
                switch (fcode)
@@ -455,21 +688,38 @@ makemailer(line)
 
                  case 'F':             /* flags */
                        for (; *p != '\0'; p++)
 
                  case 'F':             /* flags */
                        for (; *p != '\0'; p++)
-                               setbitn(*p, m->m_flags);
+                               if (!(isascii(*p) && isspace(*p)))
+                                       setbitn(*p, m->m_flags);
                        break;
 
                  case 'S':             /* sender rewriting ruleset */
                  case 'R':             /* recipient rewriting ruleset */
                        break;
 
                  case 'S':             /* sender rewriting ruleset */
                  case 'R':             /* recipient rewriting ruleset */
-                       i = atoi(p);
+                       i = strtol(p, &endp, 10);
                        if (i < 0 || i >= MAXRWSETS)
                        {
                                syserr("invalid rewrite set, %d max", MAXRWSETS);
                                return;
                        }
                        if (fcode == 'S')
                        if (i < 0 || i >= MAXRWSETS)
                        {
                                syserr("invalid rewrite set, %d max", MAXRWSETS);
                                return;
                        }
                        if (fcode == 'S')
-                               m->m_s_rwset = i;
+                               m->m_sh_rwset = m->m_se_rwset = i;
                        else
                        else
-                               m->m_r_rwset = i;
+                               m->m_rh_rwset = m->m_re_rwset = i;
+
+                       p = endp;
+                       if (*p++ == '/')
+                       {
+                               i = strtol(p, NULL, 10);
+                               if (i < 0 || i >= MAXRWSETS)
+                               {
+                                       syserr("invalid rewrite set, %d max",
+                                               MAXRWSETS);
+                                       return;
+                               }
+                               if (fcode == 'S')
+                                       m->m_sh_rwset = i;
+                               else
+                                       m->m_rh_rwset = i;
+                       }
                        break;
 
                  case 'E':             /* end of line string */
                        break;
 
                  case 'E':             /* end of line string */
@@ -483,44 +733,80 @@ makemailer(line)
                  case 'M':             /* maximum message size */
                        m->m_maxsize = atol(p);
                        break;
                  case 'M':             /* maximum message size */
                        m->m_maxsize = atol(p);
                        break;
+
+                 case 'L':             /* maximum line length */
+                       m->m_linelimit = atoi(p);
+                       break;
+
+                 case 'D':             /* working directory */
+                       m->m_execdir = newstr(p);
+                       break;
                }
 
                }
 
-               p = DelimChar;
+               p = delimptr;
+       }
+
+       /* do some heuristic cleanup for back compatibility */
+       if (bitnset(M_LIMITS, m->m_flags))
+       {
+               if (m->m_linelimit == 0)
+                       m->m_linelimit = SMTPLINELIM;
+               if (ConfigLevel < 2)
+                       setbitn(M_7BITS, m->m_flags);
+       }
+
+       /* do some rationality checking */
+       if (m->m_argv == NULL)
+       {
+               syserr("M%s: A= argument required", m->m_name);
+               return;
+       }
+       if (m->m_mailer == NULL)
+       {
+               syserr("M%s: P= argument required", m->m_name);
+               return;
        }
 
        }
 
-       /* now store the mailer away */
        if (NextMailer >= MAXMAILERS)
        {
                syserr("too many mailers defined (%d max)", MAXMAILERS);
                return;
        }
        if (NextMailer >= MAXMAILERS)
        {
                syserr("too many mailers defined (%d max)", MAXMAILERS);
                return;
        }
-       Mailer[NextMailer++] = m;
+
        s = stab(m->m_name, ST_MAILER, ST_ENTER);
        s = stab(m->m_name, ST_MAILER, ST_ENTER);
-       s->s_mailer = m;
+       if (s->s_mailer != NULL)
+       {
+               i = s->s_mailer->m_mno;
+               free(s->s_mailer);
+       }
+       else
+       {
+               i = NextMailer++;
+       }
+       Mailer[i] = s->s_mailer = m;
+       m->m_mno = i;
 }
 \f/*
 **  MUNCHSTRING -- translate a string into internal form.
 **
 **     Parameters:
 **             p -- the string to munch.
 }
 \f/*
 **  MUNCHSTRING -- translate a string into internal form.
 **
 **     Parameters:
 **             p -- the string to munch.
+**             delimptr -- if non-NULL, set to the pointer of the
+**                     field delimiter character.
 **
 **     Returns:
 **             the munched string.
 **
 **     Returns:
 **             the munched string.
-**
-**     Side Effects:
-**             Sets "DelimChar" to point to the string that caused us
-**             to stop.
 */
 
 char *
 */
 
 char *
-munchstring(p)
+munchstring(p, delimptr)
        register char *p;
        register char *p;
+       char **delimptr;
 {
        register char *q;
        bool backslash = FALSE;
        bool quotemode = FALSE;
        static char buf[MAXLINE];
 {
        register char *q;
        bool backslash = FALSE;
        bool quotemode = FALSE;
        static char buf[MAXLINE];
-       extern char *DelimChar;
 
        for (q = buf; *p != '\0'; p++)
        {
 
        for (q = buf; *p != '\0'; p++)
        {
@@ -561,7 +847,8 @@ munchstring(p)
                }
        }
 
                }
        }
 
-       DelimChar = p;
+       if (delimptr != NULL)
+               *delimptr = p;
        *q++ = '\0';
        return (buf);
 }
        *q++ = '\0';
        return (buf);
 }
@@ -592,9 +879,9 @@ makeargv(p)
        while (*p != '\0' && i < MAXPV)
        {
                q = p;
        while (*p != '\0' && i < MAXPV)
        {
                q = p;
-               while (*p != '\0' && !isspace(*p))
+               while (*p != '\0' && !(isascii(*p) && isspace(*p)))
                        p++;
                        p++;
-               while (isspace(*p))
+               while (isascii(*p) && isspace(*p))
                        *p++ = '\0';
                argv[i++] = newstr(q);
        }
                        *p++ = '\0';
                argv[i++] = newstr(q);
        }
@@ -651,6 +938,7 @@ printrules()
 **                     reset the user id to avoid security problems.
 **             sticky -- if set, don't let other setoptions override
 **                     this value.
 **                     reset the user id to avoid security problems.
 **             sticky -- if set, don't let other setoptions override
 **                     this value.
+**             e -- the main envelope.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -660,20 +948,43 @@ printrules()
 */
 
 static BITMAP  StickyOpt;              /* set if option is stuck */
 */
 
 static BITMAP  StickyOpt;              /* set if option is stuck */
-extern char    *NetName;               /* name of home (local) network */
 
 
-setoption(opt, val, safe, sticky)
+
+#ifdef NAMED_BIND
+
+struct resolverflags
+{
+       char    *rf_name;       /* name of the flag */
+       long    rf_bits;        /* bits to set/clear */
+} ResolverFlags[] =
+{
+       "debug",        RES_DEBUG,
+       "aaonly",       RES_AAONLY,
+       "usevc",        RES_USEVC,
+       "primary",      RES_PRIMARY,
+       "igntc",        RES_IGNTC,
+       "recurse",      RES_RECURSE,
+       "defnames",     RES_DEFNAMES,
+       "stayopen",     RES_STAYOPEN,
+       "dnsrch",       RES_DNSRCH,
+       NULL,           0
+};
+
+#endif
+
+setoption(opt, val, safe, sticky, e)
        char opt;
        char *val;
        bool safe;
        bool sticky;
        char opt;
        char *val;
        bool safe;
        bool sticky;
+       register ENVELOPE *e;
 {
 {
+       register char *p;
        extern bool atobool();
        extern time_t convtime();
        extern int QueueLA;
        extern int RefuseLA;
        extern bool trusteduser();
        extern bool atobool();
        extern time_t convtime();
        extern int QueueLA;
        extern int RefuseLA;
        extern bool trusteduser();
-       extern char *username();
 
        if (tTd(37, 1))
                printf("setoption %c=%s", opt, val);
 
        if (tTd(37, 1))
                printf("setoption %c=%s", opt, val);
@@ -682,7 +993,7 @@ setoption(opt, val, safe, sticky)
        **  See if this option is preset for us.
        */
 
        **  See if this option is preset for us.
        */
 
-       if (bitnset(opt, StickyOpt))
+       if (!sticky && bitnset(opt, StickyOpt))
        {
                if (tTd(37, 1))
                        printf(" (ignored)\n");
        {
                if (tTd(37, 1))
                        printf(" (ignored)\n");
@@ -695,7 +1006,7 @@ setoption(opt, val, safe, sticky)
 
        if (!safe && getuid() == 0)
                safe = TRUE;
 
        if (!safe && getuid() == 0)
                safe = TRUE;
-       if (!safe && index("deiLmorsv", opt) == NULL)
+       if (!safe && strchr("bdeEijLmoprsvC7", opt) == NULL)
        {
                if (opt != 'M' || (val[0] != 'r' && val[0] != 's'))
                {
        {
                if (opt != 'M' || (val[0] != 'r' && val[0] != 's'))
                {
@@ -703,22 +1014,27 @@ setoption(opt, val, safe, sticky)
                                printf(" (unsafe)");
                        if (getuid() != geteuid())
                        {
                                printf(" (unsafe)");
                        if (getuid() != geteuid())
                        {
-                               printf("(Resetting uid)\n");
+                               if (tTd(37, 1))
+                                       printf("(Resetting uid)");
                                (void) setgid(getgid());
                                (void) setuid(getuid());
                        }
                }
        }
                                (void) setgid(getgid());
                                (void) setuid(getuid());
                        }
                }
        }
-       else if (tTd(37, 1))
+       if (tTd(37, 1))
                printf("\n");
 
        switch (opt)
        {
                printf("\n");
 
        switch (opt)
        {
+         case '7':             /* force seven-bit input */
+               SevenBit = atobool(val);
+               break;
+
          case 'A':             /* set default alias file */
                if (val[0] == '\0')
          case 'A':             /* set default alias file */
                if (val[0] == '\0')
-                       AliasFile = "aliases";
+                       setalias("aliases");
                else
                else
-                       AliasFile = newstr(val);
+                       setalias(val);
                break;
 
          case 'a':             /* look N minutes for "@:@" in alias file */
                break;
 
          case 'a':             /* look N minutes for "@:@" in alias file */
@@ -734,30 +1050,40 @@ setoption(opt, val, safe, sticky)
                        SpaceSub = ' ';
                break;
 
                        SpaceSub = ' ';
                break;
 
+         case 'b':             /* min blocks free on queue fs/max msg size */
+               p = strchr(val, '/');
+               if (p != NULL)
+               {
+                       *p++ = '\0';
+                       MaxMessageSize = atol(p);
+               }
+               MinBlocksFree = atol(val);
+               break;
+
          case 'c':             /* don't connect to "expensive" mailers */
                NoConnect = atobool(val);
                break;
 
          case 'c':             /* don't connect to "expensive" mailers */
                NoConnect = atobool(val);
                break;
 
-         case 'C':             /* checkpoint after N connections */
-               CheckPointLimit = atoi(val);
+         case 'C':             /* checkpoint every N addresses */
+               CheckpointInterval = atoi(val);
                break;
 
          case 'd':             /* delivery mode */
                switch (*val)
                {
                  case '\0':
                break;
 
          case 'd':             /* delivery mode */
                switch (*val)
                {
                  case '\0':
-                       SendMode = SM_DELIVER;
+                       e->e_sendmode = SM_DELIVER;
                        break;
 
                  case SM_QUEUE:        /* queue only */
 #ifndef QUEUE
                        syserr("need QUEUE to set -odqueue");
                        break;
 
                  case SM_QUEUE:        /* queue only */
 #ifndef QUEUE
                        syserr("need QUEUE to set -odqueue");
-#endif QUEUE
+#endif /* QUEUE */
                        /* fall through..... */
 
                  case SM_DELIVER:      /* do everything */
                  case SM_FORK:         /* fork after verification */
                        /* fall through..... */
 
                  case SM_DELIVER:      /* do everything */
                  case SM_FORK:         /* fork after verification */
-                       SendMode = *val;
+                       e->e_sendmode = *val;
                        break;
 
                  default:
                        break;
 
                  default:
@@ -770,6 +1096,11 @@ setoption(opt, val, safe, sticky)
                AutoRebuild = atobool(val);
                break;
 
                AutoRebuild = atobool(val);
                break;
 
+         case 'E':             /* error message header/header file */
+               if (*val != '\0')
+                       ErrMsgFile = newstr(val);
+               break;
+
          case 'e':             /* set error processing mode */
                switch (*val)
                {
          case 'e':             /* set error processing mode */
                switch (*val)
                {
@@ -781,7 +1112,7 @@ setoption(opt, val, safe, sticky)
                        /* fall through... */
 
                  case EM_PRINT:        /* print errors normally (default) */
                        /* fall through... */
 
                  case EM_PRINT:        /* print errors normally (default) */
-                       ErrorMode = *val;
+                       e->e_errormode = *val;
                        break;
                }
                break;
                        break;
                }
                break;
@@ -794,6 +1125,10 @@ setoption(opt, val, safe, sticky)
                SaveFrom = atobool(val);
                break;
 
                SaveFrom = atobool(val);
                break;
 
+         case 'G':             /* match recipients against GECOS field */
+               MatchGecos = atobool(val);
+               break;
+
          case 'g':             /* default gid */
                DefGid = atoi(val);
                break;
          case 'g':             /* default gid */
                DefGid = atoi(val);
                break;
@@ -805,16 +1140,75 @@ setoption(opt, val, safe, sticky)
                        HelpFile = newstr(val);
                break;
 
                        HelpFile = newstr(val);
                break;
 
+         case 'h':             /* maximum hop count */
+               MaxHopCount = atoi(val);
+               break;
+
          case 'I':             /* use internet domain name server */
          case 'I':             /* use internet domain name server */
-               UseNameServer = atobool(val);
+#ifdef NAMED_BIND
+               UseNameServer = TRUE;
+               for (p = val; *p != 0; )
+               {
+                       bool clearmode;
+                       char *q;
+                       struct resolverflags *rfp;
+
+                       while (*p == ' ')
+                               p++;
+                       if (*p == '\0')
+                               break;
+                       clearmode = FALSE;
+                       if (*p == '-')
+                               clearmode = TRUE;
+                       else if (*p != '+')
+                               p--;
+                       p++;
+                       q = p;
+                       while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+                               p++;
+                       if (*p != '\0')
+                               *p++ = '\0';
+                       for (rfp = ResolverFlags; rfp->rf_name != NULL; rfp++)
+                       {
+                               if (strcasecmp(q, rfp->rf_name) == 0)
+                                       break;
+                       }
+                       if (clearmode)
+                               _res.options &= ~rfp->rf_bits;
+                       else
+                               _res.options |= rfp->rf_bits;
+               }
+               if (tTd(8, 2))
+                       printf("_res.options = %x\n", _res.options);
+#else
+               usrerr("name server (I option) specified but BIND not compiled in");
+#endif
                break;
 
          case 'i':             /* ignore dot lines in message */
                IgnrDot = atobool(val);
                break;
 
                break;
 
          case 'i':             /* ignore dot lines in message */
                IgnrDot = atobool(val);
                break;
 
-         case 'k':             /* checkpoint every N addresses */
-               CheckpointInterval = atoi(val);
+         case 'j':             /* send errors in MIME (RFC 1341) format */
+               SendMIMEErrors = atobool(val);
+               break;
+
+         case 'J':             /* .forward search path */
+               ForwardPath = newstr(val);
+               break;
+
+         case 'k':             /* connection cache size */
+               MaxMciCache = atoi(val);
+               if (MaxMciCache < 0)
+                       MaxMciCache = 0;
+               break;
+
+         case 'K':             /* connection cache timeout */
+               MciCacheTimeout = convtime(val, 'm');
+               break;
+
+         case 'l':             /* use Errors-To: header */
+               UseErrorsTo = atobool(val);
                break;
 
          case 'L':             /* log level */
                break;
 
          case 'L':             /* log level */
@@ -834,11 +1228,11 @@ setoption(opt, val, safe, sticky)
                CheckAliases = atobool(val);
                break;
 
                CheckAliases = atobool(val);
                break;
 
-# ifdef DAEMON
-         case 'N':             /* home (local?) network name */
-               NetName = newstr(val);
+           /* 'N' available -- was "net name" */
+
+         case 'O':             /* daemon options */
+               setdaemonoptions(val);
                break;
                break;
-# endif DAEMON
 
          case 'o':             /* assume old style headers */
                if (atobool(val))
 
          case 'o':             /* assume old style headers */
                if (atobool(val))
@@ -847,6 +1241,34 @@ setoption(opt, val, safe, sticky)
                        CurEnv->e_flags &= ~EF_OLDSTYLE;
                break;
 
                        CurEnv->e_flags &= ~EF_OLDSTYLE;
                break;
 
+         case 'p':             /* select privacy level */
+               p = val;
+               for (;;)
+               {
+                       register struct prival *pv;
+                       extern struct prival PrivacyValues[];
+
+                       while (isascii(*p) && (isspace(*p) || ispunct(*p)))
+                               p++;
+                       if (*p == '\0')
+                               break;
+                       val = p;
+                       while (isascii(*p) && isalnum(*p))
+                               p++;
+                       if (*p != '\0')
+                               *p++ = '\0';
+
+                       for (pv = PrivacyValues; pv->pv_name != NULL; pv++)
+                       {
+                               if (strcasecmp(val, pv->pv_name) == 0)
+                                       break;
+                       }
+                       if (pv->pv_name == NULL)
+                               syserr("readcf: Op line: %s unrecognized", val);
+                       PrivacyFlags |= pv->pv_flag;
+               }
+               break;
+
          case 'P':             /* postmaster copy address for returned mail */
                PostMasterCopy = newstr(val);
                break;
          case 'P':             /* postmaster copy address for returned mail */
                PostMasterCopy = newstr(val);
                break;
@@ -860,10 +1282,16 @@ setoption(opt, val, safe, sticky)
                        QueueDir = "mqueue";
                else
                        QueueDir = newstr(val);
                        QueueDir = "mqueue";
                else
                        QueueDir = newstr(val);
+               if (RealUid != 0 && !safe)
+                       auth_warning(e, "Processed from queue %s", QueueDir);
+               break;
+
+         case 'R':             /* don't prune routes */
+               DontPruneRoutes = atobool(val);
                break;
 
          case 'r':             /* read timeout */
                break;
 
          case 'r':             /* read timeout */
-               ReadTimeout = convtime(val);
+               settimeouts(val);
                break;
 
          case 'S':             /* status file */
                break;
 
          case 'S':             /* status file */
@@ -878,10 +1306,21 @@ setoption(opt, val, safe, sticky)
                break;
 
          case 'T':             /* queue timeout */
                break;
 
          case 'T':             /* queue timeout */
-               TimeOut = convtime(val);
-               /*FALLTHROUGH*/
+               p = strchr(val, '/');
+               if (p != NULL)
+               {
+                       *p++ = '\0';
+                       TimeOuts.to_q_warning = convtime(p, 'd');
+               }
+               TimeOuts.to_q_return = convtime(val, 'h');
+               break;
 
          case 't':             /* time zone name */
 
          case 't':             /* time zone name */
+               TimeZoneSpec = newstr(val);
+               break;
+
+         case 'U':             /* location of user database */
+               UdbSpec = newstr(val);
                break;
 
          case 'u':             /* set default uid */
                break;
 
          case 'u':             /* set default uid */
@@ -889,10 +1328,18 @@ setoption(opt, val, safe, sticky)
                setdefuser();
                break;
 
                setdefuser();
                break;
 
+         case 'V':             /* fallback MX host */
+               FallBackMX = newstr(val);
+               break;
+
          case 'v':             /* run in verbose mode */
                Verbose = atobool(val);
                break;
 
          case 'v':             /* run in verbose mode */
                Verbose = atobool(val);
                break;
 
+           /* 'w' available -- was "no wildcard MX matching" */
+
+           /* 'W' available -- was wizard password */
+
          case 'x':             /* load avg at which to auto-queue msgs */
                QueueLA = atoi(val);
                break;
          case 'x':             /* load avg at which to auto-queue msgs */
                QueueLA = atoi(val);
                break;
@@ -944,6 +1391,177 @@ setclass(class, word)
 {
        register STAB *s;
 
 {
        register STAB *s;
 
+       if (tTd(37, 8))
+               printf("%s added to class %c\n", word, class);
        s = stab(word, ST_CLASS, ST_ENTER);
        setbitn(class, s->s_class);
 }
        s = stab(word, ST_CLASS, ST_ENTER);
        setbitn(class, s->s_class);
 }
+\f/*
+**  MAKEMAPENTRY -- create a map entry
+**
+**     Parameters:
+**             line -- the config file line
+**
+**     Returns:
+**             TRUE if it successfully entered the map entry.
+**             FALSE otherwise (usually syntax error).
+**
+**     Side Effects:
+**             Enters the map into the dictionary.
+*/
+
+void
+makemapentry(line)
+       char *line;
+{
+       register char *p;
+       char *mapname;
+       char *classname;
+       register STAB *map;
+       STAB *class;
+
+       for (p = line; isascii(*p) && isspace(*p); p++)
+               continue;
+       if (!(isascii(*p) && isalnum(*p)))
+       {
+               syserr("readcf: config K line: no map name");
+               return;
+       }
+
+       mapname = p;
+       while (isascii(*++p) && isalnum(*p))
+               continue;
+       if (*p != '\0')
+               *p++ = '\0';
+       while (isascii(*p) && isspace(*p))
+               p++;
+       if (!(isascii(*p) && isalnum(*p)))
+       {
+               syserr("readcf: config K line, map %s: no map class", mapname);
+               return;
+       }
+       classname = p;
+       while (isascii(*++p) && isalnum(*p))
+               continue;
+       if (*p != '\0')
+               *p++ = '\0';
+       while (isascii(*p) && isspace(*p))
+               p++;
+
+       /* look up the class */
+       class = stab(classname, ST_MAPCLASS, ST_FIND);
+       if (class == NULL)
+       {
+               syserr("readcf: map %s: class %s not available", mapname, classname);
+               return;
+       }
+
+       /* enter the map */
+       map = stab(mapname, ST_MAP, ST_ENTER);
+       map->s_map.map_class = &class->s_mapclass;
+       map->s_map.map_mname = newstr(mapname);
+
+       if (class->s_mapclass.map_parse(&map->s_map, p))
+               map->s_map.map_mflags |= MF_VALID;
+}
+\f/*
+**  SETTIMEOUTS -- parse and set timeout values
+**
+**     Parameters:
+**             val -- a pointer to the values.  If NULL, do initial
+**                     settings.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Initializes the TimeOuts structure
+*/
+
+#define MINUTES        * 60
+#define HOUR   * 3600
+
+settimeouts(val)
+       register char *val;
+{
+       register char *p;
+       extern time_t convtime();
+
+       if (val == NULL)
+       {
+               TimeOuts.to_initial = (time_t) 5 MINUTES;
+               TimeOuts.to_helo = (time_t) 5 MINUTES;
+               TimeOuts.to_mail = (time_t) 10 MINUTES;
+               TimeOuts.to_rcpt = (time_t) 1 HOUR;
+               TimeOuts.to_datainit = (time_t) 5 MINUTES;
+               TimeOuts.to_datablock = (time_t) 1 HOUR;
+               TimeOuts.to_datafinal = (time_t) 1 HOUR;
+               TimeOuts.to_rset = (time_t) 5 MINUTES;
+               TimeOuts.to_quit = (time_t) 2 MINUTES;
+               TimeOuts.to_nextcommand = (time_t) 1 HOUR;
+               TimeOuts.to_miscshort = (time_t) 2 MINUTES;
+               return;
+       }
+
+       for (;; val = p)
+       {
+               while (isascii(*val) && isspace(*val))
+                       val++;
+               if (*val == '\0')
+                       break;
+               for (p = val; *p != '\0' && *p != ','; p++)
+                       continue;
+               if (*p != '\0')
+                       *p++ = '\0';
+
+               if (isascii(*val) && isdigit(*val))
+               {
+                       /* old syntax -- set everything */
+                       TimeOuts.to_mail = convtime(val, 'm');
+                       TimeOuts.to_rcpt = TimeOuts.to_mail;
+                       TimeOuts.to_datainit = TimeOuts.to_mail;
+                       TimeOuts.to_datablock = TimeOuts.to_mail;
+                       TimeOuts.to_datafinal = TimeOuts.to_mail;
+                       TimeOuts.to_nextcommand = TimeOuts.to_mail;
+                       continue;
+               }
+               else
+               {
+                       register char *q = strchr(val, '=');
+                       time_t to;
+
+                       if (q == NULL)
+                       {
+                               /* syntax error */
+                               continue;
+                       }
+                       *q++ = '\0';
+                       to = convtime(q, 'm');
+
+                       if (strcasecmp(val, "initial") == 0)
+                               TimeOuts.to_initial = to;
+                       else if (strcasecmp(val, "mail") == 0)
+                               TimeOuts.to_mail = to;
+                       else if (strcasecmp(val, "rcpt") == 0)
+                               TimeOuts.to_rcpt = to;
+                       else if (strcasecmp(val, "datainit") == 0)
+                               TimeOuts.to_datainit = to;
+                       else if (strcasecmp(val, "datablock") == 0)
+                               TimeOuts.to_datablock = to;
+                       else if (strcasecmp(val, "datafinal") == 0)
+                               TimeOuts.to_datafinal = to;
+                       else if (strcasecmp(val, "command") == 0)
+                               TimeOuts.to_nextcommand = to;
+                       else if (strcasecmp(val, "rset") == 0)
+                               TimeOuts.to_rset = to;
+                       else if (strcasecmp(val, "helo") == 0)
+                               TimeOuts.to_helo = to;
+                       else if (strcasecmp(val, "quit") == 0)
+                               TimeOuts.to_quit = to;
+                       else if (strcasecmp(val, "misc") == 0)
+                               TimeOuts.to_miscshort = to;
+                       else
+                               syserr("settimeouts: invalid timeout %s", val);
+               }
+       }
+}
index 41634c1..9e3e4d3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)recipient.c        5.19 (Berkeley) 3/2/91";
+static char sccsid[] = "@(#)recipient.c        8.1 (Berkeley) 6/27/93";
 #endif /* not lint */
 
 #endif /* not lint */
 
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <pwd.h>
 # include "sendmail.h"
 # include "sendmail.h"
+# include <pwd.h>
 
 /*
 **  SENDTOLIST -- Designate a send list.
 
 /*
 **  SENDTOLIST -- Designate a send list.
@@ -55,9 +53,10 @@ static char sccsid[] = "@(#)recipient.c      5.19 (Berkeley) 3/2/91";
 **                     expansion.
 **             sendq -- a pointer to the head of a queue to put
 **                     these people into.
 **                     expansion.
 **             sendq -- a pointer to the head of a queue to put
 **                     these people into.
+**             e -- the envelope in which to add these recipients.
 **
 **     Returns:
 **
 **     Returns:
-**             none
+**             The number of addresses actually on the list.
 **
 **     Side Effects:
 **             none.
 **
 **     Side Effects:
 **             none.
@@ -65,16 +64,17 @@ static char sccsid[] = "@(#)recipient.c     5.19 (Berkeley) 3/2/91";
 
 # define MAXRCRSN      10
 
 
 # define MAXRCRSN      10
 
-sendtolist(list, ctladdr, sendq)
+sendtolist(list, ctladdr, sendq, e)
        char *list;
        ADDRESS *ctladdr;
        ADDRESS **sendq;
        char *list;
        ADDRESS *ctladdr;
        ADDRESS **sendq;
+       register ENVELOPE *e;
 {
        register char *p;
        register ADDRESS *al;   /* list of addresses to send to */
        bool firstone;          /* set on first address sent */
 {
        register char *p;
        register ADDRESS *al;   /* list of addresses to send to */
        bool firstone;          /* set on first address sent */
-       bool selfref;           /* set if this list includes ctladdr */
        char delimiter;         /* the address delimiter */
        char delimiter;         /* the address delimiter */
+       int naddrs;
 
        if (tTd(25, 1))
        {
 
        if (tTd(25, 1))
        {
@@ -84,27 +84,27 @@ sendtolist(list, ctladdr, sendq)
 
        /* heuristic to determine old versus new style addresses */
        if (ctladdr == NULL &&
 
        /* heuristic to determine old versus new style addresses */
        if (ctladdr == NULL &&
-           (index(list, ',') != NULL || index(list, ';') != NULL ||
-            index(list, '<') != NULL || index(list, '(') != NULL))
-               CurEnv->e_flags &= ~EF_OLDSTYLE;
+           (strchr(list, ',') != NULL || strchr(list, ';') != NULL ||
+            strchr(list, '<') != NULL || strchr(list, '(') != NULL))
+               e->e_flags &= ~EF_OLDSTYLE;
        delimiter = ' ';
        delimiter = ' ';
-       if (!bitset(EF_OLDSTYLE, CurEnv->e_flags) || ctladdr != NULL)
+       if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL)
                delimiter = ',';
 
        firstone = TRUE;
                delimiter = ',';
 
        firstone = TRUE;
-       selfref = FALSE;
        al = NULL;
        al = NULL;
+       naddrs = 0;
 
        for (p = list; *p != '\0'; )
        {
 
        for (p = list; *p != '\0'; )
        {
+               auto char *delimptr;
                register ADDRESS *a;
                register ADDRESS *a;
-               extern char *DelimChar;         /* defined in prescan */
 
                /* parse the address */
 
                /* parse the address */
-               while (isspace(*p) || *p == ',')
+               while ((isascii(*p) && isspace(*p)) || *p == ',')
                        p++;
                        p++;
-               a = parseaddr(p, (ADDRESS *) NULL, 1, delimiter);
-               p = DelimChar;
+               a = parseaddr(p, (ADDRESS *) NULL, 1, delimiter, &delimptr, e);
+               p = delimptr;
                if (a == NULL)
                        continue;
                a->q_next = al;
                if (a == NULL)
                        continue;
                a->q_next = al;
@@ -115,34 +115,28 @@ sendtolist(list, ctladdr, sendq)
                    (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags)))
                        a->q_flags |= QPRIMARY;
 
                    (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags)))
                        a->q_flags |= QPRIMARY;
 
-               /* put on send queue or suppress self-reference */
                if (ctladdr != NULL && sameaddr(ctladdr, a))
                if (ctladdr != NULL && sameaddr(ctladdr, a))
-                       selfref = TRUE;
-               else
-                       al = a;
+                       ctladdr->q_flags |= QSELFREF;
+               al = a;
                firstone = FALSE;
        }
 
                firstone = FALSE;
        }
 
-       /* if this alias doesn't include itself, delete ctladdr */
-       if (!selfref && ctladdr != NULL)
-               ctladdr->q_flags |= QDONTSEND;
-
        /* arrange to send to everyone on the local send list */
        while (al != NULL)
        {
                register ADDRESS *a = al;
        /* arrange to send to everyone on the local send list */
        while (al != NULL)
        {
                register ADDRESS *a = al;
-               extern ADDRESS *recipient();
 
                al = a->q_next;
 
                al = a->q_next;
-               setctladdr(a);
-               a = recipient(a, sendq);
+               a = recipient(a, sendq, e);
 
                /* arrange to inherit full name */
                if (a->q_fullname == NULL && ctladdr != NULL)
                        a->q_fullname = ctladdr->q_fullname;
 
                /* arrange to inherit full name */
                if (a->q_fullname == NULL && ctladdr != NULL)
                        a->q_fullname = ctladdr->q_fullname;
+               naddrs++;
        }
 
        }
 
-       CurEnv->e_to = NULL;
+       e->e_to = NULL;
+       return (naddrs);
 }
 \f/*
 **  RECIPIENT -- Designate a message recipient
 }
 \f/*
 **  RECIPIENT -- Designate a message recipient
@@ -154,6 +148,7 @@ sendtolist(list, ctladdr, sendq)
 **             sendq -- a pointer to the head of a queue to put the
 **                     recipient in.  Duplicate supression is done
 **                     in this queue.
 **             sendq -- a pointer to the head of a queue to put the
 **                     recipient in.  Duplicate supression is done
 **                     in this queue.
+**             e -- the current envelope.
 **
 **     Returns:
 **             The actual address in the queue.  This will be "a" if
 **
 **     Returns:
 **             The actual address in the queue.  This will be "a" if
@@ -163,22 +158,22 @@ sendtolist(list, ctladdr, sendq)
 **             none.
 */
 
 **             none.
 */
 
-extern ADDRESS *getctladdr();
-
 ADDRESS *
 ADDRESS *
-recipient(a, sendq)
+recipient(a, sendq, e)
        register ADDRESS *a;
        register ADDRESS **sendq;
        register ADDRESS *a;
        register ADDRESS **sendq;
+       register ENVELOPE *e;
 {
        register ADDRESS *q;
        ADDRESS **pq;
        register struct mailer *m;
        register char *p;
        bool quoted = FALSE;            /* set if the addr has a quote bit */
 {
        register ADDRESS *q;
        ADDRESS **pq;
        register struct mailer *m;
        register char *p;
        bool quoted = FALSE;            /* set if the addr has a quote bit */
+       int findusercount = 0;
        char buf[MAXNAME];              /* unquoted image of the user name */
        char buf[MAXNAME];              /* unquoted image of the user name */
-       extern bool safefile();
+       extern int safefile();
 
 
-       CurEnv->e_to = a->q_paddr;
+       e->e_to = a->q_paddr;
        m = a->q_mailer;
        errno = 0;
        if (tTd(26, 1))
        m = a->q_mailer;
        errno = 0;
        if (tTd(26, 1))
@@ -190,7 +185,7 @@ recipient(a, sendq)
        /* break aliasing loops */
        if (AliasLevel > MAXRCRSN)
        {
        /* break aliasing loops */
        if (AliasLevel > MAXRCRSN)
        {
-               usrerr("aliasing/forwarding loop broken");
+               usrerr("554 aliasing/forwarding loop broken");
                return (a);
        }
 
                return (a);
        }
 
@@ -199,31 +194,23 @@ recipient(a, sendq)
        */
 
        /* set the queue timeout */
        */
 
        /* set the queue timeout */
-       a->q_timeout = TimeOut;
-
-       /* map user & host to lower case if requested on non-aliases */
-       if (a->q_alias == NULL)
-               loweraddr(a);
+       a->q_timeout = TimeOuts.to_q_return;
 
        /* get unquoted user for file, program or user.name check */
        (void) strcpy(buf, a->q_user);
        for (p = buf; *p != '\0' && !quoted; p++)
        {
 
        /* get unquoted user for file, program or user.name check */
        (void) strcpy(buf, a->q_user);
        for (p = buf; *p != '\0' && !quoted; p++)
        {
-               if (!isascii(*p) && (*p & 0377) != (SpaceSub & 0377))
+               if (*p == '\\')
                        quoted = TRUE;
        }
                        quoted = TRUE;
        }
-       stripquotes(buf, TRUE);
+       stripquotes(buf);
 
 
-       /* do sickly crude mapping for program mailing, etc. */
-       if (m == LocalMailer && buf[0] == '|')
+       /* check for direct mailing to restricted mailers */
+       if (a->q_alias == NULL && m == ProgMailer &&
+           !bitset(EF_QUEUERUN, e->e_flags))
        {
        {
-               a->q_mailer = m = ProgMailer;
-               a->q_user++;
-               if (a->q_alias == NULL && !QueueRun && !ForceMail)
-               {
-                       a->q_flags |= QDONTSEND|QBADADDR;
-                       usrerr("Cannot mail directly to programs");
-               }
+               a->q_flags |= QBADADDR;
+               usrerr("550 Cannot mail directly to programs", m->m_name);
        }
 
        /*
        }
 
        /*
@@ -237,17 +224,19 @@ recipient(a, sendq)
 
        for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
        {
 
        for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
        {
-               if (!ForceMail && sameaddr(q, a))
+               if (sameaddr(q, a))
                {
                        if (tTd(26, 1))
                        {
                                printf("%s in sendq: ", a->q_paddr);
                                printaddr(q, FALSE);
                        }
                {
                        if (tTd(26, 1))
                        {
                                printf("%s in sendq: ", a->q_paddr);
                                printaddr(q, FALSE);
                        }
-                       if (!bitset(QDONTSEND, a->q_flags))
-                               message(Arpa_Info, "duplicate suppressed");
                        if (!bitset(QPRIMARY, q->q_flags))
                        if (!bitset(QPRIMARY, q->q_flags))
+                       {
+                               if (!bitset(QDONTSEND, a->q_flags))
+                                       message("duplicate suppressed");
                                q->q_flags |= a->q_flags;
                                q->q_flags |= a->q_flags;
+                       }
                        return (q);
                }
        }
                        return (q);
                }
        }
@@ -255,95 +244,181 @@ recipient(a, sendq)
        /* add address on list */
        *pq = a;
        a->q_next = NULL;
        /* add address on list */
        *pq = a;
        a->q_next = NULL;
-       CurEnv->e_nrcpts++;
 
        /*
 
        /*
-       **  Alias the name and handle :include: specs.
+       **  Alias the name and handle special mailer types.
        */
 
        */
 
-       if (m == LocalMailer && !bitset(QDONTSEND, a->q_flags))
+  trylocaluser:
+       if (tTd(29, 7))
+               printf("at trylocaluser %s\n", a->q_user);
+
+       if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))
+               return (a);
+
+       if (m == InclMailer)
        {
        {
-               if (strncmp(a->q_user, ":include:", 9) == 0)
+               a->q_flags |= QDONTSEND;
+               if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags))
                {
                {
-                       a->q_flags |= QDONTSEND;
-                       if (a->q_alias == NULL && !QueueRun && !ForceMail)
+                       a->q_flags |= QBADADDR;
+                       usrerr("550 Cannot mail directly to :include:s");
+               }
+               else
+               {
+                       int ret;
+
+                       message("including file %s", a->q_user);
+                       ret = include(a->q_user, FALSE, a, sendq, e);
+                       if (transienterror(ret))
                        {
                        {
-                               a->q_flags |= QBADADDR;
-                               usrerr("Cannot mail directly to :include:s");
+#ifdef LOG
+                               if (LogLevel > 2)
+                                       syslog(LOG_ERR, "%s: include %s: transient error: %e",
+                                               e->e_id, a->q_user, errstring(ret));
+#endif
+                               a->q_flags |= QQUEUEUP|QDONTSEND;
+                               usrerr("451 Cannot open %s: %s",
+                                       a->q_user, errstring(ret));
                        }
                        }
-                       else
+                       else if (ret != 0)
                        {
                        {
-                               message(Arpa_Info, "including file %s", &a->q_user[9]);
-                               include(&a->q_user[9], " sending", a, sendq);
+                               usrerr("550 Cannot open %s: %s",
+                                       a->q_user, errstring(ret));
+                               a->q_flags |= QBADADDR;
                        }
                }
                        }
                }
-               else
-                       alias(a, sendq);
        }
        }
+       else if (m == FileMailer)
+       {
+               struct stat stb;
+               extern bool writable();
+
+               p = strrchr(buf, '/');
+               /* check if writable or creatable */
+               if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags))
+               {
+                       a->q_flags |= QBADADDR;
+                       usrerr("550 Cannot mail directly to files");
+               }
+               else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
+                   (*p = '\0', safefile(buf, getruid(), S_IWRITE|S_IEXEC) != 0))
+               {
+                       a->q_flags |= QBADADDR;
+                       giveresponse(EX_CANTCREAT, m, NULL, e);
+               }
+       }
+
+       if (m != LocalMailer)
+       {
+               if (!bitset(QDONTSEND, a->q_flags))
+                       e->e_nrcpts++;
+               return (a);
+       }
+
+       /* try aliasing */
+       alias(a, sendq, e);
+
+# ifdef USERDB
+       /* if not aliased, look it up in the user database */
+       if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags))
+       {
+               extern int udbexpand();
+               extern int errno;
+
+               if (udbexpand(a, sendq, e) == EX_TEMPFAIL)
+               {
+                       a->q_flags |= QQUEUEUP|QDONTSEND;
+                       if (e->e_message == NULL)
+                               e->e_message = newstr("Deferred: user database error");
+# ifdef LOG
+                       if (LogLevel > 8)
+                               syslog(LOG_INFO, "%s: deferred: udbexpand: %s",
+                                       e->e_id, errstring(errno));
+# endif
+                       message("queued (user database error): %s",
+                               errstring(errno));
+                       e->e_nrcpts++;
+                       return (a);
+               }
+       }
+# endif
+
+       /* if it was an alias or a UDB expansion, just return now */
+       if (bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags))
+               return (a);
 
        /*
 
        /*
-       **  If the user is local and still being sent, verify that
-       **  the address is good.  If it is, try to forward.
-       **  If the address is already good, we have a forwarding
-       **  loop.  This can be broken by just sending directly to
-       **  the user (which is probably correct anyway).
+       **  If we have a level two config file, then pass the name through
+       **  Ruleset 5 before sending it off.  Ruleset 5 has the right
+       **  to send rewrite it to another mailer.  This gives us a hook
+       **  after local aliasing has been done.
        */
 
        */
 
-       if (!bitset(QDONTSEND, a->q_flags) && m == LocalMailer)
+       if (tTd(29, 5))
        {
        {
-               struct stat stb;
-               extern bool writable();
+               printf("recipient: testing local?  cl=%d, rr5=%x\n\t",
+                       ConfigLevel, RewriteRules[5]);
+               printaddr(a, FALSE);
+       }
+       if (!bitset(QNOTREMOTE, a->q_flags) && ConfigLevel >= 2 &&
+           RewriteRules[5] != NULL)
+       {
+               maplocaluser(a, sendq, e);
+       }
+
+       /*
+       **  If it didn't get rewritten to another mailer, go ahead
+       **  and deliver it.
+       */
+
+       if (!bitset(QDONTSEND|QQUEUEUP, a->q_flags))
+       {
+               auto bool fuzzy;
+               register struct passwd *pw;
+               extern struct passwd *finduser();
 
 
-               /* see if this is to a file */
-               if (buf[0] == '/')
+               /* warning -- finduser may trash buf */
+               pw = finduser(buf, &fuzzy);
+               if (pw == NULL)
                {
                {
-                       p = rindex(buf, '/');
-                       /* check if writable or creatable */
-                       if (a->q_alias == NULL && !QueueRun && !ForceMail)
-                       {
-                               a->q_flags |= QDONTSEND|QBADADDR;
-                               usrerr("Cannot mail directly to files");
-                       }
-                       else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
-                           (*p = '\0', !safefile(buf, getruid(), S_IWRITE|S_IEXEC)))
-                       {
-                               a->q_flags |= QBADADDR;
-                               giveresponse(EX_CANTCREAT, m, CurEnv);
-                       }
+                       a->q_flags |= QBADADDR;
+                       giveresponse(EX_NOUSER, m, NULL, e);
                }
                else
                {
                }
                else
                {
-                       register struct passwd *pw;
-                       extern struct passwd *finduser();
+                       char nbuf[MAXNAME];
 
 
-                       /* warning -- finduser may trash buf */
-                       pw = finduser(buf);
-                       if (pw == NULL)
-                       {
-                               a->q_flags |= QBADADDR;
-                               giveresponse(EX_NOUSER, m, CurEnv);
-                       }
-                       else
+                       if (fuzzy)
                        {
                        {
-                               char nbuf[MAXNAME];
-
-                               if (strcmp(a->q_user, pw->pw_name) != 0)
+                               /* name was a fuzzy match */
+                               a->q_user = newstr(pw->pw_name);
+                               if (findusercount++ > 3)
                                {
                                {
-                                       a->q_user = newstr(pw->pw_name);
-                                       (void) strcpy(buf, pw->pw_name);
+                                       a->q_flags |= QBADADDR;
+                                       usrerr("554 aliasing/forwarding loop for %s broken",
+                                               pw->pw_name);
+                                       return (a);
                                }
                                }
-                               a->q_home = newstr(pw->pw_dir);
-                               a->q_uid = pw->pw_uid;
-                               a->q_gid = pw->pw_gid;
-                               a->q_flags |= QGOODUID;
-                               buildfname(pw->pw_gecos, pw->pw_name, nbuf);
-                               if (nbuf[0] != '\0')
-                                       a->q_fullname = newstr(nbuf);
-                               if (!quoted)
-                                       forward(a, sendq);
+
+                               /* see if it aliases */
+                               (void) strcpy(buf, pw->pw_name);
+                               goto trylocaluser;
                        }
                        }
+                       a->q_home = newstr(pw->pw_dir);
+                       a->q_uid = pw->pw_uid;
+                       a->q_gid = pw->pw_gid;
+                       a->q_ruser = newstr(pw->pw_name);
+                       a->q_flags |= QGOODUID;
+                       buildfname(pw->pw_gecos, pw->pw_name, nbuf);
+                       if (nbuf[0] != '\0')
+                               a->q_fullname = newstr(nbuf);
+                       if (!quoted)
+                               forward(a, sendq, e);
                }
        }
                }
        }
+       if (!bitset(QDONTSEND, a->q_flags))
+               e->e_nrcpts++;
        return (a);
 }
 \f/*
        return (a);
 }
 \f/*
@@ -357,6 +432,9 @@ recipient(a, sendq)
 **
 **     Parameters:
 **             name -- the name to match against.
 **
 **     Parameters:
 **             name -- the name to match against.
+**             fuzzyp -- an outarg that is set to TRUE if this entry
+**                     was found using the fuzzy matching algorithm;
+**                     set to FALSE otherwise.
 **
 **     Returns:
 **             A pointer to a pw struct.
 **
 **     Returns:
 **             A pointer to a pw struct.
@@ -367,24 +445,36 @@ recipient(a, sendq)
 */
 
 struct passwd *
 */
 
 struct passwd *
-finduser(name)
+finduser(name, fuzzyp)
        char *name;
        char *name;
+       bool *fuzzyp;
 {
        register struct passwd *pw;
        register char *p;
        extern struct passwd *getpwent();
        extern struct passwd *getpwnam();
 
 {
        register struct passwd *pw;
        register char *p;
        extern struct passwd *getpwent();
        extern struct passwd *getpwnam();
 
-       /* map upper => lower case */
-       for (p = name; *p != '\0'; p++)
-       {
-               if (isascii(*p) && isupper(*p))
-                       *p = tolower(*p);
-       }
+       if (tTd(29, 4))
+               printf("finduser(%s): ", name);
+
+       *fuzzyp = FALSE;
 
        /* look up this login name using fast path */
        if ((pw = getpwnam(name)) != NULL)
 
        /* look up this login name using fast path */
        if ((pw = getpwnam(name)) != NULL)
+       {
+               if (tTd(29, 4))
+                       printf("found (non-fuzzy)\n");
                return (pw);
                return (pw);
+       }
+
+#ifdef MATCHGECOS
+       /* see if fuzzy matching allowed */
+       if (!MatchGecos)
+       {
+               if (tTd(29, 4))
+                       printf("not found (fuzzy disabled)\n");
+               return NULL;
+       }
 
        /* search for a matching full name instead */
        for (p = name; *p != '\0'; p++)
 
        /* search for a matching full name instead */
        for (p = name; *p != '\0'; p++)
@@ -398,12 +488,21 @@ finduser(name)
                char buf[MAXNAME];
 
                buildfname(pw->pw_gecos, pw->pw_name, buf);
                char buf[MAXNAME];
 
                buildfname(pw->pw_gecos, pw->pw_name, buf);
-               if (index(buf, ' ') != NULL && !strcasecmp(buf, name))
+               if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name))
                {
                {
-                       message(Arpa_Info, "sending to login name %s", pw->pw_name);
+                       if (tTd(29, 4))
+                               printf("fuzzy matches %s\n", pw->pw_name);
+                       message("sending to login name %s", pw->pw_name);
+                       *fuzzyp = TRUE;
                        return (pw);
                }
        }
                        return (pw);
                }
        }
+       if (tTd(29, 4))
+               printf("no fuzzy match found\n");
+#else
+       if (tTd(29, 4))
+               printf("not found (fuzzy disabled)\n");
+#endif
        return (NULL);
 }
 \f/*
        return (NULL);
 }
 \f/*
@@ -432,7 +531,8 @@ bool
 writable(s)
        register struct stat *s;
 {
 writable(s)
        register struct stat *s;
 {
-       int euid, egid;
+       uid_t euid;
+       gid_t egid;
        int bits;
 
        if (bitset(0111, s->st_mode))
        int bits;
 
        if (bitset(0111, s->st_mode))
@@ -463,7 +563,8 @@ writable(s)
 **
 **     Parameters:
 **             fname -- filename to include.
 **
 **     Parameters:
 **             fname -- filename to include.
-**             msg -- message to print in verbose mode.
+**             forwarding -- if TRUE, we are reading a .forward file.
+**                     if FALSE, it's a :include: file.
 **             ctladdr -- address template to use to fill in these
 **                     addresses -- effective user/group id are
 **                     the important things.
 **             ctladdr -- address template to use to fill in these
 **                     addresses -- effective user/group id are
 **                     the important things.
@@ -471,70 +572,165 @@ writable(s)
 **                     to put these addresses in.
 **
 **     Returns:
 **                     to put these addresses in.
 **
 **     Returns:
-**             none.
+**             open error status
 **
 **     Side Effects:
 **             reads the :include: file and sends to everyone
 **             listed in that file.
 */
 
 **
 **     Side Effects:
 **             reads the :include: file and sends to everyone
 **             listed in that file.
 */
 
-include(fname, msg, ctladdr, sendq)
+static jmp_buf CtxIncludeTimeout;
+
+int
+include(fname, forwarding, ctladdr, sendq, e)
        char *fname;
        char *fname;
-       char *msg;
+       bool forwarding;
        ADDRESS *ctladdr;
        ADDRESS **sendq;
        ADDRESS *ctladdr;
        ADDRESS **sendq;
+       ENVELOPE *e;
 {
 {
-       char buf[MAXLINE];
        register FILE *fp;
        register FILE *fp;
-       char *oldto = CurEnv->e_to;
+       char *oldto = e->e_to;
        char *oldfilename = FileName;
        int oldlinenumber = LineNumber;
        char *oldfilename = FileName;
        int oldlinenumber = LineNumber;
+       register EVENT *ev = NULL;
+       int nincludes;
+       int ret;
+       ADDRESS *ca;
+       uid_t uid;
+       char buf[MAXLINE];
+       static int includetimeout();
+
+       if (tTd(27, 2))
+               printf("include(%s)\n", fname);
+       if (tTd(27, 14))
+       {
+               printf("ctladdr ");
+               printaddr(ctladdr, FALSE);
+       }
+
+       /*
+       **  If home directory is remote mounted but server is down,
+       **  this can hang or give errors; use a timeout to avoid this
+       */
+
+       ca = getctladdr(ctladdr);
+       if (ca == NULL)
+               uid = 0;
+       else
+               uid = ca->q_uid;
+
+       if (setjmp(CtxIncludeTimeout) != 0)
+       {
+               ctladdr->q_flags |= QQUEUEUP|QDONTSEND;
+               errno = 0;
+               usrerr("451 open timeout on %s", fname);
+               return ETIMEDOUT;
+       }
+       ev = setevent((time_t) 60, includetimeout, 0);
+
+       /* the input file must be marked safe */
+       if ((ret = safefile(fname, uid, S_IREAD)) != 0)
+       {
+               /* don't use this .forward file */
+               clrevent(ev);
+               if (tTd(27, 4))
+                       printf("include: not safe (uid=%d): %s\n",
+                               uid, errstring(ret));
+               return ret;
+       }
 
        fp = fopen(fname, "r");
        if (fp == NULL)
        {
 
        fp = fopen(fname, "r");
        if (fp == NULL)
        {
-               usrerr("Cannot open %s", fname);
-               return;
+               int ret = errno;
+
+               clrevent(ev);
+               return ret;
        }
        }
-       if (getctladdr(ctladdr) == NULL)
+
+       if (ca == NULL)
        {
                struct stat st;
 
                if (fstat(fileno(fp), &st) < 0)
        {
                struct stat st;
 
                if (fstat(fileno(fp), &st) < 0)
+               {
+                       int ret = errno;
+
+                       clrevent(ev);
                        syserr("Cannot fstat %s!", fname);
                        syserr("Cannot fstat %s!", fname);
+                       return ret;
+               }
                ctladdr->q_uid = st.st_uid;
                ctladdr->q_gid = st.st_gid;
                ctladdr->q_flags |= QGOODUID;
        }
 
                ctladdr->q_uid = st.st_uid;
                ctladdr->q_gid = st.st_gid;
                ctladdr->q_flags |= QGOODUID;
        }
 
+       clrevent(ev);
+
+       if (bitset(EF_VRFYONLY, e->e_flags))
+       {
+               /* don't do any more now */
+               ctladdr->q_flags |= QVERIFIED;
+               e->e_nrcpts++;
+               xfclose(fp, "include", fname);
+               return 0;
+       }
+
        /* read the file -- each line is a comma-separated list. */
        FileName = fname;
        LineNumber = 0;
        /* read the file -- each line is a comma-separated list. */
        FileName = fname;
        LineNumber = 0;
+       ctladdr->q_flags &= ~QSELFREF;
+       nincludes = 0;
        while (fgets(buf, sizeof buf, fp) != NULL)
        {
        while (fgets(buf, sizeof buf, fp) != NULL)
        {
-               register char *p = index(buf, '\n');
+               register char *p = strchr(buf, '\n');
 
                LineNumber++;
                if (p != NULL)
                        *p = '\0';
 
                LineNumber++;
                if (p != NULL)
                        *p = '\0';
-               if (buf[0] == '\0')
+               if (buf[0] == '#' || buf[0] == '\0')
                        continue;
                        continue;
-               CurEnv->e_to = oldto;
-               message(Arpa_Info, "%s to %s", msg, buf);
+               e->e_to = NULL;
+               message("%s to %s",
+                       forwarding ? "forwarding" : "sending", buf);
+#ifdef LOG
+               if (forwarding && LogLevel > 9)
+                       syslog(LOG_INFO, "%s: forward %s => %s",
+                               e->e_id, oldto, buf);
+#endif
+
                AliasLevel++;
                AliasLevel++;
-               sendtolist(buf, ctladdr, sendq);
+               nincludes += sendtolist(buf, ctladdr, sendq, e);
                AliasLevel--;
        }
                AliasLevel--;
        }
+       if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))
+       {
+               if (tTd(27, 5))
+               {
+                       printf("include: QDONTSEND ");
+                       printaddr(ctladdr, FALSE);
+               }
+               ctladdr->q_flags |= QDONTSEND;
+       }
 
 
-       (void) fclose(fp);
+       (void) xfclose(fp, "include", fname);
        FileName = oldfilename;
        LineNumber = oldlinenumber;
        FileName = oldfilename;
        LineNumber = oldlinenumber;
+       return 0;
+}
+
+static
+includetimeout()
+{
+       longjmp(CtxIncludeTimeout, 1);
 }
 \f/*
 **  SENDTOARGV -- send to an argument vector.
 **
 **     Parameters:
 **             argv -- argument vector to send to.
 }
 \f/*
 **  SENDTOARGV -- send to an argument vector.
 **
 **     Parameters:
 **             argv -- argument vector to send to.
+**             e -- the current envelope.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -544,29 +740,15 @@ include(fname, msg, ctladdr, sendq)
 **                     send queue.
 */
 
 **                     send queue.
 */
 
-sendtoargv(argv)
+sendtoargv(argv, e)
        register char **argv;
        register char **argv;
+       register ENVELOPE *e;
 {
        register char *p;
 
        while ((p = *argv++) != NULL)
        {
 {
        register char *p;
 
        while ((p = *argv++) != NULL)
        {
-               if (argv[0] != NULL && argv[1] != NULL && !strcasecmp(argv[0], "at"))
-               {
-                       char nbuf[MAXNAME];
-
-                       if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf)
-                               usrerr("address overflow");
-                       else
-                       {
-                               (void) strcpy(nbuf, p);
-                               (void) strcat(nbuf, "@");
-                               (void) strcat(nbuf, argv[1]);
-                               p = newstr(nbuf);
-                               argv += 2;
-                       }
-               }
-               sendtolist(p, (ADDRESS *) NULL, &CurEnv->e_sendqueue);
+               (void) sendtolist(p, (ADDRESS *) NULL, &e->e_sendqueue, e);
        }
 }
 \f/*
        }
 }
 \f/*
index 1a7fbe2..5a35734 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)savemail.c 5.14 (Berkeley) 8/29/90";
+static char sccsid[] = "@(#)savemail.c 8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #endif /* not lint */
 
-# include <sys/types.h>
 # include <pwd.h>
 # include "sendmail.h"
 
 # include <pwd.h>
 # include "sendmail.h"
 
@@ -77,7 +76,7 @@ savemail(e)
        register struct passwd *pw;
        register FILE *fp;
        int state;
        register struct passwd *pw;
        register FILE *fp;
        int state;
-       auto ADDRESS *q;
+       auto ADDRESS *q = NULL;
        char buf[MAXLINE+1];
        extern struct passwd *getpwnam();
        register char *p;
        char buf[MAXLINE+1];
        extern struct passwd *getpwnam();
        register char *p;
@@ -85,16 +84,18 @@ savemail(e)
        typedef int (*fnptr)();
 
        if (tTd(6, 1))
        typedef int (*fnptr)();
 
        if (tTd(6, 1))
-               printf("\nsavemail, ErrorMode = %c\n", ErrorMode);
+       {
+               printf("\nsavemail, errormode = %c, id = %s\n  e_from=",
+                       e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id);
+               printaddr(&e->e_from, FALSE);
+       }
 
 
-       if (bitset(EF_RESPONSE, e->e_flags))
-               return;
-       if (e->e_class < 0)
+       if (e->e_id == NULL)
        {
        {
-               message(Arpa_Info, "Dumping junk mail");
+               /* can't return a message with no id */
                return;
        }
                return;
        }
-       ForceMail = TRUE;
+
        e->e_flags &= ~EF_FATALERRS;
 
        /*
        e->e_flags &= ~EF_FATALERRS;
 
        /*
@@ -104,9 +105,10 @@ savemail(e)
 
        if (e->e_from.q_paddr == NULL)
        {
 
        if (e->e_from.q_paddr == NULL)
        {
-               if (parseaddr("root", &e->e_from, 0, '\0') == NULL)
+               e->e_sender = "Postmaster";
+               if (parseaddr(e->e_sender, &e->e_from, 0, '\0', NULL, e) == NULL)
                {
                {
-                       syserr("Cannot parse root!");
+                       syserr("553 Cannot parse Postmaster!");
                        ExitStat = EX_SOFTWARE;
                        finis();
                }
                        ExitStat = EX_SOFTWARE;
                        finis();
                }
@@ -128,7 +130,7 @@ savemail(e)
        */
 
        /* determine starting state */
        */
 
        /* determine starting state */
-       switch (ErrorMode)
+       switch (e->e_errormode)
        {
          case EM_WRITE:
                state = ESM_REPORT;
        {
          case EM_WRITE:
                state = ESM_REPORT;
@@ -154,11 +156,23 @@ savemail(e)
                return;
 
          default:
                return;
 
          default:
-               syserr("savemail: ErrorMode x%x\n");
+               syserr("554 savemail: bogus errormode x%x\n", e->e_errormode);
                state = ESM_MAIL;
                break;
        }
 
                state = ESM_MAIL;
                break;
        }
 
+       /* if this is already an error response, send to postmaster */
+       if (bitset(EF_RESPONSE, e->e_flags))
+       {
+               if (e->e_parent != NULL &&
+                   bitset(EF_RESPONSE, e->e_parent->e_flags))
+               {
+                       /* got an error sending a response -- can it */
+                       return;
+               }
+               state = ESM_POSTMASTER;
+       }
+
        while (state != ESM_DONE)
        {
                if (tTd(6, 5))
        while (state != ESM_DONE)
        {
                if (tTd(6, 5))
@@ -187,7 +201,7 @@ savemail(e)
                                break;
                        }
 
                                break;
                        }
 
-                       expand("\001n", buf, &buf[sizeof buf - 1], e);
+                       expand("\201n", buf, &buf[sizeof buf - 1], e);
                        printf("\r\nMessage from %s...\r\n", buf);
                        printf("Errors occurred while sending mail.\r\n");
                        if (e->e_xfp != NULL)
                        printf("\r\nMessage from %s...\r\n", buf);
                        printf("Errors occurred while sending mail.\r\n");
                        if (e->e_xfp != NULL)
@@ -208,14 +222,13 @@ savemail(e)
                                while (fgets(buf, sizeof buf, fp) != NULL &&
                                       !ferror(stdout))
                                        fputs(buf, stdout);
                                while (fgets(buf, sizeof buf, fp) != NULL &&
                                       !ferror(stdout))
                                        fputs(buf, stdout);
-                               (void) fclose(fp);
+                               (void) xfclose(fp, "savemail transcript", e->e_id);
                        }
                        printf("Original message will be saved in dead.letter.\r\n");
                        state = ESM_DEADLETTER;
                        break;
 
                  case ESM_MAIL:
                        }
                        printf("Original message will be saved in dead.letter.\r\n");
                        state = ESM_DEADLETTER;
                        break;
 
                  case ESM_MAIL:
-                 case ESM_POSTMASTER:
                        /*
                        **  If mailing back, do it.
                        **      Throw away all further output.  Don't alias,
                        /*
                        **  If mailing back, do it.
                        **      Throw away all further output.  Don't alias,
@@ -227,39 +240,62 @@ savemail(e)
                        **      it has already been sent to the sender.
                        */
 
                        **      it has already been sent to the sender.
                        */
 
-                       if (state == ESM_MAIL)
+                       if (strcmp(e->e_from.q_paddr, "<>") != 0)
+                               (void) sendtolist(e->e_from.q_paddr,
+                                         (ADDRESS *) NULL,
+                                         &e->e_errorqueue, e);
+
+                       /* deliver a cc: to the postmaster if desired */
+                       if (PostMasterCopy != NULL)
                        {
                        {
-                               if (e->e_errorqueue == NULL)
-                                       sendtolist(e->e_from.q_paddr,
-                                               (ADDRESS *) NULL,
-                                               &e->e_errorqueue);
-
-                               /* deliver a cc: to the postmaster if desired */
-                               if (PostMasterCopy != NULL)
-                                       sendtolist(PostMasterCopy,
-                                               (ADDRESS *) NULL,
-                                               &e->e_errorqueue);
-                               q = e->e_errorqueue;
+                               auto ADDRESS *rlist = NULL;
+
+                               (void) sendtolist(PostMasterCopy,
+                                                 (ADDRESS *) NULL,
+                                                 &rlist, e);
+                               (void) returntosender(e->e_message,
+                                                     rlist, FALSE, e);
                        }
                        }
-                       else
+                       q = e->e_errorqueue;
+                       if (q == NULL)
                        {
                        {
-                               if (parseaddr("postmaster", q, 0, '\0') == NULL)
-                               {
-                                       syserr("cannot parse postmaster!");
-                                       ExitStat = EX_SOFTWARE;
-                                       state = ESM_USRTMP;
-                                       break;
-                               }
+                               /* this is an error-error */
+                               state = ESM_POSTMASTER;
+                               break;
                        }
                        }
-                       if (returntosender(e->e_message != NULL ? e->e_message :
-                                          "Unable to deliver mail",
-                                          q, TRUE) == 0)
+                       if (returntosender(e->e_message,
+                                          q, (e->e_class >= 0), e) == 0)
                        {
                                state = ESM_DONE;
                                break;
                        }
 
                        {
                                state = ESM_DONE;
                                break;
                        }
 
-                       state = state == ESM_MAIL ? ESM_POSTMASTER : ESM_USRTMP;
+                       /* didn't work -- return to postmaster */
+                       state = ESM_POSTMASTER;
+                       break;
+
+                 case ESM_POSTMASTER:
+                       /*
+                       **  Similar to previous case, but to system postmaster.
+                       */
+
+                       q = NULL;
+                       if (sendtolist("postmaster", NULL, &q, e) <= 0)
+                       {
+                               syserr("553 cannot parse postmaster!");
+                               ExitStat = EX_SOFTWARE;
+                               state = ESM_USRTMP;
+                               break;
+                       }
+                       if (returntosender(e->e_message,
+                                          q, (e->e_class >= 0), e) == 0)
+                       {
+                               state = ESM_DONE;
+                               break;
+                       }
+
+                       /* didn't work -- last resort */
+                       state = ESM_USRTMP;
                        break;
 
                  case ESM_DEADLETTER:
                        break;
 
                  case ESM_DEADLETTER:
@@ -282,24 +318,23 @@ savemail(e)
                        }
                        if (p == NULL)
                        {
                        }
                        if (p == NULL)
                        {
-                               syserr("Can't return mail to %s", e->e_from.q_paddr);
+                               /* no local directory */
                                state = ESM_MAIL;
                                break;
                        }
                        if (e->e_dfp != NULL)
                        {
                                state = ESM_MAIL;
                                break;
                        }
                        if (e->e_dfp != NULL)
                        {
-                               auto ADDRESS *q;
                                bool oldverb = Verbose;
 
                                /* we have a home directory; open dead.letter */
                                define('z', p, e);
                                bool oldverb = Verbose;
 
                                /* we have a home directory; open dead.letter */
                                define('z', p, e);
-                               expand("\001z/dead.letter", buf, &buf[sizeof buf - 1], e);
+                               expand("\201z/dead.letter", buf, &buf[sizeof buf - 1], e);
                                Verbose = TRUE;
                                Verbose = TRUE;
-                               message(Arpa_Info, "Saving message in %s", buf);
+                               message("Saving message in %s", buf);
                                Verbose = oldverb;
                                e->e_to = buf;
                                q = NULL;
                                Verbose = oldverb;
                                e->e_to = buf;
                                q = NULL;
-                               sendtolist(buf, (ADDRESS *) NULL, &q);
+                               (void) sendtolist(buf, &e->e_from, &q, e);
                                if (deliver(e, q) == 0)
                                        state = ESM_DONE;
                                else
                                if (deliver(e, q) == 0)
                                        state = ESM_DONE;
                                else
@@ -317,36 +352,38 @@ savemail(e)
                        **  Log the mail in /usr/tmp/dead.letter.
                        */
 
                        **  Log the mail in /usr/tmp/dead.letter.
                        */
 
-                       fp = dfopen("/usr/tmp/dead.letter", "a");
+                       if (e->e_class < 0)
+                       {
+                               state = ESM_DONE;
+                               break;
+                       }
+
+                       fp = dfopen("/usr/tmp/dead.letter",
+                                   O_WRONLY|O_CREAT|O_APPEND, FileMode);
                        if (fp == NULL)
                        {
                                state = ESM_PANIC;
                                break;
                        }
 
                        if (fp == NULL)
                        {
                                state = ESM_PANIC;
                                break;
                        }
 
-                       putfromline(fp, ProgMailer);
-                       (*e->e_puthdr)(fp, ProgMailer, e);
-                       putline("\n", fp, ProgMailer);
-                       (*e->e_putbody)(fp, ProgMailer, e);
-                       putline("\n", fp, ProgMailer);
+                       putfromline(fp, FileMailer, e);
+                       (*e->e_puthdr)(fp, FileMailer, e);
+                       putline("\n", fp, FileMailer);
+                       (*e->e_putbody)(fp, FileMailer, e, NULL);
+                       putline("\n", fp, FileMailer);
                        (void) fflush(fp);
                        state = ferror(fp) ? ESM_PANIC : ESM_DONE;
                        (void) fflush(fp);
                        state = ferror(fp) ? ESM_PANIC : ESM_DONE;
-                       (void) fclose(fp);
+                       (void) xfclose(fp, "savemail", "/usr/tmp/dead.letter");
                        break;
 
                  default:
                        break;
 
                  default:
-                       syserr("savemail: unknown state %d", state);
+                       syserr("554 savemail: unknown state %d", state);
 
                        /* fall through ... */
 
                  case ESM_PANIC:
 
                        /* fall through ... */
 
                  case ESM_PANIC:
-                       syserr("savemail: HELP!!!!");
-# ifdef LOG
-                       if (LogLevel >= 1)
-                               syslog(LOG_ALERT, "savemail: HELP!!!!");
-# endif LOG
-
                        /* leave the locked queue & transcript files around */
                        /* leave the locked queue & transcript files around */
+                       syserr("554 savemail: cannot save rejected email anywhere");
                        exit(EX_SOFTWARE);
                }
        }
                        exit(EX_SOFTWARE);
                }
        }
@@ -359,6 +396,7 @@ savemail(e)
 **             returnq -- the queue of people to send the message to.
 **             sendbody -- if TRUE, also send back the body of the
 **                     message; otherwise just send the header.
 **             returnq -- the queue of people to send the message to.
 **             sendbody -- if TRUE, also send back the body of the
 **                     message; otherwise just send the header.
+**             e -- the current envelope.
 **
 **     Returns:
 **             zero -- if everything went ok.
 **
 **     Returns:
 **             zero -- if everything went ok.
@@ -372,80 +410,116 @@ savemail(e)
 static bool    SendBody;
 
 #define MAXRETURNS     6       /* max depth of returning messages */
 static bool    SendBody;
 
 #define MAXRETURNS     6       /* max depth of returning messages */
+#define ERRORFUDGE     100     /* nominal size of error message text */
 
 
-returntosender(msg, returnq, sendbody)
+returntosender(msg, returnq, sendbody, e)
        char *msg;
        ADDRESS *returnq;
        bool sendbody;
        char *msg;
        ADDRESS *returnq;
        bool sendbody;
+       register ENVELOPE *e;
 {
        char buf[MAXNAME];
        extern putheader(), errbody();
        register ENVELOPE *ee;
 {
        char buf[MAXNAME];
        extern putheader(), errbody();
        register ENVELOPE *ee;
-       extern ENVELOPE *newenvelope();
+       ENVELOPE *oldcur = CurEnv;
        ENVELOPE errenvelope;
        static int returndepth;
        register ADDRESS *q;
 
        ENVELOPE errenvelope;
        static int returndepth;
        register ADDRESS *q;
 
+       if (returnq == NULL)
+               return (-1);
+
+       if (msg == NULL)
+               msg = "Unable to deliver mail";
+
        if (tTd(6, 1))
        {
        if (tTd(6, 1))
        {
-               printf("Return To Sender: msg=\"%s\", depth=%d, CurEnv=%x,\n",
-                      msg, returndepth, CurEnv);
-               printf("\treturnq=");
+               printf("Return To Sender: msg=\"%s\", depth=%d, e=%x, returnq=",
+                      msg, returndepth, e);
                printaddr(returnq, TRUE);
        }
 
        if (++returndepth >= MAXRETURNS)
        {
                if (returndepth != MAXRETURNS)
                printaddr(returnq, TRUE);
        }
 
        if (++returndepth >= MAXRETURNS)
        {
                if (returndepth != MAXRETURNS)
-                       syserr("returntosender: infinite recursion on %s", returnq->q_paddr);
+                       syserr("554 returntosender: infinite recursion on %s", returnq->q_paddr);
                /* don't "unrecurse" and fake a clean exit */
                /* returndepth--; */
                return (0);
        }
 
        SendBody = sendbody;
                /* don't "unrecurse" and fake a clean exit */
                /* returndepth--; */
                return (0);
        }
 
        SendBody = sendbody;
-       define('g', "\001f", CurEnv);
-       ee = newenvelope(&errenvelope);
-       define('a', "\001b", ee);
+       define('g', e->e_from.q_paddr, e);
+       ee = newenvelope(&errenvelope, e);
+       define('a', "\201b", ee);
+       define('r', "internal", ee);
+       define('s', "localhost", ee);
+       define('_', "localhost", ee);
        ee->e_puthdr = putheader;
        ee->e_putbody = errbody;
        ee->e_flags |= EF_RESPONSE;
        ee->e_puthdr = putheader;
        ee->e_putbody = errbody;
        ee->e_flags |= EF_RESPONSE;
-       if (!bitset(EF_OLDSTYLE, CurEnv->e_flags))
+       if (!bitset(EF_OLDSTYLE, e->e_flags))
                ee->e_flags &= ~EF_OLDSTYLE;
        ee->e_sendqueue = returnq;
                ee->e_flags &= ~EF_OLDSTYLE;
        ee->e_sendqueue = returnq;
+       ee->e_msgsize = e->e_msgsize + ERRORFUDGE;
        openxscript(ee);
        for (q = returnq; q != NULL; q = q->q_next)
        {
        openxscript(ee);
        for (q = returnq; q != NULL; q = q->q_next)
        {
+               if (bitset(QBADADDR, q->q_flags))
+                       continue;
+
+               if (!bitset(QDONTSEND, q->q_flags))
+                       ee->e_nrcpts++;
+
+               if (!DontPruneRoutes && pruneroute(q->q_paddr))
+                       parseaddr(q->q_paddr, q, 0, '\0', NULL, e);
+
                if (q->q_alias == NULL)
                if (q->q_alias == NULL)
-                       addheader("to", q->q_paddr, ee);
+                       addheader("To", q->q_paddr, ee);
        }
 
        }
 
+# ifdef LOG
+       if (LogLevel > 5)
+               syslog(LOG_INFO, "%s: %s: return to sender: %s",
+                       e->e_id, ee->e_id, msg);
+# endif
+
        (void) sprintf(buf, "Returned mail: %s", msg);
        (void) sprintf(buf, "Returned mail: %s", msg);
-       addheader("subject", buf, ee);
+       addheader("Subject", buf, ee);
+       if (SendMIMEErrors)
+       {
+               addheader("MIME-Version", "1.0", ee);
+               (void) sprintf(buf, "%s.%ld/%s",
+                       ee->e_id, curtime(), MyHostName);
+               ee->e_msgboundary = newstr(buf);
+               (void) sprintf(buf, "multipart/mixed; boundary=\"%s\"",
+                                       ee->e_msgboundary);
+               addheader("Content-Type", buf, ee);
+       }
 
        /* fake up an address header for the from person */
 
        /* fake up an address header for the from person */
-       expand("\001n", buf, &buf[sizeof buf - 1], CurEnv);
-       if (parseaddr(buf, &ee->e_from, -1, '\0') == NULL)
+       expand("\201n", buf, &buf[sizeof buf - 1], e);
+       if (parseaddr(buf, &ee->e_from, 1, '\0', NULL, e) == NULL)
        {
        {
-               syserr("Can't parse myself!");
+               syserr("553 Can't parse myself!");
                ExitStat = EX_SOFTWARE;
                returndepth--;
                return (-1);
        }
                ExitStat = EX_SOFTWARE;
                returndepth--;
                return (-1);
        }
-       loweraddr(&ee->e_from);
+       ee->e_sender = ee->e_from.q_paddr;
 
        /* push state into submessage */
        CurEnv = ee;
 
        /* push state into submessage */
        CurEnv = ee;
-       define('f', "\001n", ee);
+       define('f', "\201n", ee);
        define('x', "Mail Delivery Subsystem", ee);
        define('x', "Mail Delivery Subsystem", ee);
-       eatheader(ee);
+       eatheader(ee, TRUE);
 
        /* actually deliver the error message */
        sendall(ee, SM_DEFAULT);
 
        /* restore state */
        dropenvelope(ee);
 
        /* actually deliver the error message */
        sendall(ee, SM_DEFAULT);
 
        /* restore state */
        dropenvelope(ee);
-       CurEnv = CurEnv->e_parent;
+       CurEnv = oldcur;
        returndepth--;
 
        /* should check for delivery errors here */
        returndepth--;
 
        /* should check for delivery errors here */
@@ -475,8 +549,82 @@ errbody(fp, m, e)
        register ENVELOPE *e;
 {
        register FILE *xfile;
        register ENVELOPE *e;
 {
        register FILE *xfile;
-       char buf[MAXLINE];
        char *p;
        char *p;
+       register ADDRESS *q;
+       bool printheader;
+       char buf[MAXLINE];
+
+       if (e->e_parent == NULL)
+       {
+               syserr("errbody: null parent");
+               putline("   ----- Original message lost -----\n", fp, m);
+               return;
+       }
+
+       /*
+       **  Output MIME header.
+       */
+
+       if (e->e_msgboundary != NULL)
+       {
+               putline("This is a MIME-encapsulated message", fp, m);
+               putline("", fp, m);
+               (void) sprintf(buf, "--%s", e->e_msgboundary);
+               putline(buf, fp, m);
+               putline("", fp, m);
+       }
+
+       /*
+       **  Output error message header (if specified and available).
+       */
+
+       if (ErrMsgFile != NULL)
+       {
+               if (*ErrMsgFile == '/')
+               {
+                       xfile = fopen(ErrMsgFile, "r");
+                       if (xfile != NULL)
+                       {
+                               while (fgets(buf, sizeof buf, xfile) != NULL)
+                               {
+                                       expand(buf, buf, &buf[sizeof buf - 1], e);
+                                       putline(buf, fp, m);
+                               }
+                               (void) fclose(xfile);
+                               putline("\n", fp, m);
+                       }
+               }
+               else
+               {
+                       expand(ErrMsgFile, buf, &buf[sizeof buf - 1], e);
+                       putline(buf, fp, m);
+                       putline("", fp, m);
+               }
+       }
+
+       /*
+       **  Output message introduction
+       */
+
+       printheader = TRUE;
+       for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
+       {
+               if (bitset(QBADADDR, q->q_flags))
+               {
+                       if (printheader)
+                       {
+                               putline("   ----- The following addresses failed -----",
+                                       fp, m);
+                               printheader = FALSE;
+                       }
+                       if (q->q_alias != NULL)
+                               putline(q->q_alias->q_paddr, fp, m);
+                       else
+                               putline(q->q_paddr, fp, m);
+               }
+       }
+       if (!printheader)
+               putline("\n", fp, m);
 
        /*
        **  Output transcript of errors
 
        /*
        **  Output transcript of errors
@@ -487,16 +635,16 @@ errbody(fp, m, e)
        if ((xfile = fopen(p, "r")) == NULL)
        {
                syserr("Cannot open %s", p);
        if ((xfile = fopen(p, "r")) == NULL)
        {
                syserr("Cannot open %s", p);
-               fprintf(fp, "  ----- Transcript of session is unavailable -----\n");
+               putline("   ----- Transcript of session is unavailable -----\n", fp, m);
        }
        else
        {
        }
        else
        {
-               fprintf(fp, "   ----- Transcript of session follows -----\n");
+               putline("   ----- Transcript of session follows -----\n", fp, m);
                if (e->e_xfp != NULL)
                        (void) fflush(e->e_xfp);
                while (fgets(buf, sizeof buf, xfile) != NULL)
                        putline(buf, fp, m);
                if (e->e_xfp != NULL)
                        (void) fflush(e->e_xfp);
                while (fgets(buf, sizeof buf, xfile) != NULL)
                        putline(buf, fp, m);
-               (void) fclose(xfile);
+               (void) xfclose(xfile, "errbody xscript", p);
        }
        errno = 0;
 
        }
        errno = 0;
 
@@ -505,33 +653,44 @@ errbody(fp, m, e)
        */
 
        if (NoReturn)
        */
 
        if (NoReturn)
-               fprintf(fp, "\n   ----- Return message suppressed -----\n\n");
-       else if (e->e_parent->e_dfp != NULL)
+               SendBody = FALSE;
+       putline("", fp, m);
+       if (e->e_parent->e_df != NULL)
        {
                if (SendBody)
        {
                if (SendBody)
-               {
-                       putline("\n", fp, m);
                        putline("   ----- Unsent message follows -----\n", fp, m);
                        putline("   ----- Unsent message follows -----\n", fp, m);
-                       (void) fflush(fp);
-                       putheader(fp, m, e->e_parent);
-                       putline("\n", fp, m);
-                       putbody(fp, m, e->e_parent);
-               }
                else
                else
+                       putline("   ----- Message header follows -----\n", fp, m);
+               (void) fflush(fp);
+
+               if (e->e_msgboundary != NULL)
                {
                {
-                       putline("\n", fp, m);
-                       putline("  ----- Message header follows -----\n", fp, m);
-                       (void) fflush(fp);
-                       putheader(fp, m, e->e_parent);
+                       putline("", fp, m);
+                       (void) sprintf(buf, "--%s", e->e_msgboundary);
+                       putline(buf, fp, m);
+                       putline("Content-Type: message/rfc822", fp, m);
+                       putline("", fp, m);
                }
                }
+               putheader(fp, m, e->e_parent);
+               putline("", fp, m);
+               if (SendBody)
+                       putbody(fp, m, e->e_parent, e->e_msgboundary);
+               else
+                       putline("   ----- Message body suppressed -----", fp, m);
        }
        else
        {
        }
        else
        {
-               putline("\n", fp, m);
                putline("  ----- No message was collected -----\n", fp, m);
                putline("  ----- No message was collected -----\n", fp, m);
-               putline("\n", fp, m);
        }
 
        }
 
+       if (e->e_msgboundary != NULL)
+       {
+               putline("", fp, m);
+               (void) sprintf(buf, "--%s--", e->e_msgboundary);
+               putline(buf, fp, m);
+       }
+       putline("", fp, m);
+
        /*
        **  Cleanup and exit
        */
        /*
        **  Cleanup and exit
        */
@@ -539,3 +698,62 @@ errbody(fp, m, e)
        if (errno != 0)
                syserr("errbody: I/O error");
 }
        if (errno != 0)
                syserr("errbody: I/O error");
 }
+\f/*
+**  PRUNEROUTE -- prune an RFC-822 source route
+** 
+**     Trims down a source route to the last internet-registered hop.
+**     This is encouraged by RFC 1123 section 5.3.3.
+** 
+**     Parameters:
+**             addr -- the address
+** 
+**     Returns:
+**             TRUE -- address was modified
+**             FALSE -- address could not be pruned
+** 
+**     Side Effects:
+**             modifies addr in-place
+*/
+
+pruneroute(addr)
+       char *addr;
+{
+#ifdef NAMED_BIND
+       char *start, *at, *comma;
+       char c;
+       int rcode;
+       char hostbuf[BUFSIZ];
+       char *mxhosts[MAXMXHOSTS + 1];
+
+       /* check to see if this is really a route-addr */
+       if (*addr != '<' || addr[1] != '@' || addr[strlen(addr) - 1] != '>')
+               return FALSE;
+       start = strchr(addr, ':');
+       at = strrchr(addr, '@');
+       if (start == NULL || at == NULL || at < start)
+               return FALSE;
+
+       /* slice off the angle brackets */
+       strcpy(hostbuf, at + 1);
+       hostbuf[strlen(hostbuf) - 1] = '\0';
+
+       while (start)
+       {
+               if (getmxrr(hostbuf, mxhosts, FALSE, &rcode) > 0)
+               {
+                       strcpy(addr + 1, start + 1);
+                       return TRUE;
+               }
+               c = *start;
+               *start = '\0';
+               comma = strrchr(addr, ',');
+               if (comma && comma[1] == '@')
+                       strcpy(hostbuf, comma + 2);
+               else
+                       comma = 0;
+               *start = c;
+               start = comma;
+       }
+#endif
+       return FALSE;
+}
index 6f51054..5c07b5d 100644 (file)
@@ -1,5 +1,5 @@
-.\" Copyright (c) 1988, 1991 The Regents of the University of California.
-.\" All rights reserved.
+.\" Copyright (c) 1988, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
@@ -29,9 +29,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\"     @(#)sendmail.8 6.10 (Berkeley) 8/5/91
+.\"     @(#)sendmail.8 8.1 (Berkeley) 6/16/93
 .\"
 .\"
-.Dd August 5, 1991
+.Dd June 16, 1993
 .Dt SENDMAIL 8
 .Os BSD 4
 .Sh NAME
 .Dt SENDMAIL 8
 .Os BSD 4
 .Sh NAME
@@ -80,9 +80,15 @@ expansions, e.g.,
 if `john' sends to `group',
 and `group' includes `john' in the expansion,
 then the letter will not be delivered to `john'.
 if `john' sends to `group',
 and `group' includes `john' in the expansion,
 then the letter will not be delivered to `john'.
-.Pp
-Flags are:
+.Ss Parameters
 .Bl -tag -width Fl
 .Bl -tag -width Fl
+.It Fl B Ns Ar type
+Set the body type to
+.Ar type .
+Current legal values
+.Li 7BIT
+or
+.Li 8BITMIME .
 .It Fl ba
 Go into
 .Tn ARPANET
 .It Fl ba
 Go into
 .Tn ARPANET
@@ -169,6 +175,10 @@ Set option
 to the specified
 .Em value .
 Options are described below.
 to the specified
 .Em value .
 Options are described below.
+.It Fl p Ns Ar protocol
+Set the name of the protocol used to receive the message.
+This can be a simple protocol name such as ``UUCP''
+or a protocol and hostname, such as ``UUCP:ucbvax''.
 .It Fl q Ns Bq Ar time
 Processed saved messages in the queue at given intervals.
 If
 .It Fl q Ns Bq Ar time
 Processed saved messages in the queue at given intervals.
 If
@@ -218,7 +228,7 @@ receive copies even if listed in the message header.
 Go into verbose mode.
 Alias expansions will be announced, etc.
 .El
 Go into verbose mode.
 Alias expansions will be announced, etc.
 .El
-.Pp
+.Ss Options
 There are also a number of processing options that may be set.
 Normally these will only be used by a system administrator.
 Options may be set either on the command line
 There are also a number of processing options that may be set.
 Normally these will only be used by a system administrator.
 Options may be set either on the command line
@@ -226,16 +236,26 @@ using the
 .Fl o
 flag
 or in the configuration file.
 .Fl o
 flag
 or in the configuration file.
-These are described in detail in the
+This is a partial list;
+for a complete list (and details), consult the
 .%T "Sendmail Installation and Operation Guide" .
 The options are:
 .Bl -tag -width Fl
 .It Li A Ns Ar file
 Use alternate alias file.
 .%T "Sendmail Installation and Operation Guide" .
 The options are:
 .Bl -tag -width Fl
 .It Li A Ns Ar file
 Use alternate alias file.
+.It Li b Ns Ar nblocks
+The minimum number of free blocks needed on the spool filesystem.
 .It Li c
 On mailers that are considered ``expensive'' to connect to,
 don't initiate immediate connection.
 This requires queueing.
 .It Li c
 On mailers that are considered ``expensive'' to connect to,
 don't initiate immediate connection.
 This requires queueing.
+.It Li C Ar N
+Checkpoint the queue file after every
+.Ar N
+successful deliveries (default 10).
+This avoids excessive duplicate deliveries
+when sending to long mailing lists
+interrupted by system crashes.
 .It Li d Ns Ar x
 Set the delivery mode to
 .Ar x .
 .It Li d Ns Ar x
 Set the delivery mode to
 .Ar x .
@@ -279,32 +299,40 @@ and if the sender is local to this machine,
 a copy of the message is appended to the file
 .Pa dead.letter
 in the sender's home directory.
 a copy of the message is appended to the file
 .Pa dead.letter
 in the sender's home directory.
-.It Li F Ns Ar mode
-The mode to use when creating temporary files.
 .It Li f
 Save
 .Tn UNIX Ns \-style
 From lines at the front of messages.
 .It Li f
 Save
 .Tn UNIX Ns \-style
 From lines at the front of messages.
+.It Li G
+Match local mail names against the GECOS portion of the password file.
 .It Li g Ar N
 The default group id to use when calling mailers.
 .It Li H Ns Ar file
 The
 .Tn SMTP
 help file.
 .It Li g Ar N
 The default group id to use when calling mailers.
 .It Li H Ns Ar file
 The
 .Tn SMTP
 help file.
+.It Li h Ar N
+The maximum number of times a message is allowed to ``hop''
+before we decide it is in a loop.
 .It Li i
 Do not take dots on a line by themselves
 as a message terminator.
 .It Li i
 Do not take dots on a line by themselves
 as a message terminator.
-.It Li k Ar N
-Checkpoint the queue file after every
-.Ar N
-successful deliveries (default 10).
-This avoids excessive duplicate deliveries
-when sending to long mailing lists
-interrupted by system crashes.
+.It Li j
+Send error messages in MIME format.
+.It Li K Ns Ar timeout
+Set connection cache timeout.
+.It Li k Ns Ar N
+Set connection cache size.
 .It Li L Ns Ar n
 The log level.
 .It Li L Ns Ar n
 The log level.
+.It Li l
+Pay attention to the Errors-To: header.
 .It Li m
 Send to ``me'' (the sender) also if I am in an alias expansion.
 .It Li m
 Send to ``me'' (the sender) also if I am in an alias expansion.
+.It Li n
+Validate the right hand side of aliases during a
+.Xr newaliases 1
+command.
 .It Li o
 If set, this message may have
 old style headers.
 .It Li o
 If set, this message may have
 old style headers.
@@ -315,15 +343,6 @@ If set, an adaptive algorithm is used that will correctly
 determine the header format in most cases.
 .It Li Q Ns Ar queuedir
 Select the directory in which to queue messages.
 determine the header format in most cases.
 .It Li Q Ns Ar queuedir
 Select the directory in which to queue messages.
-.It Li r Ns Ar timeout
-The timeout on reads;
-if none is set,
-.Nm sendmail
-will wait forever for a mailer.
-This option violates the word (if not the intent) of the
-.Tn SMTP
-specification,
-show the timeout should probably be fairly large.
 .It Li S Ns Ar file
 Save statistics in the named file.
 .It Li s
 .It Li S Ns Ar file
 Save statistics in the named file.
 .It Li s
@@ -349,22 +368,11 @@ This may not be available if your sendmail does not have the
 option compiled in.
 .It Li u Ns Ar N
 Set the default user id for mailers.
 option compiled in.
 .It Li u Ns Ar N
 Set the default user id for mailers.
-.It Li w
-If not set, name server lookups will us a querytype of ANY
-to find types
-.Dv CNAME , A ,
-and
-.Dv MX ,
-and will cause all existing records to be cached by our local server.
-If there is (might be) a wildcard MX in the local domain
-or its parents that are searched, you
-.ul
-must
-set this option, which will use a querytype of
-.Dv CNAME
-only;
-otherwise, it would cause all fully-qualified names
-to match as names in the local domain.
+.It Li Y
+Fork each job during queue runs.
+May be convenient on memory-poor machines.
+.It Li 7
+Strip incoming messages to seven bits.
 .El
 .Pp
 In aliases,
 .El
 .Pp
 In aliases,
@@ -446,8 +454,7 @@ these values are only approximations.
 .Bl -tag -width /usr/lib/sendmail.fc -compact
 .It Pa /etc/aliases
 raw data for alias names
 .Bl -tag -width /usr/lib/sendmail.fc -compact
 .It Pa /etc/aliases
 raw data for alias names
-.It Pa /etc/aliases.pag
-.It Pa /etc/aliases.dir
+.It Pa /etc/aliases.db
 data base of alias names
 .It Pa /etc/sendmail.cf
 configuration file
 data base of alias names
 .It Pa /etc/sendmail.cf
 configuration file
@@ -459,6 +466,8 @@ help file
 collected statistics
 .It Pa /var/spool/mqueue/*
 temp files
 collected statistics
 .It Pa /var/spool/mqueue/*
 temp files
+.It Pa /var/run/sendmail.pid
+The process id of the daemon
 .El
 .Sh SEE ALSO
 .Xr binmail 1 ,
 .El
 .Sh SEE ALSO
 .Xr binmail 1 ,
index ac757f6..c6a8554 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,7 +31,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)sendmail.h  5.17 (Berkeley) 3/12/91
+ *     @(#)sendmail.h  8.1 (Berkeley) 6/7/93
  */
 
 /*
  */
 
 /*
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
 # ifdef _DEFINE
 # define EXTERN
 # ifndef lint
-static char SmailSccsId[] =    "@(#)sendmail.h 5.17            3/12/91";
-# endif lint
-# else  _DEFINE
+static char SmailSccsId[] =    "@(#)sendmail.h 8.1             6/7/93";
+# endif
+# else /*  _DEFINE */
 # define EXTERN extern
 # define EXTERN extern
-# endif _DEFINE
+# endif /* _DEFINE */
 
 
+# include <unistd.h>
+# include <stddef.h>
+# include <stdlib.h>
 # include <stdio.h>
 # include <ctype.h>
 # include <setjmp.h>
 # include <stdio.h>
 # include <ctype.h>
 # include <setjmp.h>
+# include <sysexits.h>
+# include <string.h>
+# include <time.h>
+# include <errno.h>
+
 # include "conf.h"
 # include "useful.h"
 
 # ifdef LOG
 # include "conf.h"
 # include "useful.h"
 
 # ifdef LOG
-# include <sys/syslog.h>
-# endif LOG
+# include <syslog.h>
+# endif /* LOG */
 
 # ifdef DAEMON
 
 # ifdef DAEMON
-# ifdef VMUNIX
 # include <sys/socket.h>
 # include <sys/socket.h>
+# endif
+# ifdef NETINET
 # include <netinet/in.h>
 # include <netinet/in.h>
-# endif VMUNIX
-# endif DAEMON
+# endif
+# ifdef NETISO
+# include <netiso/iso.h>
+# endif
+# ifdef NETNS
+# include <netns/ns.h>
+# endif
+# ifdef NETX25
+# include <netccitt/x25.h>
+# endif
 
 
 
 
-# define PSBUFSIZE     (MAXNAME + MAXATOM)     /* size of prescan buffer */
 
 
 /*
 
 
 /*
@@ -108,12 +124,13 @@ struct address
        char            *q_host;        /* host name */
        struct mailer   *q_mailer;      /* mailer to use */
        u_short         q_flags;        /* status flags, see below */
        char            *q_host;        /* host name */
        struct mailer   *q_mailer;      /* mailer to use */
        u_short         q_flags;        /* status flags, see below */
-       short           q_uid;          /* user-id of receiver (if known) */
-       short           q_gid;          /* group-id of receiver (if known) */
+       uid_t           q_uid;          /* user-id of receiver (if known) */
+       gid_t           q_gid;          /* group-id of receiver (if known) */
        char            *q_home;        /* home dir (local mailer only) */
        char            *q_fullname;    /* full name if known */
        struct address  *q_next;        /* chain */
        struct address  *q_alias;       /* address this results from */
        char            *q_home;        /* home dir (local mailer only) */
        char            *q_fullname;    /* full name if known */
        struct address  *q_next;        /* chain */
        struct address  *q_alias;       /* address this results from */
+       char            *q_owner;       /* owner of q_alias */
        struct address  *q_tchain;      /* temporary use chain */
        time_t          q_timeout;      /* timeout for this address */
 };
        struct address  *q_tchain;      /* temporary use chain */
        time_t          q_timeout;      /* timeout for this address */
 };
@@ -126,6 +143,9 @@ typedef struct address ADDRESS;
 # define QPRIMARY      000010  /* set from argv */
 # define QQUEUEUP      000020  /* queue for later transmission */
 # define QSENT         000040  /* has been successfully delivered */
 # define QPRIMARY      000010  /* set from argv */
 # define QQUEUEUP      000020  /* queue for later transmission */
 # define QSENT         000040  /* has been successfully delivered */
+# define QNOTREMOTE    000100  /* not an address for remote forwarding */
+# define QSELFREF      000200  /* this address references itself */
+# define QVERIFIED     000400  /* verified, but not expanded */
 \f/*
 **  Mailer definition structure.
 **     Every mailer known to the system is declared in this
 \f/*
 **  Mailer definition structure.
 **     Every mailer known to the system is declared in this
@@ -145,38 +165,57 @@ struct mailer
        BITMAP  m_flags;        /* status flags, see below */
        short   m_mno;          /* mailer number internally */
        char    **m_argv;       /* template argument vector */
        BITMAP  m_flags;        /* status flags, see below */
        short   m_mno;          /* mailer number internally */
        char    **m_argv;       /* template argument vector */
-       short   m_s_rwset;      /* rewriting set for sender addresses */
-       short   m_r_rwset;      /* rewriting set for recipient addresses */
+       short   m_sh_rwset;     /* rewrite set: sender header addresses */
+       short   m_se_rwset;     /* rewrite set: sender envelope addresses */
+       short   m_rh_rwset;     /* rewrite set: recipient header addresses */
+       short   m_re_rwset;     /* rewrite set: recipient envelope addresses */
        char    *m_eol;         /* end of line string */
        long    m_maxsize;      /* size limit on message to this mailer */
        char    *m_eol;         /* end of line string */
        long    m_maxsize;      /* size limit on message to this mailer */
+       int     m_linelimit;    /* max # characters per line */
+       char    *m_execdir;     /* directory to chdir to before execv */
 };
 
 typedef struct mailer  MAILER;
 
 /* bits for m_flags */
 };
 
 typedef struct mailer  MAILER;
 
 /* bits for m_flags */
+# define M_ESMTP       'a'     /* run Extended SMTP protocol */
+# define M_BLANKEND    'b'     /* ensure blank line at end of message */
+# define M_NOCOMMENT   'c'     /* don't include comment part of address */
 # define M_CANONICAL   'C'     /* make addresses canonical "u@dom" */
 # define M_CANONICAL   'C'     /* make addresses canonical "u@dom" */
+               /*      'D'     /* CF: include Date: */
 # define M_EXPENSIVE   'e'     /* it costs to use this mailer.... */
 # define M_ESCFROM     'E'     /* escape From lines to >From */
 # define M_FOPT                'f'     /* mailer takes picky -f flag */
 # define M_EXPENSIVE   'e'     /* it costs to use this mailer.... */
 # define M_ESCFROM     'E'     /* escape From lines to >From */
 # define M_FOPT                'f'     /* mailer takes picky -f flag */
+               /*      'F'     /* CF: include From: or Resent-From: */
+# define M_NO_NULL_FROM        'g'     /* sender of errors should be $g */
 # define M_HST_UPPER   'h'     /* preserve host case distinction */
 # define M_HST_UPPER   'h'     /* preserve host case distinction */
+               /*      'H'     /* UIUC: MAIL11V3: preview headers */
 # define M_INTERNAL    'I'     /* SMTP to another sendmail site */
 # define M_INTERNAL    'I'     /* SMTP to another sendmail site */
-# define M_LOCAL       'l'     /* delivery is to this host */
+# define M_LOCALMAILER 'l'     /* delivery is to this host */
 # define M_LIMITS      'L'     /* must enforce SMTP line limits */
 # define M_MUSER       'm'     /* can handle multiple users at once */
 # define M_LIMITS      'L'     /* must enforce SMTP line limits */
 # define M_MUSER       'm'     /* can handle multiple users at once */
+               /*      'M'     /* CF: include Message-Id: */
 # define M_NHDR                'n'     /* don't insert From line */
 # define M_NHDR                'n'     /* don't insert From line */
+               /*      'N'     /* UIUC: MAIL11V3: DATA returns multi-status */
 # define M_FROMPATH    'p'     /* use reverse-path in MAIL FROM: */
 # define M_FROMPATH    'p'     /* use reverse-path in MAIL FROM: */
+               /*      'P'     /* CF: include Return-Path: */
 # define M_ROPT                'r'     /* mailer takes picky -r flag */
 # define M_SECURE_PORT 'R'     /* try to send on a reserved TCP port */
 # define M_STRIPQ      's'     /* strip quote chars from user/host */
 # define M_RESTR       'S'     /* must be daemon to execute */
 # define M_USR_UPPER   'u'     /* preserve user case distinction */
 # define M_UGLYUUCP    'U'     /* this wants an ugly UUCP from line */
 # define M_ROPT                'r'     /* mailer takes picky -r flag */
 # define M_SECURE_PORT 'R'     /* try to send on a reserved TCP port */
 # define M_STRIPQ      's'     /* strip quote chars from user/host */
 # define M_RESTR       'S'     /* must be daemon to execute */
 # define M_USR_UPPER   'u'     /* preserve user case distinction */
 # define M_UGLYUUCP    'U'     /* this wants an ugly UUCP from line */
+               /*      'V'     /* UIUC: !-relativize all addresses */
+               /*      'x'     /* CF: include Full-Name: */
 # define M_XDOT                'X'     /* use hidden-dot algorithm */
 # define M_XDOT                'X'     /* use hidden-dot algorithm */
+# define M_7BITS       '7'     /* use 7-bit path */
 
 EXTERN MAILER  *Mailer[MAXMAILERS+1];
 
 EXTERN MAILER  *LocalMailer;           /* ptr to local mailer */
 EXTERN MAILER  *ProgMailer;            /* ptr to program mailer */
 
 EXTERN MAILER  *Mailer[MAXMAILERS+1];
 
 EXTERN MAILER  *LocalMailer;           /* ptr to local mailer */
 EXTERN MAILER  *ProgMailer;            /* ptr to program mailer */
+EXTERN MAILER  *FileMailer;            /* ptr to *file* mailer */
+EXTERN MAILER  *InclMailer;            /* ptr to *include* mailer */
 \f/*
 **  Header structure.
 **     This structure is used internally to store header items.
 \f/*
 **  Header structure.
 **     This structure is used internally to store header items.
@@ -218,6 +257,8 @@ extern struct hdrinfo       HdrInfo[];
 # define H_TRACE       00200   /* this field contains trace information */
 # define H_FROM                00400   /* this is a from-type field */
 # define H_VALID       01000   /* this field has a validated value */
 # define H_TRACE       00200   /* this field contains trace information */
 # define H_FROM                00400   /* this is a from-type field */
 # define H_VALID       01000   /* this field has a validated value */
+# define H_RECEIPTTO   02000   /* this field has return receipt info */
+# define H_ERRORSTO    04000   /* this field has error address info */
 \f/*
 **  Envelope structure.
 **     This structure defines the message itself.  There is usually
 \f/*
 **  Envelope structure.
 **     This structure defines the message itself.  There is usually
@@ -227,7 +268,9 @@ extern struct hdrinfo       HdrInfo[];
 **     will have their own envelope.
 */
 
 **     will have their own envelope.
 */
 
-struct envelope
+# define ENVELOPE      struct envelope
+
+ENVELOPE
 {
        HDR             *e_header;      /* head of header list */
        long            e_msgpriority;  /* adjusted priority of this message */
 {
        HDR             *e_header;      /* head of header list */
        long            e_msgpriority;  /* adjusted priority of this message */
@@ -235,6 +278,7 @@ struct envelope
        char            *e_to;          /* the target person */
        char            *e_receiptto;   /* return receipt address */
        ADDRESS         e_from;         /* the person it is from */
        char            *e_to;          /* the target person */
        char            *e_receiptto;   /* return receipt address */
        ADDRESS         e_from;         /* the person it is from */
+       char            *e_sender;      /* e_from.q_paddr w comments stripped */
        char            **e_fromdomain; /* the domain part of the sender */
        ADDRESS         *e_sendqueue;   /* list of message recipients */
        ADDRESS         *e_errorqueue;  /* the queue for error responses */
        char            **e_fromdomain; /* the domain part of the sender */
        ADDRESS         *e_sendqueue;   /* list of message recipients */
        ADDRESS         *e_errorqueue;  /* the queue for error responses */
@@ -243,20 +287,27 @@ struct envelope
        short           e_class;        /* msg class (priority, junk, etc.) */
        short           e_flags;        /* flags, see below */
        short           e_hopcount;     /* number of times processed */
        short           e_class;        /* msg class (priority, junk, etc.) */
        short           e_flags;        /* flags, see below */
        short           e_hopcount;     /* number of times processed */
-       int             (*e_puthdr)();  /* function to put header of message */
-       int             (*e_putbody)(); /* function to put body of message */
+       short           e_nsent;        /* number of sends since checkpoint */
+       short           e_sendmode;     /* message send mode */
+       short           e_errormode;    /* error return mode */
+       int             (*e_puthdr)__P((FILE *, MAILER *, ENVELOPE *));
+                                       /* function to put header of message */
+       int             (*e_putbody)__P((FILE *, MAILER *, ENVELOPE *, char *));
+                                       /* function to put body of message */
        struct envelope *e_parent;      /* the message this one encloses */
        struct envelope *e_sibling;     /* the next envelope of interest */
        struct envelope *e_parent;      /* the message this one encloses */
        struct envelope *e_sibling;     /* the next envelope of interest */
+       char            *e_bodytype;    /* type of message body */
        char            *e_df;          /* location of temp file */
        FILE            *e_dfp;         /* temporary file */
        char            *e_id;          /* code for this entry in queue */
        FILE            *e_xfp;         /* transcript file */
        char            *e_df;          /* location of temp file */
        FILE            *e_dfp;         /* temporary file */
        char            *e_id;          /* code for this entry in queue */
        FILE            *e_xfp;         /* transcript file */
+       FILE            *e_lockfp;      /* the lock file for this message */
        char            *e_message;     /* error message */
        char            *e_message;     /* error message */
+       char            *e_statmsg;     /* stat msg (changes per delivery) */
+       char            *e_msgboundary; /* MIME-style message part boundary */
        char            *e_macro[128];  /* macro definitions */
 };
 
        char            *e_macro[128];  /* macro definitions */
 };
 
-typedef struct envelope        ENVELOPE;
-
 /* values for e_flags */
 #define EF_OLDSTYLE    000001          /* use spaces (not commas) in hdrs */
 #define EF_INQUEUE     000002          /* this message is fully queued */
 /* values for e_flags */
 #define EF_OLDSTYLE    000001          /* use spaces (not commas) in hdrs */
 #define EF_INQUEUE     000002          /* this message is fully queued */
@@ -267,6 +318,9 @@ typedef struct envelope     ENVELOPE;
 #define EF_KEEPQUEUE   000100          /* keep queue files always */
 #define EF_RESPONSE    000200          /* this is an error or return receipt */
 #define EF_RESENT      000400          /* this message is being forwarded */
 #define EF_KEEPQUEUE   000100          /* keep queue files always */
 #define EF_RESPONSE    000200          /* this is an error or return receipt */
 #define EF_RESENT      000400          /* this message is being forwarded */
+#define EF_VRFYONLY    001000          /* verify only (don't expand aliases) */
+#define EF_WARNING     002000          /* warning message has been sent */
+#define EF_QUEUERUN    004000          /* this envelope is from queue */
 
 EXTERN ENVELOPE        *CurEnv;        /* envelope currently being processed */
 \f/*
 
 EXTERN ENVELOPE        *CurEnv;        /* envelope currently being processed */
 \f/*
@@ -323,55 +377,175 @@ EXTERN struct rewrite    *RewriteRules[MAXRWSETS];
 */
 
 /* left hand side items */
 */
 
 /* left hand side items */
-# define MATCHZANY     '\020'  /* match zero or more tokens */
-# define MATCHANY      '\021'  /* match one or more tokens */
-# define MATCHONE      '\022'  /* match exactly one token */
-# define MATCHCLASS    '\023'  /* match one token in a class */
-# define MATCHNCLASS   '\024'  /* match anything not in class */
-# define MATCHREPL     '\025'  /* replacement on RHS for above */
+# define MATCHZANY     0220    /* match zero or more tokens */
+# define MATCHANY      0221    /* match one or more tokens */
+# define MATCHONE      0222    /* match exactly one token */
+# define MATCHCLASS    0223    /* match one token in a class */
+# define MATCHNCLASS   0224    /* match anything not in class */
+# define MATCHREPL     0225    /* replacement on RHS for above */
 
 /* right hand side items */
 
 /* right hand side items */
-# define CANONNET      '\026'  /* canonical net, next token */
-# define CANONHOST     '\027'  /* canonical host, next token */
-# define CANONUSER     '\030'  /* canonical user, next N tokens */
-# define CALLSUBR      '\031'  /* call another rewriting set */
+# define CANONNET      0226    /* canonical net, next token */
+# define CANONHOST     0227    /* canonical host, next token */
+# define CANONUSER     0230    /* canonical user, next N tokens */
+# define CALLSUBR      0231    /* call another rewriting set */
 
 /* conditionals in macros */
 
 /* conditionals in macros */
-# define CONDIF                '\032'  /* conditional if-then */
-# define CONDELSE      '\033'  /* conditional else */
-# define CONDFI                '\034'  /* conditional fi */
+# define CONDIF                0232    /* conditional if-then */
+# define CONDELSE      0233    /* conditional else */
+# define CONDFI                0234    /* conditional fi */
 
 /* bracket characters for host name lookup */
 
 /* bracket characters for host name lookup */
-# define HOSTBEGIN     '\035'  /* hostname lookup begin */
-# define HOSTEND       '\036'  /* hostname lookup end */
+# define HOSTBEGIN     0235    /* hostname lookup begin */
+# define HOSTEND       0236    /* hostname lookup end */
+
+/* bracket characters for generalized lookup */
+# define LOOKUPBEGIN   0205    /* generalized lookup begin */
+# define LOOKUPEND     0206    /* generalized lookup end */
+
+/* macro substitution character */
+# define MACROEXPAND   0201    /* macro expansion */
+# define MACRODEXPAND  0202    /* deferred macro expansion */
 
 
-/* \001 is also reserved as the macro expansion character */
+/* to make the code clearer */
+# define MATCHZERO     CANONHOST
+
+/* external <==> internal mapping table */
+struct metamac
+{
+       char    metaname;       /* external code (after $) */
+       char    metaval;        /* internal code (as above) */
+};
 \f/*
 \f/*
-**  Information about hosts that we have looked up recently.
+**  Information about currently open connections to mailers, or to
+**  hosts that we have looked up recently.
+*/
+
+# define MCI   struct mailer_con_info
+
+MCI
+{
+       short           mci_flags;      /* flag bits, see below */
+       short           mci_errno;      /* error number on last connection */
+       short           mci_exitstat;   /* exit status from last connection */
+       short           mci_state;      /* SMTP state */
+       long            mci_maxsize;    /* max size this server will accept */
+       FILE            *mci_in;        /* input side of connection */
+       FILE            *mci_out;       /* output side of connection */
+       int             mci_pid;        /* process id of subordinate proc */
+       char            *mci_phase;     /* SMTP phase string */
+       struct mailer   *mci_mailer;    /* ptr to the mailer for this conn */
+       char            *mci_host;      /* host name */
+       time_t          mci_lastuse;    /* last usage time */
+};
+
+
+/* flag bits */
+#define MCIF_VALID     000001          /* this entry is valid */
+#define MCIF_TEMP      000002          /* don't cache this connection */
+#define MCIF_CACHED    000004          /* currently in open cache */
+#define MCIF_ESMTP     000010          /* this host speaks ESMTP */
+#define MCIF_EXPN      000020          /* EXPN command supported */
+#define MCIF_SIZE      000040          /* SIZE option supported */
+#define MCIF_8BITMIME  000100          /* BODY=8BITMIME supported */
+
+/* states */
+#define MCIS_CLOSED    0               /* no traffic on this connection */
+#define MCIS_OPENING   1               /* sending initial protocol */
+#define MCIS_OPEN      2               /* open, initial protocol sent */
+#define MCIS_ACTIVE    3               /* message being sent */
+#define MCIS_QUITING   4               /* running quit protocol */
+#define MCIS_SSD       5               /* service shutting down */
+#define MCIS_ERROR     6               /* I/O error on connection */
+\f/*
+**  Name canonification short circuit.
 **
 **
-**     This stuff is 4.2/3bsd specific.
+**     If the name server for a host is down, the process of trying to
+**     canonify the name can hang.  This is similar to (but alas, not
+**     identical to) looking up the name for delivery.  This stab type
+**     caches the result of the name server lookup so we don't hang
+**     multiple times.
 */
 
 */
 
-# ifdef DAEMON
-# ifdef VMUNIX
+#define NAMECANON      struct _namecanon
+
+NAMECANON
+{
+       short           nc_errno;       /* cached errno */
+       short           nc_herrno;      /* cached h_errno */
+       short           nc_stat;        /* cached exit status code */
+       short           nc_flags;       /* flag bits */
+       char            *nc_cname;      /* the canonical name */
+};
+
+/* values for nc_flags */
+#define NCF_VALID      0x0001  /* entry valid */
+\f/*
+**  Mapping functions
+**
+**     These allow arbitrary mappings in the config file.  The idea
+**     (albeit not the implementation) comes from IDA sendmail.
+*/
+
+# define MAPCLASS      struct _mapclass
+# define MAP           struct _map
+
 
 
-# define HOSTINFO      struct hostinfo
+/*
+**  An actual map.
+*/
 
 
-HOSTINFO
+MAP
 {
 {
-       char            *ho_name;       /* name of this host */
-       struct in_addr  ho_inaddr;      /* internet address */
-       short           ho_flags;       /* flag bits, see below */
-       short           ho_errno;       /* error number on last connection */
-       short           ho_exitstat;    /* exit status from last connection */
+       MAPCLASS        *map_class;     /* the class of this map */
+       char            *map_mname;     /* name of this map */
+       int             map_mflags;     /* flags, see below */
+       char            *map_file;      /* the (nominal) filename */
+       void            *map_db1;       /* the open database ptr */
+       void            *map_db2;       /* an "extra" database pointer */
+       char            *map_app;       /* to append to successful matches */
+       char            *map_domain;    /* the (nominal) NIS domain */
+       char            *map_rebuild;   /* program to run to do auto-rebuild */
 };
 
 };
 
+/* bit values for map_flags */
+# define MF_VALID      0x0001          /* this entry is valid */
+# define MF_INCLNULL   0x0002          /* include null byte in key */
+# define MF_OPTIONAL   0x0004          /* don't complain if map not found */
+# define MF_NOFOLDCASE 0x0008          /* don't fold case in keys */
+# define MF_MATCHONLY  0x0010          /* don't use the map value */
+# define MF_OPEN       0x0020          /* this entry is open */
+# define MF_WRITABLE   0x0040          /* open for writing */
+# define MF_ALIAS      0x0080          /* this is an alias file */
+# define MF_IMPL_HASH  0x1000          /* implicit: underlying hash database */
+# define MF_IMPL_NDBM  0x2000          /* implicit: underlying NDBM database */
 
 
-/* flag bits */
-#define HOF_VALID      00001           /* this entry is valid */
 
 
-# endif VMUNIX
-# endif DAEMON
+/*
+**  The class of a map -- essentially the functions to call
+*/
+
+MAPCLASS
+{
+       char    *map_cname;             /* name of this map class */
+       char    *map_ext;               /* extension for database file */
+       short   map_cflags;             /* flag bits, see below */
+       bool    (*map_parse)__P((MAP *, char *));
+                                       /* argument parsing function */
+       char    *(*map_lookup)__P((MAP *, char *, char **, int *));
+                                       /* lookup function */
+       void    (*map_store)__P((MAP *, char *, char *));
+                                       /* store function */
+       bool    (*map_open)__P((MAP *, int));
+                                       /* open function */
+       void    (*map_close)__P((MAP *));
+                                       /* close function */
+};
+
+/* bit values for map_cflags */
+#define MCF_ALIASOK    0x0001          /* can be used for aliases */
+#define MCF_ALIASONLY  0x0002          /* usable only for aliases */
+#define MCF_REBUILDABLE        0x0004          /* can rebuild alias files */
 \f/*
 **  Symbol table definitions
 */
 \f/*
 **  Symbol table definitions
 */
@@ -387,9 +561,11 @@ struct symtab
                ADDRESS         *sv_addr;       /* pointer to address header */
                MAILER          *sv_mailer;     /* pointer to mailer */
                char            *sv_alias;      /* alias */
                ADDRESS         *sv_addr;       /* pointer to address header */
                MAILER          *sv_mailer;     /* pointer to mailer */
                char            *sv_alias;      /* alias */
-# ifdef HOSTINFO
-               HOSTINFO        sv_host;        /* host information */
-# endif HOSTINFO
+               MAPCLASS        sv_mapclass;    /* mapping function class */
+               MAP             sv_map;         /* mapping function */
+               char            *sv_hostsig;    /* host signature */
+               MCI             sv_mci;         /* mailer connection info */
+               NAMECANON       sv_namecanon;   /* canonical name cache */
        }       s_value;
 };
 
        }       s_value;
 };
 
@@ -401,15 +577,24 @@ typedef struct symtab     STAB;
 # define ST_ADDRESS    2       /* an address in parsed format */
 # define ST_MAILER     3       /* a mailer header */
 # define ST_ALIAS      4       /* an alias */
 # define ST_ADDRESS    2       /* an address in parsed format */
 # define ST_MAILER     3       /* a mailer header */
 # define ST_ALIAS      4       /* an alias */
-# define ST_HOST       5       /* host information */
+# define ST_MAPCLASS   5       /* mapping function class */
+# define ST_MAP                6       /* mapping function */
+# define ST_HOSTSIG    7       /* host signature */
+# define ST_NAMECANON  8       /* cached canonical name */
+# define ST_MCI                16      /* mailer connection info (offset) */
 
 # define s_class       s_value.sv_class
 # define s_address     s_value.sv_addr
 # define s_mailer      s_value.sv_mailer
 # define s_alias       s_value.sv_alias
 
 # define s_class       s_value.sv_class
 # define s_address     s_value.sv_addr
 # define s_mailer      s_value.sv_mailer
 # define s_alias       s_value.sv_alias
-# define s_host                s_value.sv_host
+# define s_mci         s_value.sv_mci
+# define s_mapclass    s_value.sv_mapclass
+# define s_hostsig     s_value.sv_hostsig
+# define s_map         s_value.sv_map
+# define s_namecanon   s_value.sv_namecanon
 
 
-extern STAB    *stab();
+extern STAB            *stab __P((char *, int, int));
+extern void            stabapply __P((void (*)(STAB *, int), int));
 
 /* opcodes to stab */
 # define ST_FIND       0       /* find entry */
 
 /* opcodes to stab */
 # define ST_FIND       0       /* find entry */
@@ -426,7 +611,8 @@ extern STAB *stab();
 struct event
 {
        time_t          ev_time;        /* time of the function call */
 struct event
 {
        time_t          ev_time;        /* time of the function call */
-       int             (*ev_func)();   /* function to call */
+       int             (*ev_func)__P((int));
+                                       /* function to call */
        int             ev_arg;         /* argument to ev_func */
        int             ev_pid;         /* pid that set this event */
        struct event    *ev_link;       /* link to next item */
        int             ev_arg;         /* argument to ev_func */
        int             ev_pid;         /* pid that set this event */
        struct event    *ev_link;       /* link to next item */
@@ -454,7 +640,6 @@ EXTERN EVENT        *EventQueue;            /* head of event queue */
 EXTERN char    OpMode;         /* operation mode, see below */
 
 #define MD_DELIVER     'm'             /* be a mail sender */
 EXTERN char    OpMode;         /* operation mode, see below */
 
 #define MD_DELIVER     'm'             /* be a mail sender */
-#define MD_ARPAFTP     'a'             /* old-style arpanet protocols */
 #define MD_SMTP                's'             /* run SMTP on standard input */
 #define MD_DAEMON      'd'             /* run as a daemon */
 #define MD_VERIFY      'v'             /* verify: don't collect or deliver */
 #define MD_SMTP                's'             /* run SMTP on standard input */
 #define MD_DAEMON      'd'             /* run as a daemon */
 #define MD_VERIFY      'v'             /* verify: don't collect or deliver */
@@ -464,8 +649,7 @@ EXTERN char OpMode;         /* operation mode, see below */
 #define MD_FREEZE      'z'             /* freeze the configuration file */
 
 
 #define MD_FREEZE      'z'             /* freeze the configuration file */
 
 
-EXTERN char    SendMode;       /* send mode, see below */
-
+/* values for e_sendmode -- send modes */
 #define SM_DELIVER     'i'             /* interactive delivery */
 #define SM_QUICKD      'j'             /* deliver w/o queueing */
 #define SM_FORK                'b'             /* deliver in background */
 #define SM_DELIVER     'i'             /* interactive delivery */
 #define SM_QUICKD      'j'             /* deliver w/o queueing */
 #define SM_FORK                'b'             /* deliver in background */
@@ -476,25 +660,83 @@ EXTERN char       SendMode;       /* send mode, see below */
 #define SM_DEFAULT     '\0'            /* unspecified, use SendMode */
 
 
 #define SM_DEFAULT     '\0'            /* unspecified, use SendMode */
 
 
-EXTERN char    ErrorMode;      /* error mode, see below */
-
+/* values for e_errormode -- error handling modes */
 #define EM_PRINT       'p'             /* print errors */
 #define EM_MAIL                'm'             /* mail back errors */
 #define EM_WRITE       'w'             /* write back errors */
 #define EM_BERKNET     'e'             /* special berknet processing */
 #define EM_QUIET       'q'             /* don't print messages (stat only) */
 #define EM_PRINT       'p'             /* print errors */
 #define EM_MAIL                'm'             /* mail back errors */
 #define EM_WRITE       'w'             /* write back errors */
 #define EM_BERKNET     'e'             /* special berknet processing */
 #define EM_QUIET       'q'             /* don't print messages (stat only) */
+\f/*
+**  Additional definitions
+*/
 
 
-/* offset used to issure that the error messages for name server error
- * codes are unique.
- */
+
+/* Offset used to ensure that name server error * codes are unique */
 #define        MAX_ERRNO       100
 #define        MAX_ERRNO       100
+
+
+/*
+**  Privacy flags
+**     These are bit values for the PrivacyFlags word.
+*/
+
+#define PRIV_PUBLIC            0       /* what have I got to hide? */
+#define PRIV_NEEDMAILHELO      00001   /* insist on HELO for MAIL, at least */
+#define PRIV_NEEDEXPNHELO      00002   /* insist on HELO for EXPN */
+#define PRIV_NEEDVRFYHELO      00004   /* insist on HELO for VRFY */
+#define PRIV_NOEXPN            00010   /* disallow EXPN command entirely */
+#define PRIV_NOVRFY            00020   /* disallow VRFY command entirely */
+#define PRIV_AUTHWARNINGS      00040   /* flag possible authorization probs */
+#define PRIV_RESTRMAILQ                01000   /* restrict mailq command */
+#define PRIV_GOAWAY            00777   /* don't give no info, anyway, anyhow */
+
+/* struct defining such things */
+struct prival
+{
+       char    *pv_name;       /* name of privacy flag */
+       int     pv_flag;        /* numeric level */
+};
+
+
+/*
+**  Flags passed to remotename
+*/
+
+#define RF_SENDERADDR          0001    /* this is a sender address */
+#define RF_HEADERADDR          0002    /* this is a header address */
+#define RF_CANONICAL           0004    /* strip comment information */
+#define RF_ADDDOMAIN           0010    /* OK to do domain extension */
+
+
+/*
+**  Regular UNIX sockaddrs are too small to handle ISO addresses, so
+**  we are forced to declare a supertype here.
+*/
+
+union bigsockaddr
+{
+       struct sockaddr         sa;     /* general version */
+#ifdef NETINET
+       struct sockaddr_in      sin;    /* INET family */
+#endif
+#ifdef NETISO
+       struct sockaddr_iso     siso;   /* ISO family */
+#endif
+#ifdef NETNS
+       struct sockaddr_ns      sns;    /* XNS family */
+#endif
+#ifdef NETX25
+       struct sockaddr_x25     sx25;   /* X.25 family */
+#endif
+};
+
+#define SOCKADDR       union bigsockaddr
+
 \f/*
 **  Global variables.
 */
 
 EXTERN bool    FromFlag;       /* if set, "From" person is explicit */
 \f/*
 **  Global variables.
 */
 
 EXTERN bool    FromFlag;       /* if set, "From" person is explicit */
-EXTERN bool    NoAlias;        /* if set, don't do any aliasing */
-EXTERN bool    ForceMail;      /* if set, mail even if already got a copy */
 EXTERN bool    MeToo;          /* send to the sender also */
 EXTERN bool    IgnrDot;        /* don't let dot end messages */
 EXTERN bool    SaveFrom;       /* save leading "From" lines */
 EXTERN bool    MeToo;          /* send to the sender also */
 EXTERN bool    IgnrDot;        /* don't let dot end messages */
 EXTERN bool    SaveFrom;       /* save leading "From" lines */
@@ -502,64 +744,105 @@ EXTERN bool      Verbose;        /* set if blow-by-blow desired */
 EXTERN bool    GrabTo;         /* if set, get recipients from msg */
 EXTERN bool    NoReturn;       /* don't return letter to sender */
 EXTERN bool    SuprErrs;       /* set if we are suppressing errors */
 EXTERN bool    GrabTo;         /* if set, get recipients from msg */
 EXTERN bool    NoReturn;       /* don't return letter to sender */
 EXTERN bool    SuprErrs;       /* set if we are suppressing errors */
-EXTERN bool    QueueRun;       /* currently running message from the queue */
 EXTERN bool    HoldErrs;       /* only output errors to transcript */
 EXTERN bool    NoConnect;      /* don't connect to non-local mailers */
 EXTERN bool    SuperSafe;      /* be extra careful, even if expensive */
 EXTERN bool    ForkQueueRuns;  /* fork for each job when running the queue */
 EXTERN bool    AutoRebuild;    /* auto-rebuild the alias database as needed */
 EXTERN bool    CheckAliases;   /* parse addresses during newaliases */
 EXTERN bool    HoldErrs;       /* only output errors to transcript */
 EXTERN bool    NoConnect;      /* don't connect to non-local mailers */
 EXTERN bool    SuperSafe;      /* be extra careful, even if expensive */
 EXTERN bool    ForkQueueRuns;  /* fork for each job when running the queue */
 EXTERN bool    AutoRebuild;    /* auto-rebuild the alias database as needed */
 EXTERN bool    CheckAliases;   /* parse addresses during newaliases */
+EXTERN bool    NoAlias;        /* suppress aliasing */
 EXTERN bool    UseNameServer;  /* use internet domain name server */
 EXTERN bool    UseNameServer;  /* use internet domain name server */
+EXTERN bool    SevenBit;       /* force 7-bit data */
 EXTERN int     SafeAlias;      /* minutes to wait until @:@ in alias file */
 EXTERN int     SafeAlias;      /* minutes to wait until @:@ in alias file */
-EXTERN time_t  TimeOut;        /* time until timeout */
 EXTERN FILE    *InChannel;     /* input connection */
 EXTERN FILE    *OutChannel;    /* output connection */
 EXTERN FILE    *InChannel;     /* input connection */
 EXTERN FILE    *OutChannel;    /* output connection */
-EXTERN int     RealUid;        /* when Daemon, real uid of caller */
-EXTERN int     RealGid;        /* when Daemon, real gid of caller */
-EXTERN int     DefUid;         /* default uid to run as */
+EXTERN uid_t   RealUid;        /* when Daemon, real uid of caller */
+EXTERN gid_t   RealGid;        /* when Daemon, real gid of caller */
+EXTERN uid_t   DefUid;         /* default uid to run as */
+EXTERN gid_t   DefGid;         /* default gid to run as */
 EXTERN char    *DefUser;       /* default user to run as (from DefUid) */
 EXTERN char    *DefUser;       /* default user to run as (from DefUid) */
-EXTERN int     DefGid;         /* default gid to run as */
 EXTERN int     OldUmask;       /* umask when sendmail starts up */
 EXTERN int     Errors;         /* set if errors (local to single pass) */
 EXTERN int     ExitStat;       /* exit status code */
 EXTERN int     AliasLevel;     /* depth of aliasing */
 EXTERN int     OldUmask;       /* umask when sendmail starts up */
 EXTERN int     Errors;         /* set if errors (local to single pass) */
 EXTERN int     ExitStat;       /* exit status code */
 EXTERN int     AliasLevel;     /* depth of aliasing */
-EXTERN int     MotherPid;      /* proc id of parent process */
 EXTERN int     LineNumber;     /* line number in current input */
 EXTERN int     LineNumber;     /* line number in current input */
-EXTERN time_t  ReadTimeout;    /* timeout on reads */
 EXTERN int     LogLevel;       /* level of logging to perform */
 EXTERN int     FileMode;       /* mode on files */
 EXTERN int     QueueLA;        /* load average starting forced queueing */
 EXTERN int     RefuseLA;       /* load average refusing connections are */
 EXTERN int     LogLevel;       /* level of logging to perform */
 EXTERN int     FileMode;       /* mode on files */
 EXTERN int     QueueLA;        /* load average starting forced queueing */
 EXTERN int     RefuseLA;       /* load average refusing connections are */
-EXTERN int     QueueFactor;    /* slope of queue function */
+EXTERN int     CurrentLA;      /* current load average */
+EXTERN long    QueueFactor;    /* slope of queue function */
 EXTERN time_t  QueueIntvl;     /* intervals between running the queue */
 EXTERN time_t  QueueIntvl;     /* intervals between running the queue */
-EXTERN char    *AliasFile;     /* location of alias file */
 EXTERN char    *HelpFile;      /* location of SMTP help file */
 EXTERN char    *HelpFile;      /* location of SMTP help file */
+EXTERN char    *ErrMsgFile;    /* file to prepend to all error messages */
 EXTERN char    *StatFile;      /* location of statistics summary */
 EXTERN char    *QueueDir;      /* location of queue directory */
 EXTERN char    *FileName;      /* name to print on error messages */
 EXTERN char    *SmtpPhase;     /* current phase in SMTP processing */
 EXTERN char    *MyHostName;    /* name of this host for SMTP messages */
 EXTERN char    *RealHostName;  /* name of host we are talking to */
 EXTERN char    *StatFile;      /* location of statistics summary */
 EXTERN char    *QueueDir;      /* location of queue directory */
 EXTERN char    *FileName;      /* name to print on error messages */
 EXTERN char    *SmtpPhase;     /* current phase in SMTP processing */
 EXTERN char    *MyHostName;    /* name of this host for SMTP messages */
 EXTERN char    *RealHostName;  /* name of host we are talking to */
-EXTERN struct  sockaddr_in RealHostAddr;/* address of host we are talking to */
+EXTERN SOCKADDR RealHostAddr;  /* address of host we are talking to */
 EXTERN char    *CurHostName;   /* current host we are dealing with */
 EXTERN jmp_buf TopFrame;       /* branch-to-top-of-loop-on-error frame */
 EXTERN bool    QuickAbort;     /*  .... but only if we want a quick abort */
 EXTERN char    *CurHostName;   /* current host we are dealing with */
 EXTERN jmp_buf TopFrame;       /* branch-to-top-of-loop-on-error frame */
 EXTERN bool    QuickAbort;     /*  .... but only if we want a quick abort */
+EXTERN bool    LogUsrErrs;     /* syslog user errors (e.g., SMTP RCPT cmd) */
+EXTERN bool    SendMIMEErrors; /* send error messages in MIME format */
+EXTERN bool    MatchGecos;     /* look for user names in gecos field */
+EXTERN bool    UseErrorsTo;    /* use Errors-To: header (back compat) */
+EXTERN char    SpaceSub;       /* substitution for <lwsp> */
+EXTERN int     PrivacyFlags;   /* privacy flags */
 extern char    *ConfFile;      /* location of configuration file [conf.c] */
 extern char    *FreezeFile;    /* location of frozen memory image [conf.c] */
 extern char    *ConfFile;      /* location of configuration file [conf.c] */
 extern char    *FreezeFile;    /* location of frozen memory image [conf.c] */
-extern char    Arpa_Info[];    /* the reply code for Arpanet info [conf.c] */
+extern char    *PidFile;       /* location of proc id file [conf.c] */
 extern ADDRESS NullAddress;    /* a null (template) address [main.c] */
 extern ADDRESS NullAddress;    /* a null (template) address [main.c] */
-EXTERN char    SpaceSub;       /* substitution for <lwsp> */
-EXTERN int     WkClassFact;    /* multiplier for message class -> priority */
-EXTERN int     WkRecipFact;    /* multiplier for # of recipients -> priority */
-EXTERN int     WkTimeFact;     /* priority offset each time this job is run */
-EXTERN int     CheckPointLimit;        /* deliveries before checkpointing */
-EXTERN int     Nmx;                    /* number of MX RRs */
+EXTERN long    WkClassFact;    /* multiplier for message class -> priority */
+EXTERN long    WkRecipFact;    /* multiplier for # of recipients -> priority */
+EXTERN long    WkTimeFact;     /* priority offset each time this job is run */
+EXTERN char    *UdbSpec;       /* user database source spec */
+EXTERN int     MaxHopCount;    /* max # of hops until bounce */
+EXTERN int     ConfigLevel;    /* config file level */
+EXTERN char    *TimeZoneSpec;  /* override time zone specification */
+EXTERN char    *ForwardPath;   /* path to search for .forward files */
+EXTERN long    MinBlocksFree;  /* min # of blocks free on queue fs */
+EXTERN char    *FallBackMX;    /* fall back MX host */
+EXTERN long    MaxMessageSize; /* advertised max size we will accept */
 EXTERN char    *PostMasterCopy;        /* address to get errs cc's */
 EXTERN char    *PostMasterCopy;        /* address to get errs cc's */
-EXTERN char    *MxHosts[MAXMXHOSTS+1]; /* for MX RRs */
-EXTERN char    *TrustedUsers[MAXTRUST+1];      /* list of trusted users */
-EXTERN char    *UserEnviron[MAXUSERENVIRON+1]; /* saved user environment */
 EXTERN int     CheckpointInterval;     /* queue file checkpoint interval */
 EXTERN int     CheckpointInterval;     /* queue file checkpoint interval */
-\f/*
+EXTERN bool    DontPruneRoutes;        /* don't prune source routes */
+EXTERN int     MaxMciCache;            /* maximum entries in MCI cache */
+EXTERN time_t  MciCacheTimeout;        /* maximum idle time on connections */
+EXTERN char    *QueueLimitRecipient;   /* limit queue runs to this recipient */
+EXTERN char    *QueueLimitSender;      /* limit queue runs to this sender */
+EXTERN char    *QueueLimitId;          /* limit queue runs to this id */
+
+
+/*
+**  Timeouts
+**
+**     Indicated values are the MINIMUM per RFC 1123 section 5.3.2.
+*/
+
+EXTERN struct
+{
+       time_t  to_initial;     /* initial greeting timeout [5m] */
+       time_t  to_mail;        /* MAIL command [5m] */
+       time_t  to_rcpt;        /* RCPT command [5m] */
+       time_t  to_datainit;    /* DATA initiation [2m] */
+       time_t  to_datablock;   /* DATA block [3m] */
+       time_t  to_datafinal;   /* DATA completion [10m] */
+       time_t  to_nextcommand; /* next command [5m] */
+                       /* following timeouts are not mentioned in RFC 1123 */
+       time_t  to_rset;        /* RSET command */
+       time_t  to_helo;        /* HELO command */
+       time_t  to_quit;        /* QUIT command */
+       time_t  to_miscshort;   /* misc short commands (NOOP, VERB, etc) */
+                       /* following are per message */
+       time_t  to_q_return;    /* queue return timeout */
+       time_t  to_q_warning;   /* queue warning timeout */
+} TimeOuts;
+
+
+/*
 **  Trace information
 */
 
 **  Trace information
 */
 
@@ -571,7 +854,6 @@ EXTERN u_char       tTdvect[100];
 **  Miscellaneous information.
 */
 
 **  Miscellaneous information.
 */
 
-# include      <sysexits.h>
 
 
 /*
 
 
 /*
@@ -594,11 +876,49 @@ EXTERN u_char     tTdvect[100];
 **  Declarations of useful functions
 */
 
 **  Declarations of useful functions
 */
 
-extern ADDRESS *parseaddr();
-extern char    *xalloc();
-extern bool    sameaddr();
-extern FILE    *dfopen();
-extern EVENT   *setevent();
-extern char    *sfgets();
-extern char    *queuename();
-extern time_t  curtime();
+extern ADDRESS         *parseaddr __P((char *, ADDRESS *, int, int, char **, ENVELOPE *));
+extern char            *xalloc __P((int));
+extern bool            sameaddr __P((ADDRESS *, ADDRESS *));
+extern FILE            *dfopen __P((char *, int, int));
+extern EVENT           *setevent __P((time_t, int(*)(), int));
+extern char            *sfgets __P((char *, int, FILE *, time_t, char *));
+extern char            *queuename __P((ENVELOPE *, int));
+extern time_t          curtime __P(());
+extern bool            transienterror __P((int));
+extern const char      *errstring __P((int));
+extern void            expand __P((char *, char *, char *, ENVELOPE *));
+extern void            define __P((int, char *, ENVELOPE *));
+extern char            *macvalue __P((int, ENVELOPE *));
+extern char            **prescan __P((char *, int, char[], char **));
+extern char            *fgetfolded __P((char *, int, FILE *));
+extern ADDRESS         *recipient __P((ADDRESS *, ADDRESS **, ENVELOPE *));
+extern ENVELOPE                *newenvelope __P((ENVELOPE *, ENVELOPE *));
+extern void            dropenvelope __P((ENVELOPE *));
+extern void            clearenvelope __P((ENVELOPE *, int));
+extern char            *username __P(());
+extern MCI             *mci_get __P((char *, MAILER *));
+extern char            *pintvl __P((time_t, int));
+extern char            *map_rewrite __P((MAP *, char *, int, char **));
+extern ADDRESS         *getctladdr __P((ADDRESS *));
+extern char            *anynet_ntoa __P((SOCKADDR *));
+extern char            *remotename __P((char *, MAILER *, int, int *, ENVELOPE *));
+extern bool            shouldqueue __P((long, time_t));
+extern bool            lockfile __P((int, char *, int));
+extern char            *hostsignature __P((MAILER *, char *, ENVELOPE *));
+extern void            openxscript __P((ENVELOPE *));
+extern void            closexscript __P((ENVELOPE *));
+
+/* ellipsis is a different case though */
+#ifdef __STDC__
+extern void            auth_warning(ENVELOPE *, const char *, ...);
+extern void            syserr(const char *, ...);
+extern void            usrerr(const char *, ...);
+extern void            message(const char *, ...);
+extern void            nmessage(const char *, ...);
+#else
+extern void            auth_warning();
+extern void            syserr();
+extern void            usrerr();
+extern void            message();
+extern void            nmessage();
+#endif
index 293a713..ff208ba 100644 (file)
@@ -1,21 +1,25 @@
 cpyr
 cpyr   Copyright (c) 1983  Eric P. Allman
 cpyr
 cpyr   Copyright (c) 1983  Eric P. Allman
-cpyr   Copyright (c) 1988 The Regents of the University of California.
-cpyr   All rights reserved.
+cpyr   Copyright (c) 1988, 1993
+cpyr       The Regents of the University of California.  All rights reserved.
 cpyr   
 cpyr   
-cpyr   @(#)sendmail.hf 4.5 (Berkeley) 4/23/91
+cpyr   @(#)sendmail.hf 8.1 (Berkeley) 6/7/93
 cpyr
 smtp   Commands:
 cpyr
 smtp   Commands:
-smtp           HELO    MAIL    RCPT    DATA    RSET
-smtp           NOOP    QUIT    HELP    VRFY    EXPN
+smtp           HELO    EHLO    MAIL    RCPT    DATA
+smtp           RSET    NOOP    QUIT    HELP    VRFY
+smtp           EXPN    VERB
 smtp   For more info use "HELP <topic>".
 smtp   For more info use "HELP <topic>".
-smtp   To report bugs in the implementation contact sendmail@okeeffe.Berkeley.EDU
-smtp   For local information contact postmaster at this site.
+smtp   To report bugs in the implementation send email to
+smtp           sendmail@CS.Berkeley.EDU.
+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.  I am a boor, so I really don't
 helo           care if you do.
 help   HELP [ <topic> ]
 help           The HELP command gives help info.
 helo   HELO <hostname>
 helo           Introduce yourself.  I am a boor, so I really don't
 helo           care if you do.
+ehlo   EHLO <hostname>
+ehlo           Introduce yourself, and request extended SMTP mode.
 mail   MAIL FROM: <sender>
 mail           Specifies the sender.
 rcpt   RCPT TO: <recipient>
 mail   MAIL FROM: <sender>
 mail           Specifies the sender.
 rcpt   RCPT TO: <recipient>
@@ -27,11 +31,16 @@ rset        RSET
 rset           Resets the system.
 quit   QUIT
 quit           Exit sendmail (SMTP).
 rset           Resets the system.
 quit   QUIT
 quit           Exit sendmail (SMTP).
+verb   VERB
+verb           Go into verbose mode.  This sends 0xy responses that are
+verb           are not RFC821 standard (but should be)  They are recognized
+verb           by humans and other sendmail implementations.
 vrfy   VRFY <recipient>
 vrfy   VRFY <recipient>
-vrfy           Not implemented to protocol.  Gives some sexy
-vrfy           information.
+vrfy           Verify an address.  If you want to see what it aliases
+vrfy           to, use EXPN instead.
 expn   EXPN <recipient>
 expn   EXPN <recipient>
-expn           Same as VRFY in this implementation.
+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>
 noop   NOOP
 noop           Do nothing.
 send   SEND FROM: <sender>
index b33a1ef..2cce1b9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,9 +36,9 @@
 
 #ifndef lint
 #ifdef SMTP
 
 #ifndef lint
 #ifdef SMTP
-static char sccsid[] = "@(#)srvrsmtp.c 5.31 (Berkeley) 5/10/91 (with SMTP)";
+static char sccsid[] = "@(#)srvrsmtp.c 8.1 (Berkeley) 6/7/93 (with SMTP)";
 #else
 #else
-static char sccsid[] = "@(#)srvrsmtp.c 5.31 (Berkeley) 5/10/91 (without SMTP)";
+static char sccsid[] = "@(#)srvrsmtp.c 8.1 (Berkeley) 6/7/93 (without SMTP)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
@@ -74,15 +74,18 @@ struct cmd
 # define CMDDATA       3       /* data -- send message text */
 # define CMDRSET       4       /* rset -- reset state */
 # define CMDVRFY       5       /* vrfy -- verify address */
 # define CMDDATA       3       /* data -- send message text */
 # define CMDRSET       4       /* rset -- reset state */
 # define CMDVRFY       5       /* vrfy -- verify address */
-# define CMDHELP       6       /* help -- give usage info */
+# define CMDEXPN       6       /* expn -- expand address */
 # define CMDNOOP       7       /* noop -- do nothing */
 # define CMDQUIT       8       /* quit -- close connection and die */
 # define CMDHELO       9       /* helo -- be polite */
 # define CMDNOOP       7       /* noop -- do nothing */
 # define CMDQUIT       8       /* quit -- close connection and die */
 # define CMDHELO       9       /* helo -- be polite */
-# define CMDONEX       10      /* onex -- sending one transaction only */
-# define CMDVERB       11      /* verb -- go into verbose mode */
+# define CMDHELP       10      /* help -- give usage info */
+# define CMDEHLO       11      /* ehlo -- extended helo (RFC 1425) */
+/* non-standard commands */
+# define CMDONEX       16      /* onex -- sending one transaction only */
+# define CMDVERB       17      /* verb -- go into verbose mode */
 /* debugging-only commands, only enabled if SMTPDEBUG is defined */
 /* debugging-only commands, only enabled if SMTPDEBUG is defined */
-# define CMDDBGQSHOW   12      /* showq -- show send queue */
-# define CMDDBGDEBUG   13      /* debug -- set debug mode */
+# define CMDDBGQSHOW   24      /* showq -- show send queue */
+# define CMDDBGDEBUG   25      /* debug -- set debug mode */
 
 static struct cmd      CmdTab[] =
 {
 
 static struct cmd      CmdTab[] =
 {
@@ -91,11 +94,12 @@ static struct cmd   CmdTab[] =
        "data",         CMDDATA,
        "rset",         CMDRSET,
        "vrfy",         CMDVRFY,
        "data",         CMDDATA,
        "rset",         CMDRSET,
        "vrfy",         CMDVRFY,
-       "expn",         CMDVRFY,
+       "expn",         CMDEXPN,
        "help",         CMDHELP,
        "noop",         CMDNOOP,
        "quit",         CMDQUIT,
        "helo",         CMDHELO,
        "help",         CMDHELP,
        "noop",         CMDNOOP,
        "quit",         CMDQUIT,
        "helo",         CMDHELO,
+       "ehlo",         CMDEHLO,
        "verb",         CMDVERB,
        "onex",         CMDONEX,
        /*
        "verb",         CMDVERB,
        "onex",         CMDONEX,
        /*
@@ -112,68 +116,82 @@ bool      OneXact = FALSE;                /* one xaction only this run */
 
 #define EX_QUIT                22              /* special code for QUIT command */
 
 
 #define EX_QUIT                22              /* special code for QUIT command */
 
-smtp()
+smtp(e)
+       register ENVELOPE *e;
 {
        register char *p;
        register struct cmd *c;
        char *cmd;
        static char *skipword();
 {
        register char *p;
        register struct cmd *c;
        char *cmd;
        static char *skipword();
-       bool hasmail;                   /* mail command received */
        auto ADDRESS *vrfyqueue;
        ADDRESS *a;
        auto ADDRESS *vrfyqueue;
        ADDRESS *a;
-       char *sendinghost;
+       bool gotmail;                   /* mail command received */
+       bool gothello;                  /* helo command received */
+       bool vrfy;                      /* set if this is a vrfy command */
+       char *protocol;                 /* sending protocol */
+       char *sendinghost;              /* sending hostname */
+       long msize;                     /* approximate maximum message size */
+       auto char *delimptr;
+       char *id;
+       int nrcpts;                     /* number of RCPT commands */
        char inp[MAXLINE];
        char inp[MAXLINE];
-       char cmdbuf[100];
+       char cmdbuf[MAXLINE];
        extern char Version[];
        extern char Version[];
-       extern char *macvalue();
-       extern ADDRESS *recipient();
        extern ENVELOPE BlankEnvelope;
        extern ENVELOPE BlankEnvelope;
-       extern ENVELOPE *newenvelope();
 
 
-       hasmail = FALSE;
-       if (OutChannel != stdout)
+       if (fileno(OutChannel) != fileno(stdout))
        {
                /* arrange for debugging output to go to remote host */
        {
                /* arrange for debugging output to go to remote host */
-               (void) close(1);
-               (void) dup(fileno(OutChannel));
+               (void) dup2(fileno(OutChannel), fileno(stdout));
        }
        }
-       settime();
-       if (RealHostName != NULL)
-       {
-               CurHostName = RealHostName;
-               setproctitle("srvrsmtp %s", CurHostName);
-       }
-       else
-       {
-               /* this must be us!! */
-               CurHostName = MyHostName;
-       }
-       expand("\001e", inp, &inp[sizeof inp], CurEnv);
-       message("220", inp);
-       SmtpPhase = "startup";
-       sendinghost = NULL;
+       settime(e);
+       CurHostName = RealHostName;
+       setproctitle("server %s startup", CurHostName);
+       expand("\201e", inp, &inp[sizeof inp], e);
+       message("220-%s", inp);
+       message("220 ESMTP spoken here");
+       protocol = NULL;
+       sendinghost = macvalue('s', e);
+       gothello = FALSE;
+       gotmail = FALSE;
        for (;;)
        {
                /* arrange for backout */
                if (setjmp(TopFrame) > 0 && InChild)
        for (;;)
        {
                /* arrange for backout */
                if (setjmp(TopFrame) > 0 && InChild)
+               {
+                       QuickAbort = FALSE;
+                       SuprErrs = TRUE;
                        finis();
                        finis();
+               }
                QuickAbort = FALSE;
                HoldErrs = FALSE;
                QuickAbort = FALSE;
                HoldErrs = FALSE;
+               LogUsrErrs = FALSE;
+               e->e_flags &= ~EF_VRFYONLY;
 
                /* setup for the read */
 
                /* setup for the read */
-               CurEnv->e_to = NULL;
+               e->e_to = NULL;
                Errors = 0;
                (void) fflush(stdout);
 
                /* read the input line */
                Errors = 0;
                (void) fflush(stdout);
 
                /* read the input line */
-               p = sfgets(inp, sizeof inp, InChannel);
+               SmtpPhase = "server cmd read";
+               setproctitle("server %s cmd read", CurHostName);
+               p = sfgets(inp, sizeof inp, InChannel, TimeOuts.to_nextcommand,
+                               SmtpPhase);
 
                /* handle errors */
                if (p == NULL)
                {
                        /* end of file, just die */
 
                /* handle errors */
                if (p == NULL)
                {
                        /* end of file, just die */
-                       message("421", "%s Lost input channel from %s",
+                       message("421 %s Lost input channel from %s",
                                MyHostName, CurHostName);
                                MyHostName, CurHostName);
+#ifdef LOG
+                       if (LogLevel > 1)
+                               syslog(LOG_NOTICE, "lost input channel from %s",
+                                       CurHostName);
+#endif
+                       if (InChild)
+                               ExitStat = EX_QUIT;
                        finis();
                }
 
                        finis();
                }
 
@@ -181,19 +199,26 @@ smtp()
                fixcrlf(inp, TRUE);
 
                /* echo command to transcript */
                fixcrlf(inp, TRUE);
 
                /* echo command to transcript */
-               if (CurEnv->e_xfp != NULL)
-                       fprintf(CurEnv->e_xfp, "<<< %s\n", inp);
+               if (e->e_xfp != NULL)
+                       fprintf(e->e_xfp, "<<< %s\n", inp);
+
+               if (e->e_id == NULL)
+                       setproctitle("%s: %s", CurHostName, inp);
+               else
+                       setproctitle("%s %s: %s", e->e_id, CurHostName, inp);
 
                /* break off command */
 
                /* break off command */
-               for (p = inp; isspace(*p); p++)
+               for (p = inp; isascii(*p) && isspace(*p); p++)
                        continue;
                        continue;
-               cmd = p;
-               for (cmd = cmdbuf; *p != '\0' && !isspace(*p); )
+               cmd = cmdbuf;
+               while (*p != '\0' &&
+                      !(isascii(*p) && isspace(*p)) &&
+                      cmd < &cmdbuf[sizeof cmdbuf - 2])
                        *cmd++ = *p++;
                *cmd = '\0';
 
                /* throw away leading whitespace */
                        *cmd++ = *p++;
                *cmd = '\0';
 
                /* throw away leading whitespace */
-               while (isspace(*p))
+               while (isascii(*p) && isspace(*p))
                        p++;
 
                /* decode command */
                        p++;
 
                /* decode command */
@@ -203,131 +228,287 @@ smtp()
                                break;
                }
 
                                break;
                }
 
+               /* reset errors */
+               errno = 0;
+
                /* process command */
                switch (c->cmdcode)
                {
                  case CMDHELO:         /* hello -- introduce yourself */
                /* process command */
                switch (c->cmdcode)
                {
                  case CMDHELO:         /* hello -- introduce yourself */
-                       SmtpPhase = "HELO";
-                       setproctitle("%s: %s", CurHostName, inp);
-                       if (!strcasecmp(p, MyHostName))
+                 case CMDEHLO:         /* extended hello */
+                       if (c->cmdcode == CMDEHLO)
                        {
                        {
-                               /*
-                                * didn't know about alias,
-                                * or connected to an echo server
-                                */
-                               message("553", "%s config error: mail loops back to myself",
-                                       MyHostName);
-                               break;
+                               protocol = "ESMTP";
+                               SmtpPhase = "server EHLO";
                        }
                        }
-                       if (RealHostName != NULL && strcasecmp(p, RealHostName))
+                       else
                        {
                        {
-                               char hostbuf[MAXNAME];
+                               protocol = "SMTP";
+                               SmtpPhase = "server HELO";
+                       }
+                       sendinghost = newstr(p);
+                       if (strcasecmp(p, RealHostName) != 0)
+                       {
+                               auth_warning(e, "Host %s claimed to be %s",
+                                       RealHostName, p);
+                       }
+                       p = macvalue('_', e);
+                       if (p == NULL)
+                               p = RealHostName;
 
 
-                               (void) sprintf(hostbuf, "%s (%s)", p, RealHostName);
-                               sendinghost = newstr(hostbuf);
+                       gothello = TRUE;
+                       if (c->cmdcode != CMDEHLO)
+                       {
+                               /* print old message and be done with it */
+                               message("250 %s Hello %s, pleased to meet you",
+                                       MyHostName, p);
+                               break;
                        }
                        }
+                       
+                       /* print extended message and brag */
+                       message("250-%s Hello %s, pleased to meet you",
+                               MyHostName, p);
+                       if (!bitset(PRIV_NOEXPN, PrivacyFlags))
+                               message("250-EXPN");
+                       if (MaxMessageSize > 0)
+                               message("250-SIZE %ld", MaxMessageSize);
                        else
                        else
-                               sendinghost = newstr(p);
-                       message("250", "%s Hello %s, pleased to meet you",
-                               MyHostName, sendinghost);
+                               message("250-SIZE");
+                       message("250 HELP");
                        break;
 
                  case CMDMAIL:         /* mail -- designate sender */
                        break;
 
                  case CMDMAIL:         /* mail -- designate sender */
-                       SmtpPhase = "MAIL";
-
-                       /* force a sending host even if no HELO given */
-                       if (RealHostName != NULL && macvalue('s', CurEnv) == NULL)
-                               sendinghost = RealHostName;
+                       SmtpPhase = "server MAIL";
 
                        /* check for validity of this command */
 
                        /* check for validity of this command */
-                       if (hasmail)
+                       if (!gothello)
                        {
                        {
-                               message("503", "Sender already specified");
+                               /* set sending host to our known value */
+                               if (sendinghost == NULL)
+                                       sendinghost = RealHostName;
+
+                               if (bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
+                               {
+                                       message("503 Polite people say HELO first");
+                                       break;
+                               }
+                               else
+                               {
+                                       auth_warning(e,
+                                               "Host %s didn't use HELO protocol",
+                                               RealHostName);
+                               }
+                       }
+                       if (gotmail)
+                       {
+                               message("503 Sender already specified");
                                break;
                        }
                        if (InChild)
                        {
                                errno = 0;
                                break;
                        }
                        if (InChild)
                        {
                                errno = 0;
-                               syserr("Nested MAIL command");
-                               exit(0);
+                               syserr("503 Nested MAIL command: MAIL %s", p);
+                               finis();
                        }
 
                        /* fork a subprocess to process this command */
                        }
 
                        /* fork a subprocess to process this command */
-                       if (runinchild("SMTP-MAIL") > 0)
+                       if (runinchild("SMTP-MAIL", e) > 0)
                                break;
                                break;
-                       define('s', sendinghost, CurEnv);
-                       define('r', "SMTP", CurEnv);
-                       initsys();
-                       setproctitle("%s %s: %s", CurEnv->e_id,
-                               CurHostName, inp);
+                       if (protocol == NULL)
+                               protocol = "SMTP";
+                       define('r', protocol, e);
+                       define('s', sendinghost, e);
+                       initsys(e);
+                       nrcpts = 0;
+                       setproctitle("%s %s: %s", e->e_id, CurHostName, inp);
 
                        /* child -- go do the processing */
                        p = skipword(p, "from");
                        if (p == NULL)
                                break;
 
                        /* child -- go do the processing */
                        p = skipword(p, "from");
                        if (p == NULL)
                                break;
-                       setsender(p);
-                       if (Errors == 0)
+                       if (setjmp(TopFrame) > 0)
                        {
                        {
-                               message("250", "Sender ok");
-                               hasmail = TRUE;
+                               /* this failed -- undo work */
+                               if (InChild)
+                               {
+                                       QuickAbort = FALSE;
+                                       SuprErrs = TRUE;
+                                       finis();
+                               }
+                               break;
                        }
                        }
-                       else if (InChild)
-                               finis();
+                       QuickAbort = TRUE;
+
+                       /* must parse sender first */
+                       delimptr = NULL;
+                       setsender(p, e, &delimptr, FALSE);
+                       p = delimptr;
+                       if (p != NULL && *p != '\0')
+                               *p++ = '\0';
+
+                       /* now parse ESMTP arguments */
+                       msize = 0;
+                       for (; p != NULL && *p != '\0'; p++)
+                       {
+                               char *kp;
+                               char *vp;
+
+                               /* locate the beginning of the keyword */
+                               while (isascii(*p) && isspace(*p))
+                                       p++;
+                               if (*p == '\0')
+                                       break;
+                               kp = p;
+
+                               /* skip to the value portion */
+                               while (isascii(*p) && isalnum(*p) || *p == '-')
+                                       p++;
+                               if (*p == '=')
+                               {
+                                       *p++ = '\0';
+                                       vp = p;
+
+                                       /* skip to the end of the value */
+                                       while (*p != '\0' && *p != ' ' &&
+                                              !(isascii(*p) && iscntrl(*p)) &&
+                                              *p != '=')
+                                               p++;
+                               }
+
+                               if (*p != '\0')
+                                       *p++ = '\0';
+
+                               if (tTd(19, 1))
+                                       printf("MAIL: got arg %s=%s\n", kp,
+                                               vp == NULL ? "<null>" : vp);
+
+                               if (strcasecmp(kp, "size") == 0)
+                               {
+                                       if (vp == NULL)
+                                       {
+                                               usrerr("501 SIZE requires a value");
+                                               /* NOTREACHED */
+                                       }
+                                       msize = atol(vp);
+                               }
+                               else if (strcasecmp(kp, "body") == 0)
+                               {
+                                       if (vp == NULL)
+                                       {
+                                               usrerr("501 BODY requires a value");
+                                               /* NOTREACHED */
+                                       }
+# ifdef MIME
+                                       if (strcasecmp(vp, "8bitmime") == 0)
+                                       {
+                                               e->e_bodytype = "8BITMIME";
+                                               SevenBit = FALSE;
+                                       }
+                                       else if (strcasecmp(vp, "7bit") == 0)
+                                       {
+                                               e->e_bodytype = "7BIT";
+                                               SevenBit = TRUE;
+                                       }
+                                       else
+                                       {
+                                               usrerr("501 Unknown BODY type %s",
+                                                       vp);
+                                       }
+# endif
+                               }
+                               else
+                               {
+                                       usrerr("501 %s parameter unrecognized", kp);
+                                       /* NOTREACHED */
+                               }
+                       }
+
+                       if (MaxMessageSize > 0 && msize > MaxMessageSize)
+                       {
+                               usrerr("552 Message size exceeds fixed maximum message size (%ld)",
+                                       MaxMessageSize);
+                               /* NOTREACHED */
+                       }
+                               
+                       if (!enoughspace(msize))
+                       {
+                               message("452 Insufficient disk space; try again later");
+                               break;
+                       }
+                       message("250 Sender ok");
+                       gotmail = TRUE;
                        break;
 
                  case CMDRCPT:         /* rcpt -- designate recipient */
                        break;
 
                  case CMDRCPT:         /* rcpt -- designate recipient */
-                       SmtpPhase = "RCPT";
-                       setproctitle("%s %s: %s", CurEnv->e_id,
-                               CurHostName, inp);
+                       if (!gotmail)
+                       {
+                               usrerr("503 Need MAIL before RCPT");
+                               break;
+                       }
+                       SmtpPhase = "server RCPT";
                        if (setjmp(TopFrame) > 0)
                        {
                        if (setjmp(TopFrame) > 0)
                        {
-                               CurEnv->e_flags &= ~EF_FATALERRS;
+                               e->e_flags &= ~EF_FATALERRS;
                                break;
                        }
                        QuickAbort = TRUE;
                                break;
                        }
                        QuickAbort = TRUE;
+                       LogUsrErrs = TRUE;
+
+                       if (e->e_sendmode != SM_DELIVER)
+                               e->e_flags |= EF_VRFYONLY;
+
                        p = skipword(p, "to");
                        if (p == NULL)
                                break;
                        p = skipword(p, "to");
                        if (p == NULL)
                                break;
-                       a = parseaddr(p, (ADDRESS *) NULL, 1, '\0');
+                       a = parseaddr(p, (ADDRESS *) NULL, 1, ' ', NULL, e);
                        if (a == NULL)
                                break;
                        a->q_flags |= QPRIMARY;
                        if (a == NULL)
                                break;
                        a->q_flags |= QPRIMARY;
-                       a = recipient(a, &CurEnv->e_sendqueue);
+                       a = recipient(a, &e->e_sendqueue, e);
                        if (Errors != 0)
                                break;
 
                        /* no errors during parsing, but might be a duplicate */
                        if (Errors != 0)
                                break;
 
                        /* no errors during parsing, but might be a duplicate */
-                       CurEnv->e_to = p;
+                       e->e_to = p;
                        if (!bitset(QBADADDR, a->q_flags))
                        if (!bitset(QBADADDR, a->q_flags))
-                               message("250", "Recipient ok");
+                       {
+                               message("250 Recipient ok");
+                               nrcpts++;
+                       }
                        else
                        {
                                /* punt -- should keep message in ADDRESS.... */
                        else
                        {
                                /* punt -- should keep message in ADDRESS.... */
-                               message("550", "Addressee unknown");
+                               message("550 Addressee unknown");
                        }
                        }
-                       CurEnv->e_to = NULL;
+                       e->e_to = NULL;
                        break;
 
                  case CMDDATA:         /* data -- text of mail */
                        break;
 
                  case CMDDATA:         /* data -- text of mail */
-                       SmtpPhase = "DATA";
-                       if (!hasmail)
+                       SmtpPhase = "server DATA";
+                       if (!gotmail)
                        {
                        {
-                               message("503", "Need MAIL command");
+                               message("503 Need MAIL command");
                                break;
                        }
                                break;
                        }
-                       else if (CurEnv->e_nrcpts <= 0)
+                       else if (e->e_nrcpts <= 0)
                        {
                        {
-                               message("503", "Need RCPT (recipient)");
+                               message("503 Need RCPT (recipient)");
                                break;
                        }
 
                                break;
                        }
 
+                       /* check to see if we need to re-expand aliases */
+                       for (a = e->e_sendqueue; a != NULL; a = a->q_next)
+                       {
+                               if (bitset(QVERIFIED, a->q_flags))
+                                       break;
+                       }
+
                        /* collect the text of the message */
                        SmtpPhase = "collect";
                        /* collect the text of the message */
                        SmtpPhase = "collect";
-                       setproctitle("%s %s: %s", CurEnv->e_id,
-                               CurHostName, inp);
-                       collect(TRUE);
+                       collect(TRUE, a != NULL, e);
+                       e->e_flags &= ~EF_FATALERRS;
                        if (Errors != 0)
                        if (Errors != 0)
-                               break;
+                               goto abortmessage;
 
                        /*
                        **  Arrange to send to everyone.
 
                        /*
                        **  Arrange to send to everyone.
@@ -348,79 +529,131 @@ smtp()
                        */
 
                        SmtpPhase = "delivery";
                        */
 
                        SmtpPhase = "delivery";
-                       if (CurEnv->e_nrcpts != 1)
+                       if (nrcpts != 1 && a == NULL)
                        {
                                HoldErrs = TRUE;
                        {
                                HoldErrs = TRUE;
-                               ErrorMode = EM_MAIL;
+                               e->e_errormode = EM_MAIL;
                        }
                        }
-                       CurEnv->e_flags &= ~EF_FATALERRS;
-                       CurEnv->e_xfp = freopen(queuename(CurEnv, 'x'), "w", CurEnv->e_xfp);
+                       e->e_xfp = freopen(queuename(e, 'x'), "w", e->e_xfp);
+                       id = e->e_id;
 
                        /* send to all recipients */
 
                        /* send to all recipients */
-                       sendall(CurEnv, SM_DEFAULT);
-                       CurEnv->e_to = NULL;
+                       sendall(e, a == NULL ? SM_DEFAULT : SM_QUEUE);
+                       e->e_to = NULL;
 
                        /* save statistics */
 
                        /* save statistics */
-                       markstats(CurEnv, (ADDRESS *) NULL);
+                       markstats(e, (ADDRESS *) NULL);
 
                        /* issue success if appropriate and reset */
                        if (Errors == 0 || HoldErrs)
 
                        /* issue success if appropriate and reset */
                        if (Errors == 0 || HoldErrs)
-                               message("250", "Ok");
+                               message("250 %s Message accepted for delivery", id);
+
+                       if (bitset(EF_FATALERRS, e->e_flags) && !HoldErrs)
+                       {
+                               /* avoid sending back an extra message */
+                               e->e_flags &= ~EF_FATALERRS;
+                               e->e_flags |= EF_CLRQUEUE;
+                       }
                        else
                        else
-                               CurEnv->e_flags &= ~EF_FATALERRS;
+                       {
+                               /* from now on, we have to operate silently */
+                               HoldErrs = TRUE;
+                               e->e_errormode = EM_MAIL;
+
+                               /* if we just queued, poke it */
+                               if (a != NULL && e->e_sendmode != SM_QUEUE)
+                               {
+                                       unlockqueue(e);
+                                       dowork(id, TRUE, TRUE, e);
+                                       e->e_id = NULL;
+                               }
+                       }
 
 
+  abortmessage:
                        /* if in a child, pop back to our parent */
                        if (InChild)
                                finis();
 
                        /* clean up a bit */
                        /* if in a child, pop back to our parent */
                        if (InChild)
                                finis();
 
                        /* clean up a bit */
-                       hasmail = 0;
-                       dropenvelope(CurEnv);
-                       CurEnv = newenvelope(CurEnv);
-                       CurEnv->e_flags = BlankEnvelope.e_flags;
+                       gotmail = FALSE;
+                       dropenvelope(e);
+                       CurEnv = e = newenvelope(e, CurEnv);
+                       e->e_flags = BlankEnvelope.e_flags;
                        break;
 
                  case CMDRSET:         /* rset -- reset state */
                        break;
 
                  case CMDRSET:         /* rset -- reset state */
-                       message("250", "Reset state");
+                       message("250 Reset state");
                        if (InChild)
                                finis();
                        if (InChild)
                                finis();
+
+                       /* clean up a bit */
+                       gotmail = FALSE;
+                       dropenvelope(e);
+                       CurEnv = e = newenvelope(e, CurEnv);
                        break;
 
                  case CMDVRFY:         /* vrfy -- verify address */
                        break;
 
                  case CMDVRFY:         /* vrfy -- verify address */
-                       if (runinchild("SMTP-VRFY") > 0)
+                 case CMDEXPN:         /* expn -- expand address */
+                       vrfy = c->cmdcode == CMDVRFY;
+                       if (bitset(vrfy ? PRIV_NOVRFY : PRIV_NOEXPN,
+                                               PrivacyFlags))
+                       {
+                               if (vrfy)
+                                       message("252 Who's to say?");
+                               else
+                                       message("502 That's none of your business");
                                break;
                                break;
-                       setproctitle("%s: %s", CurHostName, inp);
+                       }
+                       else if (!gothello &&
+                                bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO,
+                                               PrivacyFlags))
+                       {
+                               message("503 I demand that you introduce yourself first");
+                               break;
+                       }
+                       if (runinchild(vrfy ? "SMTP-VRFY" : "SMTP-EXPN", e) > 0)
+                               break;
+#ifdef LOG
+                       if (LogLevel > 5)
+                               syslog(LOG_INFO, "%s: %s", CurHostName, inp);
+#endif
                        vrfyqueue = NULL;
                        QuickAbort = TRUE;
                        vrfyqueue = NULL;
                        QuickAbort = TRUE;
-                       sendtolist(p, (ADDRESS *) NULL, &vrfyqueue);
+                       if (vrfy)
+                               e->e_flags |= EF_VRFYONLY;
+                       while (*p != '\0' && isascii(*p) && isspace(*p))
+                               *p++;
+                       if (*p == '\0')
+                       {
+                               message("501 Argument required");
+                               Errors++;
+                       }
+                       else
+                       {
+                               (void) sendtolist(p, (ADDRESS *) NULL,
+                                                 &vrfyqueue, e);
+                       }
                        if (Errors != 0)
                        {
                                if (InChild)
                                        finis();
                                break;
                        }
                        if (Errors != 0)
                        {
                                if (InChild)
                                        finis();
                                break;
                        }
+                       if (vrfyqueue == NULL)
+                       {
+                               message("554 Nothing to %s", vrfy ? "VRFY" : "EXPN");
+                       }
                        while (vrfyqueue != NULL)
                        {
                                register ADDRESS *a = vrfyqueue->q_next;
                        while (vrfyqueue != NULL)
                        {
                                register ADDRESS *a = vrfyqueue->q_next;
-                               char *code;
 
                                while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags))
                                        a = a->q_next;
 
                                if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
 
                                while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags))
                                        a = a->q_next;
 
                                if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
-                               {
-                                       if (a != NULL)
-                                               code = "250-";
-                                       else
-                                               code = "250";
-                                       if (vrfyqueue->q_fullname == NULL)
-                                               message(code, "<%s>", vrfyqueue->q_paddr);
-                                       else
-                                               message(code, "%s <%s>",
-                                                   vrfyqueue->q_fullname, vrfyqueue->q_paddr);
-                               }
+                                       printvrfyaddr(vrfyqueue, a == NULL);
                                else if (a == NULL)
                                else if (a == NULL)
-                                       message("554", "Self destructive alias loop");
+                                       message("554 Self destructive alias loop");
                                vrfyqueue = a;
                        }
                        if (InChild)
                                vrfyqueue = a;
                        }
                        if (InChild)
@@ -432,36 +665,46 @@ smtp()
                        break;
 
                  case CMDNOOP:         /* noop -- do nothing */
                        break;
 
                  case CMDNOOP:         /* noop -- do nothing */
-                       message("200", "OK");
+                       message("200 OK");
                        break;
 
                  case CMDQUIT:         /* quit -- leave mail */
                        break;
 
                  case CMDQUIT:         /* quit -- leave mail */
-                       message("221", "%s closing connection", MyHostName);
+                       message("221 %s closing connection", MyHostName);
+
+                       /* avoid future 050 messages */
+                       Verbose = FALSE;
+
                        if (InChild)
                                ExitStat = EX_QUIT;
                        finis();
 
                  case CMDVERB:         /* set verbose mode */
                        if (InChild)
                                ExitStat = EX_QUIT;
                        finis();
 
                  case CMDVERB:         /* set verbose mode */
+                       if (bitset(PRIV_NOEXPN, PrivacyFlags))
+                       {
+                               /* this would give out the same info */
+                               message("502 Verbose unavailable");
+                               break;
+                       }
                        Verbose = TRUE;
                        Verbose = TRUE;
-                       SendMode = SM_DELIVER;
-                       message("200", "Verbose mode");
+                       e->e_sendmode = SM_DELIVER;
+                       message("250 Verbose mode");
                        break;
 
                  case CMDONEX:         /* doing one transaction only */
                        OneXact = TRUE;
                        break;
 
                  case CMDONEX:         /* doing one transaction only */
                        OneXact = TRUE;
-                       message("200", "Only one transaction");
+                       message("250 Only one transaction");
                        break;
 
 # ifdef SMTPDEBUG
                  case CMDDBGQSHOW:     /* show queues */
                        printf("Send Queue=");
                        break;
 
 # ifdef SMTPDEBUG
                  case CMDDBGQSHOW:     /* show queues */
                        printf("Send Queue=");
-                       printaddr(CurEnv->e_sendqueue, TRUE);
+                       printaddr(e->e_sendqueue, TRUE);
                        break;
 
                  case CMDDBGDEBUG:     /* set debug mode */
                        tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
                        tTflag(p);
                        break;
 
                  case CMDDBGDEBUG:     /* set debug mode */
                        tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
                        tTflag(p);
-                       message("200", "Debug set");
+                       message("200 Debug set");
                        break;
 
 # else /* not SMTPDEBUG */
                        break;
 
 # else /* not SMTPDEBUG */
@@ -469,22 +712,22 @@ smtp()
                  case CMDDBGQSHOW:     /* show queues */
                  case CMDDBGDEBUG:     /* set debug mode */
 # ifdef LOG
                  case CMDDBGQSHOW:     /* show queues */
                  case CMDDBGDEBUG:     /* set debug mode */
 # ifdef LOG
-                       if (RealHostName != NULL && LogLevel > 0)
+                       if (LogLevel > 0)
                                syslog(LOG_NOTICE,
                                syslog(LOG_NOTICE,
-                                   "\"%s\" command from %s (%s)\n",
+                                   "\"%s\" command from %s (%s)",
                                    c->cmdname, RealHostName,
                                    c->cmdname, RealHostName,
-                                   inet_ntoa(RealHostAddr.sin_addr));
+                                   anynet_ntoa(&RealHostAddr));
 # endif
                        /* FALL THROUGH */
 # endif /* SMTPDEBUG */
 
                  case CMDERROR:        /* unknown command */
 # endif
                        /* FALL THROUGH */
 # endif /* SMTPDEBUG */
 
                  case CMDERROR:        /* unknown command */
-                       message("500", "Command unrecognized");
+                       message("500 Command unrecognized");
                        break;
 
                  default:
                        errno = 0;
                        break;
 
                  default:
                        errno = 0;
-                       syserr("smtp: unknown code %d", c->cmdcode);
+                       syserr("500 smtp: unknown code %d", c->cmdcode);
                        break;
                }
        }
                        break;
                }
        }
@@ -512,26 +755,29 @@ skipword(p, w)
        register char *q;
 
        /* find beginning of word */
        register char *q;
 
        /* find beginning of word */
-       while (isspace(*p))
+       while (isascii(*p) && isspace(*p))
                p++;
        q = p;
 
        /* find end of word */
                p++;
        q = p;
 
        /* find end of word */
-       while (*p != '\0' && *p != ':' && !isspace(*p))
+       while (*p != '\0' && *p != ':' && !(isascii(*p) && isspace(*p)))
                p++;
                p++;
-       while (isspace(*p))
+       while (isascii(*p) && isspace(*p))
                *p++ = '\0';
        if (*p != ':')
        {
          syntax:
                *p++ = '\0';
        if (*p != ':')
        {
          syntax:
-               message("501", "Syntax error");
+               message("501 Syntax error in parameters");
                Errors++;
                return (NULL);
        }
        *p++ = '\0';
                Errors++;
                return (NULL);
        }
        *p++ = '\0';
-       while (isspace(*p))
+       while (isascii(*p) && isspace(*p))
                p++;
 
                p++;
 
+       if (*p == '\0')
+               goto syntax;
+
        /* see if the input word matches desired word */
        if (strcasecmp(q, w))
                goto syntax;
        /* see if the input word matches desired word */
        if (strcasecmp(q, w))
                goto syntax;
@@ -539,6 +785,46 @@ skipword(p, w)
        return (p);
 }
 \f/*
        return (p);
 }
 \f/*
+**  PRINTVRFYADDR -- print an entry in the verify queue
+**
+**     Parameters:
+**             a -- the address to print
+**             last -- set if this is the last one.
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             Prints the appropriate 250 codes.
+*/
+
+printvrfyaddr(a, last)
+       register ADDRESS *a;
+       bool last;
+{
+       char fmtbuf[20];
+
+       strcpy(fmtbuf, "250");
+       fmtbuf[3] = last ? ' ' : '-';
+
+       if (a->q_fullname == NULL)
+       {
+               if (strchr(a->q_user, '@') == NULL)
+                       strcpy(&fmtbuf[4], "<%s@%s>");
+               else
+                       strcpy(&fmtbuf[4], "<%s>");
+               message(fmtbuf, a->q_user, MyHostName);
+       }
+       else
+       {
+               if (strchr(a->q_user, '@') == NULL)
+                       strcpy(&fmtbuf[4], "%s <%s@%s>");
+               else
+                       strcpy(&fmtbuf[4], "%s <%s>");
+               message(fmtbuf, a->q_fullname, a->q_user, MyHostName);
+       }
+}
+\f/*
 **  HELP -- implement the HELP command.
 **
 **     Parameters:
 **  HELP -- implement the HELP command.
 **
 **     Parameters:
@@ -563,7 +849,7 @@ help(topic)
        {
                /* no help */
                errno = 0;
        {
                /* no help */
                errno = 0;
-               message("502", "HELP not implemented");
+               message("502 HELP not implemented");
                return;
        }
 
                return;
        }
 
@@ -581,21 +867,21 @@ help(topic)
                {
                        register char *p;
 
                {
                        register char *p;
 
-                       p = index(buf, '\t');
+                       p = strchr(buf, '\t');
                        if (p == NULL)
                                p = buf;
                        else
                                p++;
                        fixcrlf(p, TRUE);
                        if (p == NULL)
                                p = buf;
                        else
                                p++;
                        fixcrlf(p, TRUE);
-                       message("214-", p);
+                       message("214-%s", p);
                        noinfo = FALSE;
                }
        }
 
        if (noinfo)
                        noinfo = FALSE;
                }
        }
 
        if (noinfo)
-               message("504", "HELP topic unknown");
+               message("504 HELP topic unknown");
        else
        else
-               message("214", "End of HELP info");
+               message("214 End of HELP info");
        (void) fclose(hf);
 }
 \f/*
        (void) fclose(hf);
 }
 \f/*
@@ -612,8 +898,9 @@ help(topic)
 **             none.
 */
 
 **             none.
 */
 
-runinchild(label)
+runinchild(label, e)
        char *label;
        char *label;
+       register ENVELOPE *e;
 {
        int childpid;
 
 {
        int childpid;
 
@@ -630,6 +917,7 @@ runinchild(label)
                        auto int st;
 
                        /* parent -- wait for child to complete */
                        auto int st;
 
                        /* parent -- wait for child to complete */
+                       setproctitle("server %s child wait", CurHostName);
                        st = waitfor(childpid);
                        if (st == -1)
                                syserr("%s: lost child", label);
                        st = waitfor(childpid);
                        if (st == -1)
                                syserr("%s: lost child", label);
@@ -645,14 +933,14 @@ runinchild(label)
                        /* child */
                        InChild = TRUE;
                        QuickAbort = FALSE;
                        /* child */
                        InChild = TRUE;
                        QuickAbort = FALSE;
-                       clearenvelope(CurEnv, FALSE);
+                       clearenvelope(e, FALSE);
                }
        }
 
        /* open alias database */
                }
        }
 
        /* open alias database */
-       initaliases(AliasFile, FALSE);
+       initmaps(FALSE, e);
 
        return (0);
 }
 
 
        return (0);
 }
 
-# endif SMTP
+# endif /* SMTP */
index aefbabf..07893e5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)stab.c     5.7 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)stab.c     8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -133,3 +133,34 @@ stab(name, type, op)
 
        return (s);
 }
 
        return (s);
 }
+\f/*
+**  STABAPPLY -- apply function to all stab entries
+**
+**     Parameters:
+**             func -- the function to apply.  It will be given one
+**                     parameter (the stab entry).
+**             arg -- an arbitrary argument, passed to func.
+**
+**     Returns:
+**             none.
+*/
+
+void
+stabapply(func, arg)
+       void (*func)__P((STAB *, int));
+       int arg;
+{
+       register STAB **shead;
+       register STAB *s;
+
+       for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++)
+       {
+               for (s = *shead; s != NULL; s = s->s_next)
+               {
+                       if (tTd(38, 90))
+                               printf("stabapply: trying %d/%s\n",
+                                       s->s_type, s->s_name);
+                       func(s, arg);
+               }
+       }
+}
index 28e8d50..c2b407c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)stats.c    5.11 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)stats.c    8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -57,13 +57,13 @@ markstats(e, to)
                {
                        Stat.stat_nf[e->e_from.q_mailer->m_mno]++;
                        Stat.stat_bf[e->e_from.q_mailer->m_mno] +=
                {
                        Stat.stat_nf[e->e_from.q_mailer->m_mno]++;
                        Stat.stat_bf[e->e_from.q_mailer->m_mno] +=
-                               KBYTES(CurEnv->e_msgsize);
+                               KBYTES(e->e_msgsize);
                }
        }
        else
        {
                Stat.stat_nt[to->q_mailer->m_mno]++;
                }
        }
        else
        {
                Stat.stat_nt[to->q_mailer->m_mno]++;
-               Stat.stat_bt[to->q_mailer->m_mno] += KBYTES(CurEnv->e_msgsize);
+               Stat.stat_bt[to->q_mailer->m_mno] += KBYTES(e->e_msgsize);
        }
 }
 \f/*
        }
 }
 \f/*
index 4cc9c3d..fff3783 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)sysexits.c 5.6 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)sysexits.c 8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 #include <sysexits.h>
 
 /*
 #endif /* not lint */
 
 #include <sysexits.h>
 
 /*
- *  SYSEXITS.C -- error messages corresponding to sysexits.h
- */
-char *SysExMsg[] = {
-       /* 64 USAGE */          "500 Bad usage",
-       /* 65 DATAERR */        "501 Data format error",
-       /* 66 NOINPUT */        "550 Cannot open input",
-       /* 67 NOUSER */         "550 User unknown",
-       /* 68 NOHOST */         "550 Host unknown",
-       /* 69 UNAVAILABLE */    "554 Service unavailable",
-       /* 70 SOFTWARE */       "554 Internal error",
-       /* 71 OSERR */          "451 Operating system error",
-       /* 72 OSFILE */         "554 System file missing",
-       /* 73 CANTCREAT */      "550 Can't create output",
-       /* 74 IOERR */          "451 I/O error",
-       /* 75 TEMPFAIL */       "250 Deferred",
-       /* 76 PROTOCOL */       "554 Remote protocol error",
-       /* 77 NOPERM */         "550 Insufficient permission",
-       /* 78 CONFIG */         "554 Local configuration error",
-};
-
-int N_SysEx = sizeof(SysExMsg) / sizeof(SysExMsg[0]);
+**  SYSEXITS.C -- error messages corresponding to sysexits.h
+**
+**     If the first character of the string is a colon, interpolate
+**     the current errno after the rest of the string.
+*/
 
 
-/*
- *  STATSTRING -- return string corresponding to an error status
- *
- *     Parameters:
- *             stat -- the status to decode.
- *
- *     Returns:
- *             The string corresponding to that status
- *
- *     Side Effects:
- *             none.
- */
-char *
-statstring(stat)
-       int stat;
+char *SysExMsg[] =
 {
 {
-       static char ebuf[50];
+       /* 64 USAGE */          " 500 Bad usage",
+       /* 65 DATAERR */        " 501 Data format error",
+       /* 66 NOINPUT */        ":550 Cannot open input",
+       /* 67 NOUSER */         " 550 User unknown",
+       /* 68 NOHOST */         " 550 Host unknown",
+       /* 69 UNAVAILABLE */    " 554 Service unavailable",
+       /* 70 SOFTWARE */       ":554 Internal error",
+       /* 71 OSERR */          ":451 Operating system error",
+       /* 72 OSFILE */         ":554 System file missing",
+       /* 73 CANTCREAT */      ":550 Can't create output",
+       /* 74 IOERR */          ":451 I/O error",
+       /* 75 TEMPFAIL */       " 250 Deferred",
+       /* 76 PROTOCOL */       " 554 Remote protocol error",
+       /* 77 NOPERM */         ":550 Insufficient permission",
+       /* 78 CONFIG */         " 554 Local configuration error",
+};
 
 
-       stat -= EX__BASE;
-       if (stat < 0 || stat >= N_SysEx) {
-               (void)sprintf(ebuf, "554 Unknown status %d", stat + EX__BASE);
-               return(ebuf);
-       }
-       return(SysExMsg[stat]);
-}
+int N_SysEx = sizeof(SysExMsg) / sizeof(SysExMsg[0]);
diff --git a/usr.sbin/sendmail/src/sysexits.h b/usr.sbin/sendmail/src/sysexits.h
new file mode 100644 (file)
index 0000000..464cb11
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1987, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)sysexits.h  8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef        _SYSEXITS_H_
+#define        _SYSEXITS_H_
+
+/*
+ *  SYSEXITS.H -- Exit status codes for system programs.
+ *
+ *     This include file attempts to categorize possible error
+ *     exit statuses for system programs, notably delivermail
+ *     and the Berkeley network.
+ *
+ *     Error numbers begin at EX__BASE to reduce the possibility of
+ *     clashing with other exit statuses that random programs may
+ *     already return.  The meaning of the codes is approximately
+ *     as follows:
+ *
+ *     EX_USAGE -- The command was used incorrectly, e.g., with
+ *             the wrong number of arguments, a bad flag, a bad
+ *             syntax in a parameter, or whatever.
+ *     EX_DATAERR -- The input data was incorrect in some way.
+ *             This should only be used for user's data & not
+ *             system files.
+ *     EX_NOINPUT -- An input file (not a system file) did not
+ *             exist or was not readable.  This could also include
+ *             errors like "No message" to a mailer (if it cared
+ *             to catch it).
+ *     EX_NOUSER -- The user specified did not exist.  This might
+ *             be used for mail addresses or remote logins.
+ *     EX_NOHOST -- The host specified did not exist.  This is used
+ *             in mail addresses or network requests.
+ *     EX_UNAVAILABLE -- A service is unavailable.  This can occur
+ *             if a support program or file does not exist.  This
+ *             can also be used as a catchall message when something
+ *             you wanted to do doesn't work, but you don't know
+ *             why.
+ *     EX_SOFTWARE -- An internal software error has been detected.
+ *             This should be limited to non-operating system related
+ *             errors as possible.
+ *     EX_OSERR -- An operating system error has been detected.
+ *             This is intended to be used for such things as "cannot
+ *             fork", "cannot create pipe", or the like.  It includes
+ *             things like getuid returning a user that does not
+ *             exist in the passwd file.
+ *     EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
+ *             etc.) does not exist, cannot be opened, or has some
+ *             sort of error (e.g., syntax error).
+ *     EX_CANTCREAT -- A (user specified) output file cannot be
+ *             created.
+ *     EX_IOERR -- An error occurred while doing I/O on some file.
+ *     EX_TEMPFAIL -- temporary failure, indicating something that
+ *             is not really an error.  In sendmail, this means
+ *             that a mailer (e.g.) could not create a connection,
+ *             and the request should be reattempted later.
+ *     EX_PROTOCOL -- the remote system returned something that
+ *             was "not possible" during a protocol exchange.
+ *     EX_NOPERM -- You did not have sufficient permission to
+ *             perform the operation.  This is not intended for
+ *             file system problems, which should use NOINPUT or
+ *             CANTCREAT, but rather for higher level permissions.
+ */
+
+#define EX_OK          0       /* successful termination */
+
+#define EX__BASE       64      /* base value for error messages */
+
+#define EX_USAGE       64      /* command line usage error */
+#define EX_DATAERR     65      /* data format error */
+#define EX_NOINPUT     66      /* cannot open input */
+#define EX_NOUSER      67      /* addressee unknown */
+#define EX_NOHOST      68      /* host name unknown */
+#define EX_UNAVAILABLE 69      /* service unavailable */
+#define EX_SOFTWARE    70      /* internal software error */
+#define EX_OSERR       71      /* system error (e.g., can't fork) */
+#define EX_OSFILE      72      /* critical OS file missing */
+#define EX_CANTCREAT   73      /* can't create (user) output file */
+#define EX_IOERR       74      /* input/output error */
+#define EX_TEMPFAIL    75      /* temp failure; user is invited to retry */
+#define EX_PROTOCOL    76      /* remote error in protocol */
+#define EX_NOPERM      77      /* permission denied */
+#define EX_CONFIG      78      /* configuration error */
+
+#define EX__MAX        78      /* maximum listed value */
+
+#endif /* !_SYSEXITS_H_ */
index 45c7a6c..f27d70b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)trace.c    5.6 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)trace.c    8.1 (Berkeley) 6/7/93";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
diff --git a/usr.sbin/sendmail/src/udb.c b/usr.sbin/sendmail/src/udb.c
new file mode 100644 (file)
index 0000000..d0987d4
--- /dev/null
@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) 1983 Eric P. Allman
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "sendmail.h"
+
+#ifndef lint
+#ifdef USERDB
+static char sccsid [] = "@(#)udb.c     8.1 (Berkeley) 6/7/93 (with USERDB)";
+#else
+static char sccsid [] = "@(#)udb.c     8.1 (Berkeley) 6/7/93 (without USERDB)";
+#endif
+#endif
+
+#ifdef USERDB
+
+#include <sys/time.h>
+#include <errno.h>
+#include <netdb.h>
+#include <db.h>
+
+/*
+**  UDB.C -- interface between sendmail and Berkeley User Data Base.
+**
+**     This depends on the 4.4BSD db package.
+*/
+
+
+struct udbent
+{
+       char    *udb_spec;              /* string version of spec */
+       int     udb_type;               /* type of entry */
+       char    *udb_default;           /* default host for outgoing mail */
+       union
+       {
+               /* type UE_REMOTE -- do remote call for lookup */
+               struct
+               {
+                       struct sockaddr_in _udb_addr;   /* address */
+                       int             _udb_timeout;   /* timeout */
+               } udb_remote;
+#define udb_addr       udb_u.udb_remote._udb_addr
+#define udb_timeout    udb_u.udb_remote._udb_timeout
+
+               /* type UE_FORWARD -- forward message to remote */
+               struct
+               {
+                       char    *_udb_fwdhost;  /* name of forward host */
+               } udb_forward;
+#define udb_fwdhost    udb_u.udb_forward._udb_fwdhost
+
+               /* type UE_FETCH -- lookup in local database */
+               struct
+               {
+                       char    *_udb_dbname;   /* pathname of database */
+                       DB      *_udb_dbp;      /* open database ptr */
+               } udb_lookup;
+#define udb_dbname     udb_u.udb_lookup._udb_dbname
+#define udb_dbp                udb_u.udb_lookup._udb_dbp
+       } udb_u;
+};
+
+#define UDB_EOLIST     0       /* end of list */
+#define UDB_SKIP       1       /* skip this entry */
+#define UDB_REMOTE     2       /* look up in remote database */
+#define UDB_DBFETCH    3       /* look up in local database */
+#define UDB_FORWARD    4       /* forward to remote host */
+
+#define MAXUDBENT      10      /* maximum number of UDB entries */
+
+
+struct option
+{
+       char    *name;
+       char    *val;
+};
+\f/*
+**  UDBEXPAND -- look up user in database and expand
+**
+**     Parameters:
+**             a -- address to expand.
+**             sendq -- pointer to head of sendq to put the expansions in.
+**
+**     Returns:
+**             EX_TEMPFAIL -- if something "odd" happened -- probably due
+**                     to accessing a file on an NFS server that is down.
+**             EX_OK -- otherwise.
+**
+**     Side Effects:
+**             Modifies sendq.
+*/
+
+int    UdbPort = 1616;
+int    UdbTimeout = 10;
+
+struct udbent  UdbEnts[MAXUDBENT + 1];
+int            UdbSock = -1;
+bool           UdbInitialized = FALSE;
+
+int
+udbexpand(a, sendq, e)
+       register ADDRESS *a;
+       ADDRESS **sendq;
+       register ENVELOPE *e;
+{
+       int i;
+       register char *p;
+       DBT key;
+       DBT info;
+       bool breakout;
+       register struct udbent *up;
+       int keylen;
+       int naddrs;
+       char keybuf[MAXKEY];
+       char buf[BUFSIZ];
+
+       if (tTd(28, 1))
+               printf("udbexpand(%s)\n", a->q_paddr);
+
+       /* make certain we are supposed to send to this address */
+       if (bitset(QDONTSEND|QVERIFIED, a->q_flags))
+               return EX_OK;
+       e->e_to = a->q_paddr;
+
+       /* on first call, locate the database */
+       if (!UdbInitialized)
+       {
+               extern int _udbx_init();
+
+               if (_udbx_init() == EX_TEMPFAIL)
+                       return EX_TEMPFAIL;
+       }
+
+       /* short circuit the process if no chance of a match */
+       if (UdbSpec == NULL || UdbSpec[0] == '\0')
+               return EX_OK;
+
+       /* if name is too long, assume it won't match */
+       if (strlen(a->q_user) > sizeof keybuf - 12)
+               return EX_OK;
+
+       /* if name begins with a colon, it indicates our metadata */
+       if (a->q_user[0] == ':')
+               return EX_OK;
+
+       /* build actual database key */
+       (void) strcpy(keybuf, a->q_user);
+       (void) strcat(keybuf, ":maildrop");
+       keylen = strlen(keybuf);
+
+       breakout = FALSE;
+       for (up = UdbEnts; !breakout; up++)
+       {
+               char *user;
+
+               /*
+               **  Select action based on entry type.
+               **
+               **      On dropping out of this switch, "class" should
+               **      explain the type of the data, and "user" should
+               **      contain the user information.
+               */
+
+               switch (up->udb_type)
+               {
+                 case UDB_DBFETCH:
+                       key.data = keybuf;
+                       key.size = keylen;
+                       if (tTd(28, 80))
+                               printf("udbexpand: trying %s\n", keybuf);
+                       i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_CURSOR);
+                       if (i > 0 || info.size <= 0)
+                       {
+                               if (tTd(28, 2))
+                                       printf("udbexpand: no match on %s\n", keybuf);
+                               continue;
+                       }
+                       if (tTd(28, 80))
+                               printf("udbexpand: match %.*s: %.*s\n",
+                                       key.size, key.data, info.size, info.data);
+
+                       naddrs = 0;
+                       a->q_flags &= ~QSELFREF;
+                       while (i == 0 && key.size == keylen &&
+                                       bcmp(key.data, keybuf, keylen) == 0)
+                       {
+                               if (bitset(EF_VRFYONLY, e->e_flags))
+                               {
+                                       a->q_flags |= QVERIFIED;
+                                       e->e_nrcpts++;
+                                       return EX_OK;
+                               }
+
+                               breakout = TRUE;
+                               if (info.size < sizeof buf)
+                                       user = buf;
+                               else
+                                       user = xalloc(info.size + 1);
+                               bcopy(info.data, user, info.size);
+                               user[info.size] = '\0';
+
+                               message("expanded to %s", user);
+#ifdef LOG
+                               if (LogLevel >= 10)
+                                       syslog(LOG_INFO, "%s: expand %s => %s",
+                                               e->e_id, e->e_to, user);
+#endif
+                               AliasLevel++;
+                               naddrs += sendtolist(user, a, sendq, e);
+                               AliasLevel--;
+
+                               if (user != buf)
+                                       free(user);
+
+                               /* get the next record */
+                               i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT);
+                       }
+
+                       /* if nothing ever matched, try next database */
+                       if (!breakout)
+                               continue;
+
+                       if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
+                       {
+                               if (tTd(28, 5))
+                               {
+                                       printf("udbexpand: QDONTSEND ");
+                                       printaddr(a, FALSE);
+                               }
+                               a->q_flags |= QDONTSEND;
+                       }
+                       if (i < 0)
+                       {
+                               syserr("udbexpand: db-get %.*s stat %d",
+                                       key.size, key.data, i);
+                               return EX_TEMPFAIL;
+                       }
+
+                       /*
+                       **  If this address has a -request address, reflect
+                       **  it into the envelope.
+                       */
+
+                       (void) strcpy(keybuf, a->q_user);
+                       (void) strcat(keybuf, ":mailsender");
+                       keylen = strlen(keybuf);
+                       key.data = keybuf;
+                       key.size = keylen;
+                       i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
+                       if (i != 0 || info.size <= 0)
+                               break;
+                       a->q_owner = xalloc(info.size + 1);
+                       bcopy(info.data, a->q_owner, info.size);
+                       a->q_owner[info.size] = '\0';
+                       break;
+
+                 case UDB_REMOTE:
+                       /* not yet implemented */
+                       continue;
+
+                 case UDB_FORWARD:
+                       if (bitset(EF_VRFYONLY, e->e_flags))
+                               return EX_OK;
+                       i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1;
+                       if (i < sizeof buf)
+                               user = buf;
+                       else
+                               user = xalloc(i + 1);
+                       (void) sprintf(user, "%s@%s", a->q_user, up->udb_fwdhost);
+                       message("expanded to %s", user);
+                       a->q_flags &= ~QSELFREF;
+                       AliasLevel++;
+                       naddrs = sendtolist(user, a, sendq, e);
+                       AliasLevel--;
+                       if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
+                       {
+                               if (tTd(28, 5))
+                               {
+                                       printf("udbexpand: QDONTSEND ");
+                                       printaddr(a, FALSE);
+                               }
+                               a->q_flags |= QDONTSEND;
+                       }
+                       if (user != buf)
+                               free(user);
+                       breakout = TRUE;
+                       break;
+
+                 case UDB_EOLIST:
+                       breakout = TRUE;
+                       continue;
+
+                 default:
+                       /* unknown entry type */
+                       continue;
+               }
+       }
+       return EX_OK;
+}
+\f/*
+**  UDBSENDER -- return canonical external name of sender, given local name
+**
+**     Parameters:
+**             sender -- the name of the sender on the local machine.
+**
+**     Returns:
+**             The external name for this sender, if derivable from the
+**                     database.
+**             NULL -- if nothing is changed from the database.
+**
+**     Side Effects:
+**             none.
+*/
+
+char *
+udbsender(sender)
+       char *sender;
+{
+       register char *p;
+       register struct udbent *up;
+       int i;
+       int keylen;
+       DBT key, info;
+       char keybuf[MAXKEY];
+
+       if (tTd(28, 1))
+               printf("udbsender(%s)\n", sender);
+
+       if (!UdbInitialized)
+       {
+               if (_udbx_init() == EX_TEMPFAIL)
+                       return NULL;
+       }
+
+       /* short circuit if no spec */
+       if (UdbSpec == NULL || UdbSpec[0] == '\0')
+               return NULL;
+
+       /* long names can never match and are a pain to deal with */
+       if (strlen(sender) > sizeof keybuf - 12)
+               return NULL;
+
+       /* names beginning with colons indicate metadata */
+       if (sender[0] == ':')
+               return NULL;
+
+       /* build database key */
+       (void) strcpy(keybuf, sender);
+       (void) strcat(keybuf, ":mailname");
+       keylen = strlen(keybuf);
+
+       for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
+       {
+               /*
+               **  Select action based on entry type.
+               */
+
+               switch (up->udb_type)
+               {
+                 case UDB_DBFETCH:
+                       key.data = keybuf;
+                       key.size = keylen;
+                       i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
+                       if (i != 0 || info.size <= 0)
+                       {
+                               if (tTd(28, 2))
+                                       printf("udbsender: no match on %s\n",
+                                                       keybuf);
+                               continue;
+                       }
+
+                       p = xalloc(info.size + 1);
+                       bcopy(info.data, p, info.size);
+                       p[info.size] = '\0';
+                       if (tTd(28, 1))
+                               printf("udbsender ==> %s\n", p);
+                       return p;
+               }
+       }
+
+       /*
+       **  Nothing yet.  Search again for a default case.  But only
+       **  use it if we also have a forward (:maildrop) pointer already
+       **  in the database.
+       */
+
+       /* build database key */
+       (void) strcpy(keybuf, sender);
+       (void) strcat(keybuf, ":maildrop");
+       keylen = strlen(keybuf);
+
+       for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
+       {
+               switch (up->udb_type)
+               {
+                 case UDB_DBFETCH:
+                       /* get the default case for this database */
+                       if (up->udb_default == NULL)
+                       {
+                               key.data = ":default:mailname";
+                               key.size = strlen(key.data);
+                               i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
+                               if (i != 0 || info.size <= 0)
+                               {
+                                       /* no default case */
+                                       up->udb_default = "";
+                                       continue;
+                               }
+
+                               /* save the default case */
+                               up->udb_default = xalloc(info.size + 1);
+                               bcopy(info.data, up->udb_default, info.size);
+                               up->udb_default[info.size] = '\0';
+                       }
+                       else if (up->udb_default[0] == '\0')
+                               continue;
+
+                       /* we have a default case -- verify user:maildrop */
+                       key.data = keybuf;
+                       key.size = keylen;
+                       i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0);
+                       if (i != 0 || info.size <= 0)
+                       {
+                               /* nope -- no aliasing for this user */
+                               continue;
+                       }
+
+                       /* they exist -- build the actual address */
+                       p = xalloc(strlen(sender) + strlen(up->udb_default) + 2);
+                       (void) strcpy(p, sender);
+                       (void) strcat(p, "@");
+                       (void) strcat(p, up->udb_default);
+                       if (tTd(28, 1))
+                               printf("udbsender ==> %s\n", p);
+                       return p;
+               }
+       }
+
+       /* still nothing....  too bad */
+       return NULL;
+}
+\f/*
+**  _UDBX_INIT -- parse the UDB specification, opening any valid entries.
+**
+**     Parameters:
+**             none.
+**
+**     Returns:
+**             EX_TEMPFAIL -- if it appeared it couldn't get hold of a
+**                     database due to a host being down or some similar
+**                     (recoverable) situation.
+**             EX_OK -- otherwise.
+**
+**     Side Effects:
+**             Fills in the UdbEnts structure from UdbSpec.
+*/
+
+#define MAXUDBOPTS     27
+
+int
+_udbx_init()
+{
+       register char *p;
+       int i;
+       register struct udbent *up;
+       char buf[BUFSIZ];
+
+       if (UdbInitialized)
+               return EX_OK;
+
+# ifdef UDB_DEFAULT_SPEC
+       if (UdbSpec == NULL)
+               UdbSpec = UDB_DEFAULT_SPEC;
+# endif
+
+       p = UdbSpec;
+       up = UdbEnts;
+       while (p != NULL)
+       {
+               char *spec;
+               auto int rcode;
+               int nopts;
+               int nmx;
+               register struct hostent *h;
+               char *mxhosts[MAXMXHOSTS + 1];
+               struct option opts[MAXUDBOPTS + 1];
+
+               while (*p == ' ' || *p == '\t' || *p == ',')
+                       p++;
+               if (*p == '\0')
+                       break;
+               spec = p;
+               p = strchr(p, ',');
+               if (p != NULL)
+                       *p++ = '\0';
+
+               /* extract options */
+               nopts = _udb_parsespec(spec, opts, MAXUDBOPTS);
+
+               /*
+               **  Decode database specification.
+               **
+               **      In the sendmail tradition, the leading character
+               **      defines the semantics of the rest of the entry.
+               **
+               **      +hostname --    send a datagram to the udb server
+               **                      on host "hostname" asking for the
+               **                      home mail server for this user.
+               **      *hostname --    similar to +hostname, except that the
+               **                      hostname is searched as an MX record;
+               **                      resulting hosts are searched as for
+               **                      +mxhostname.  If no MX host is found,
+               **                      this is the same as +hostname.
+               **      @hostname --    forward email to the indicated host.
+               **                      This should be the last in the list,
+               **                      since it always matches the input.
+               **      /dbname  --     search the named database on the local
+               **                      host using the Berkeley db package.
+               */
+
+               switch (*spec)
+               {
+                 case '+':     /* search remote database */
+                 case '*':     /* search remote database (expand MX) */
+                       if (*spec == '*')
+                       {
+#ifdef NAMED_BIND
+                               nmx = getmxrr(spec + 1, mxhosts, FALSE, &rcode);
+#else
+                               mxhosts[0] = spec + 1;
+                               nmx = 1;
+                               rcode = 0;
+#endif
+                               if (tTd(28, 16))
+                               {
+                                       int i;
+
+                                       printf("getmxrr(%s): %d", spec + 1, nmx);
+                                       for (i = 0; i <= nmx; i++)
+                                               printf(" %s", mxhosts[i]);
+                                       printf("\n");
+                               }
+                       }
+                       else
+                       {
+                               nmx = 1;
+                               mxhosts[0] = spec + 1;
+                       }
+
+                       for (i = 0; i < nmx; i++)
+                       {
+                               h = gethostbyname(mxhosts[i]);
+                               if (h == NULL)
+                                       continue;
+                               up->udb_type = UDB_REMOTE;
+                               up->udb_addr.sin_family = h->h_addrtype;
+                               bcopy(h->h_addr_list[0],
+                                     (char *) &up->udb_addr.sin_addr,
+                                     h->h_length);
+                               up->udb_addr.sin_port = UdbPort;
+                               up->udb_timeout = UdbTimeout;
+                               up++;
+                       }
+
+                       /* set up a datagram socket */
+                       if (UdbSock < 0)
+                       {
+                               UdbSock = socket(AF_INET, SOCK_DGRAM, 0);
+                               (void) fcntl(UdbSock, F_SETFD, 1);
+                       }
+                       break;
+
+                 case '@':     /* forward to remote host */
+                       up->udb_type = UDB_FORWARD;
+                       up->udb_fwdhost = spec + 1;
+                       up++;
+                       break;
+
+                 case '/':     /* look up remote name */
+                       up->udb_dbname = spec;
+                       errno = 0;
+                       up->udb_dbp = dbopen(spec, O_RDONLY, 0644, DB_BTREE, NULL);
+                       if (up->udb_dbp == NULL)
+                       {
+                               if (errno != ENOENT && errno != EACCES)
+                               {
+#ifdef LOG
+                                       if (LogLevel > 2)
+                                               syslog(LOG_ERR, "dbopen(%s): %s",
+                                                       spec, errstring(errno));
+#endif
+                                       up->udb_type = UDB_EOLIST;
+                                       goto tempfail;
+                               }
+                               break;
+                       }
+                       up->udb_type = UDB_DBFETCH;
+                       up++;
+                       break;
+               }
+       }
+       up->udb_type = UDB_EOLIST;
+
+       if (tTd(28, 4))
+       {
+               for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
+               {
+                       switch (up->udb_type)
+                       {
+                         case UDB_REMOTE:
+                               printf("REMOTE: addr %s, timeo %d\n",
+                                       anynet_ntoa((SOCKADDR *) &up->udb_addr),
+                                       up->udb_timeout);
+                               break;
+
+                         case UDB_DBFETCH:
+                               printf("FETCH: file %s\n",
+                                       up->udb_dbname);
+                               break;
+
+                         case UDB_FORWARD:
+                               printf("FORWARD: host %s\n",
+                                       up->udb_fwdhost);
+                               break;
+
+                         default:
+                               printf("UNKNOWN\n");
+                               break;
+                       }
+               }
+       }
+
+       UdbInitialized = TRUE;
+       errno = 0;
+       return EX_OK;
+
+       /*
+       **  On temporary failure, back out anything we've already done
+       */
+
+  tempfail:
+       for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
+       {
+               if (up->udb_type == UDB_DBFETCH)
+               {
+                       (*up->udb_dbp->close)(up->udb_dbp);
+               }
+       }
+       return EX_TEMPFAIL;
+}
+
+int
+_udb_parsespec(udbspec, opt, maxopts)
+       char *udbspec;
+       struct option opt[];
+       int maxopts;
+{
+       register char *spec;
+       register char *spec_end;
+       register int optnum;
+
+       spec_end = strchr(udbspec, ':');
+       for (optnum = 0; optnum < maxopts && (spec = spec_end) != NULL; optnum++)
+       {
+               register char *p;
+
+               while (isascii(*spec) && isspace(*spec))
+                       spec++;
+               spec_end = strchr(spec, ':');
+               if (spec_end != NULL)
+                       *spec_end++ = '\0';
+
+               opt[optnum].name = spec;
+               opt[optnum].val = NULL;
+               p = strchr(spec, '=');
+               if (p != NULL)
+                       opt[optnum].val = ++p;
+       }
+       return optnum;
+}
+
+#else /* not USERDB */
+
+int
+udbexpand(a, sendq, e)
+       ADDRESS *a;
+       ADDRESS **sendq;
+       ENVELOPE *e;
+{
+       return EX_OK;
+}
+
+#endif /* USERDB */
index 9a22d6a..944eb5c 100644 (file)
@@ -1,6 +1,6 @@
 /*
 /*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -30,7 +30,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)useful.h    4.6 (Berkeley) 6/1/90
+ *     @(#)useful.h    8.1 (Berkeley) 6/7/93
  */
 
 # include <sys/types.h>
  */
 
 # include <sys/types.h>
@@ -42,7 +42,7 @@ typedef char  bool;
 
 # ifndef NULL
 # define NULL  0
 
 # ifndef NULL
 # define NULL  0
-# endif NULL
+# endif /* NULL */
 
 /* bit hacking */
 # define bitset(bit, word)     (((word) & (bit)) != 0)
 
 /* bit hacking */
 # define bitset(bit, word)     (((word) & (bit)) != 0)
@@ -51,7 +51,7 @@ typedef char  bool;
 # ifndef max
 # define max(a, b)     ((a) > (b) ? (a) : (b))
 # define min(a, b)     ((a) < (b) ? (a) : (b))
 # ifndef max
 # define max(a, b)     ((a) > (b) ? (a) : (b))
 # define min(a, b)     ((a) < (b) ? (a) : (b))
-# endif max
+# endif
 
 /* assertions */
 # ifndef NASSERT
 
 /* assertions */
 # ifndef NASSERT
@@ -61,23 +61,13 @@ typedef char        bool;
                fprintf(stderr, "assertion botch: %s:%d: ", __FILE__, __LINE__);\
                fprintf(stderr, msg, parm);\
        }
                fprintf(stderr, "assertion botch: %s:%d: ", __FILE__, __LINE__);\
                fprintf(stderr, msg, parm);\
        }
-# else NASSERT
+# else /* NASSERT */
 # define ASSERT(expr, msg, parm)
 # define ASSERT(expr, msg, parm)
-# endif NASSERT
+# endif /* NASSERT */
 
 /* sccs id's */
 # ifndef lint
 # define SCCSID(arg)   static char SccsId[] = "arg";
 
 /* sccs id's */
 # ifndef lint
 # define SCCSID(arg)   static char SccsId[] = "arg";
-# else lint
+# else
 # define SCCSID(arg)
 # define SCCSID(arg)
-# endif lint
-
-/* define the types of some common functions */
-extern char    *strcpy(), *strncpy();
-extern char    *strcat(), *strncat();
-extern char    *malloc();
-extern char    *index(), *rindex();
-extern int     errno;
-extern time_t  time();
-extern char    *ctime();
-extern char    *getenv();
+# endif
index 1d15c18..254f0bc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,9 +36,9 @@
 
 #ifndef lint
 #ifdef SMTP
 
 #ifndef lint
 #ifdef SMTP
-static char sccsid[] = "@(#)usersmtp.c 5.16 (Berkeley) 3/2/91 (with SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.1 (Berkeley) 6/7/93 (with SMTP)";
 #else
 #else
-static char sccsid[] = "@(#)usersmtp.c 5.16 (Berkeley) 3/2/91 (without SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.1 (Berkeley) 6/7/93 (without SMTP)";
 #endif
 #endif /* not lint */
 
 #endif
 #endif /* not lint */
 
@@ -60,16 +60,11 @@ static char sccsid[] = "@(#)usersmtp.c      5.16 (Berkeley) 3/2/91 (without SMTP)";
 char   SmtpMsgBuffer[MAXLINE];         /* buffer for commands */
 char   SmtpReplyBuffer[MAXLINE];       /* buffer for replies */
 char   SmtpError[MAXLINE] = "";        /* save failure error messages */
 char   SmtpMsgBuffer[MAXLINE];         /* buffer for commands */
 char   SmtpReplyBuffer[MAXLINE];       /* buffer for replies */
 char   SmtpError[MAXLINE] = "";        /* save failure error messages */
-FILE   *SmtpOut;                       /* output file */
-FILE   *SmtpIn;                        /* input file */
 int    SmtpPid;                        /* pid of mailer */
 
 int    SmtpPid;                        /* pid of mailer */
 
-/* following represents the state of the SMTP connection */
-int    SmtpState;                      /* connection state, see below */
-
-#define SMTP_CLOSED    0               /* connection is closed */
-#define SMTP_OPEN      1               /* connection is open for business */
-#define SMTP_SSD       2               /* service shutting down */
+#ifdef __STDC__
+extern smtpmessage(char *f, MAILER *m, MCI *mci, ...);
+#endif
 \f/*
 **  SMTPINIT -- initialize SMTP.
 **
 \f/*
 **  SMTPINIT -- initialize SMTP.
 **
@@ -81,67 +76,59 @@ int SmtpState;                      /* connection state, see below */
 **                     the mailer.
 **
 **     Returns:
 **                     the mailer.
 **
 **     Returns:
-**             appropriate exit status -- EX_OK on success.
-**             If not EX_OK, it should close the connection.
+**             none.
 **
 **     Side Effects:
 **             creates connection and sends initial protocol.
 */
 
 **
 **     Side Effects:
 **             creates connection and sends initial protocol.
 */
 
-jmp_buf        CtxGreeting;
-
-smtpinit(m, pvp)
+smtpinit(m, mci, e)
        struct mailer *m;
        struct mailer *m;
-       char **pvp;
+       register MCI *mci;
+       ENVELOPE *e;
 {
        register int r;
 {
        register int r;
-       EVENT *gte;
-       char buf[MAXNAME];
-       static int greettimeout();
+       register char *p;
+       extern void esmtp_check();
+       extern void helo_options();
+
+       if (tTd(17, 1))
+       {
+               printf("smtpinit ");
+               mci_dump(mci);
+       }
 
        /*
        **  Open the connection to the mailer.
        */
 
 
        /*
        **  Open the connection to the mailer.
        */
 
-       if (SmtpState == SMTP_OPEN)
-               syserr("smtpinit: already open");
-
-       SmtpIn = SmtpOut = NULL;
-       SmtpState = SMTP_CLOSED;
        SmtpError[0] = '\0';
        SmtpError[0] = '\0';
-       SmtpPhase = "user open";
-       setproctitle("%s %s: %s", CurEnv->e_id, pvp[1], SmtpPhase);
-       SmtpPid = openmailer(m, pvp, (ADDRESS *) NULL, TRUE, &SmtpOut, &SmtpIn);
-       if (SmtpPid < 0)
+       CurHostName = mci->mci_host;            /* XXX UGLY XXX */
+       switch (mci->mci_state)
        {
        {
-               if (tTd(18, 1))
-                       printf("smtpinit: cannot open %s: stat %d errno %d\n",
-                          pvp[0], ExitStat, errno);
-               if (CurEnv->e_xfp != NULL)
-               {
-                       register char *p;
-                       extern char *errstring();
-                       extern char *statstring();
+         case MCIS_ACTIVE:
+               /* need to clear old information */
+               smtprset(m, mci, e);
+               /* fall through */
 
 
-                       if (errno == 0)
-                       {
-                               p = statstring(ExitStat);
-                               fprintf(CurEnv->e_xfp,
-                                       "%.3s %s.%s... %s\n",
-                                       p, pvp[1], m->m_name, p);
-                       }
-                       else
-                       {
-                               r = errno;
-                               fprintf(CurEnv->e_xfp,
-                                       "421 %s.%s... Deferred: %s\n",
-                                       pvp[1], m->m_name, errstring(errno));
-                               errno = r;
-                       }
-               }
-               return (ExitStat);
+         case MCIS_OPEN:
+               return;
+
+         case MCIS_ERROR:
+         case MCIS_SSD:
+               /* shouldn't happen */
+               smtpquit(m, mci, e);
+               /* fall through */
+
+         case MCIS_CLOSED:
+               syserr("451 smtpinit: state CLOSED");
+               return;
+
+         case MCIS_OPENING:
+               break;
        }
        }
-       SmtpState = SMTP_OPEN;
+
+       mci->mci_state = MCIS_OPENING;
 
        /*
        **  Get the greeting message.
 
        /*
        **  Get the greeting message.
@@ -149,31 +136,66 @@ smtpinit(m, pvp)
        **      happen.
        */
 
        **      happen.
        */
 
-       if (setjmp(CtxGreeting) != 0)
-               goto tempfail;
-       gte = setevent((time_t) 300, greettimeout, 0);
-       SmtpPhase = "greeting wait";
-       setproctitle("%s %s: %s", CurEnv->e_id, CurHostName, SmtpPhase);
-       r = reply(m);
-       clrevent(gte);
+       SmtpPhase = mci->mci_phase = "client greeting";
+       setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+       r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check);
        if (r < 0 || REPLYTYPE(r) != 2)
        if (r < 0 || REPLYTYPE(r) != 2)
-               goto tempfail;
+               goto tempfail1;
 
        /*
        **  Send the HELO command.
        **      My mother taught me to always introduce myself.
        */
 
 
        /*
        **  Send the HELO command.
        **      My mother taught me to always introduce myself.
        */
 
-       smtpmessage("HELO %s", m, MyHostName);
-       SmtpPhase = "HELO wait";
-       setproctitle("%s %s: %s", CurEnv->e_id, CurHostName, SmtpPhase);
-       r = reply(m);
+       if (bitnset(M_ESMTP, m->m_flags))
+               mci->mci_flags |= MCIF_ESMTP;
+
+tryhelo:
+       if (bitset(MCIF_ESMTP, mci->mci_flags))
+       {
+               smtpmessage("EHLO %s", m, mci, MyHostName);
+               SmtpPhase = mci->mci_phase = "client EHLO";
+       }
+       else
+       {
+               smtpmessage("HELO %s", m, mci, MyHostName);
+               SmtpPhase = mci->mci_phase = "client HELO";
+       }
+       setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+       r = reply(m, mci, e, TimeOuts.to_helo, helo_options);
        if (r < 0)
        if (r < 0)
-               goto tempfail;
+               goto tempfail1;
        else if (REPLYTYPE(r) == 5)
        else if (REPLYTYPE(r) == 5)
+       {
+               if (bitset(MCIF_ESMTP, mci->mci_flags))
+               {
+                       /* try old SMTP instead */
+                       mci->mci_flags &= ~MCIF_ESMTP;
+                       goto tryhelo;
+               }
                goto unavailable;
                goto unavailable;
+       }
        else if (REPLYTYPE(r) != 2)
        else if (REPLYTYPE(r) != 2)
-               goto tempfail;
+               goto tempfail1;
+
+       /*
+       **  Check to see if we actually ended up talking to ourself.
+       **  This means we didn't know about an alias or MX, or we managed
+       **  to connect to an echo server.
+       */
+
+       p = strchr(&SmtpReplyBuffer[4], ' ');
+       if (p != NULL)
+               *p = '\0';
+       if (strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
+       {
+               syserr("553 %s config error: mail loops back to myself",
+                       MyHostName);
+               mci->mci_exitstat = EX_CONFIG;
+               mci->mci_errno = 0;
+               smtpquit(m, mci, e);
+               return;
+       }
 
        /*
        **  If this is expected to be another sendmail, send some internal
 
        /*
        **  If this is expected to be another sendmail, send some internal
@@ -183,65 +205,180 @@ smtpinit(m, pvp)
        if (bitnset(M_INTERNAL, m->m_flags))
        {
                /* tell it to be verbose */
        if (bitnset(M_INTERNAL, m->m_flags))
        {
                /* tell it to be verbose */
-               smtpmessage("VERB", m);
-               r = reply(m);
+               smtpmessage("VERB", m, mci);
+               r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
                if (r < 0)
                if (r < 0)
-                       goto tempfail;
+                       goto tempfail2;
+       }
 
 
-               /* tell it we will be sending one transaction only */
-               smtpmessage("ONEX", m);
-               r = reply(m);
-               if (r < 0)
-                       goto tempfail;
+       mci->mci_state = MCIS_OPEN;
+       return;
+
+  tempfail1:
+  tempfail2:
+       mci->mci_exitstat = EX_TEMPFAIL;
+       if (mci->mci_errno == 0)
+               mci->mci_errno = errno;
+       if (mci->mci_state != MCIS_CLOSED)
+               smtpquit(m, mci, e);
+       return;
+
+  unavailable:
+       mci->mci_exitstat = EX_UNAVAILABLE;
+       mci->mci_errno = errno;
+       smtpquit(m, mci, e);
+       return;
+}
+\f/*
+**  ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol
+**
+**
+**     Parameters:
+**             line -- the response line.
+**             m -- the mailer.
+**             mci -- the mailer connection info.
+**             e -- the envelope.
+**
+**     Returns:
+**             none.
+*/
+
+void
+esmtp_check(line, m, mci, e)
+       char *line;
+       MAILER *m;
+       register MCI *mci;
+       ENVELOPE *e;
+{
+       if (strlen(line) < 5)
+               return;
+       line += 4;
+       if (strncmp(line, "ESMTP ", 6) == 0)
+               mci->mci_flags |= MCIF_ESMTP;
+}
+\f/*
+**  HELO_OPTIONS -- process the options on a HELO line.
+**
+**     Parameters:
+**             line -- the response line.
+**             m -- the mailer.
+**             mci -- the mailer connection info.
+**             e -- the envelope.
+**
+**     Returns:
+**             none.
+*/
+
+void
+helo_options(line, m, mci, e)
+       char *line;
+       MAILER *m;
+       register MCI *mci;
+       ENVELOPE *e;
+{
+       register char *p;
+
+       if (strlen(line) < 5)
+               return;
+       line += 4;
+       p = strchr(line, ' ');
+       if (p != NULL)
+               *p++ = '\0';
+       if (strcasecmp(line, "size") == 0)
+       {
+               mci->mci_flags |= MCIF_SIZE;
+               if (p != NULL)
+                       mci->mci_maxsize = atol(p);
        }
        }
+       else if (strcasecmp(line, "8bitmime") == 0)
+               mci->mci_flags |= MCIF_8BITMIME;
+       else if (strcasecmp(line, "expn") == 0)
+               mci->mci_flags |= MCIF_EXPN;
+}
+\f/*
+**  SMTPMAILFROM -- send MAIL command
+**
+**     Parameters:
+**             m -- the mailer.
+**             mci -- the mailer connection structure.
+**             e -- the envelope (including the sender to specify).
+*/
+
+smtpmailfrom(m, mci, e)
+       struct mailer *m;
+       MCI *mci;
+       ENVELOPE *e;
+{
+       int r;
+       char buf[MAXNAME];
+       char optbuf[MAXLINE];
+
+       if (tTd(17, 2))
+               printf("smtpmailfrom: CurHost=%s\n", CurHostName);
+
+       /* set up appropriate options to include */
+       if (bitset(MCIF_SIZE, mci->mci_flags))
+               sprintf(optbuf, " SIZE=%ld", e->e_msgsize);
+       else
+               strcpy(optbuf, "");
 
        /*
        **  Send the MAIL command.
        **      Designates the sender.
        */
 
 
        /*
        **  Send the MAIL command.
        **      Designates the sender.
        */
 
-       expand("\001g", buf, &buf[sizeof buf - 1], CurEnv);
-       if (CurEnv->e_from.q_mailer == LocalMailer ||
+       mci->mci_state = MCIS_ACTIVE;
+
+       if (bitset(EF_RESPONSE, e->e_flags) &&
+           !bitnset(M_NO_NULL_FROM, m->m_flags))
+               (void) strcpy(buf, "");
+       else
+               expand("\201g", buf, &buf[sizeof buf - 1], e);
+       if (e->e_from.q_mailer == LocalMailer ||
            !bitnset(M_FROMPATH, m->m_flags))
        {
            !bitnset(M_FROMPATH, m->m_flags))
        {
-               smtpmessage("MAIL From:<%s>", m, buf);
+               smtpmessage("MAIL From:<%s>%s", m, mci, buf, optbuf);
        }
        else
        {
        }
        else
        {
-               smtpmessage("MAIL From:<@%s%c%s>", m, MyHostName,
-                       buf[0] == '@' ? ',' : ':', buf);
+               smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName,
+                       buf[0] == '@' ? ',' : ':', buf, optbuf);
        }
        }
-       SmtpPhase = "MAIL wait";
-       setproctitle("%s %s: %s", CurEnv->e_id, CurHostName, SmtpPhase);
-       r = reply(m);
+       SmtpPhase = mci->mci_phase = "client MAIL";
+       setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+       r = reply(m, mci, e, TimeOuts.to_mail, NULL);
        if (r < 0 || REPLYTYPE(r) == 4)
        if (r < 0 || REPLYTYPE(r) == 4)
-               goto tempfail;
+       {
+               mci->mci_exitstat = EX_TEMPFAIL;
+               mci->mci_errno = errno;
+               smtpquit(m, mci, e);
+               return EX_TEMPFAIL;
+       }
        else if (r == 250)
        else if (r == 250)
-               return (EX_OK);
+       {
+               mci->mci_exitstat = EX_OK;
+               return EX_OK;
+       }
        else if (r == 552)
        else if (r == 552)
-               goto unavailable;
-
-       /* protocol error -- close up */
-       smtpquit(m);
-       return (EX_PROTOCOL);
-
-       /* signal a temporary failure */
-  tempfail:
-       smtpquit(m);
-       return (EX_TEMPFAIL);
-
-       /* signal service unavailable */
-  unavailable:
-       smtpquit(m);
-       return (EX_UNAVAILABLE);
-}
+       {
+               /* signal service unavailable */
+               mci->mci_exitstat = EX_UNAVAILABLE;
+               smtpquit(m, mci, e);
+               return EX_UNAVAILABLE;
+       }
 
 
+#ifdef LOG
+       if (LogLevel > 1)
+       {
+               syslog(LOG_CRIT, "%s: SMTP MAIL protocol error: %s",
+                       e->e_id, SmtpReplyBuffer);
+       }
+#endif
 
 
-static
-greettimeout()
-{
-       /* timeout reading the greeting message */
-       longjmp(CtxGreeting, 1);
+       /* protocol error -- close up */
+       smtpquit(m, mci, e);
+       mci->mci_exitstat = EX_PROTOCOL;
+       return EX_PROTOCOL;
 }
 \f/*
 **  SMTPRCPT -- designate recipient.
 }
 \f/*
 **  SMTPRCPT -- designate recipient.
@@ -249,6 +386,8 @@ greettimeout()
 **     Parameters:
 **             to -- address of recipient.
 **             m -- the mailer we are sending to.
 **     Parameters:
 **             to -- address of recipient.
 **             m -- the mailer we are sending to.
+**             mci -- the connection info for this transaction.
+**             e -- the envelope for this transaction.
 **
 **     Returns:
 **             exit status corresponding to recipient status.
 **
 **     Returns:
 **             exit status corresponding to recipient status.
@@ -257,18 +396,19 @@ greettimeout()
 **             Sends the mail via SMTP.
 */
 
 **             Sends the mail via SMTP.
 */
 
-smtprcpt(to, m)
+smtprcpt(to, m, mci, e)
        ADDRESS *to;
        register MAILER *m;
        ADDRESS *to;
        register MAILER *m;
+       MCI *mci;
+       ENVELOPE *e;
 {
        register int r;
 {
        register int r;
-       extern char *remotename();
 
 
-       smtpmessage("RCPT To:<%s>", m, remotename(to->q_user, m, FALSE, TRUE));
+       smtpmessage("RCPT To:<%s>", m, mci, to->q_user);
 
 
-       SmtpPhase = "RCPT wait";
-       setproctitle("%s %s: %s", CurEnv->e_id, CurHostName, SmtpPhase);
-       r = reply(m);
+       SmtpPhase = mci->mci_phase = "client RCPT";
+       setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+       r = reply(m, mci, e, TimeOuts.to_rcpt, NULL);
        if (r < 0 || REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        else if (REPLYTYPE(r) == 2)
        if (r < 0 || REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        else if (REPLYTYPE(r) == 2)
@@ -277,6 +417,15 @@ smtprcpt(to, m)
                return (EX_NOUSER);
        else if (r == 552 || r == 554)
                return (EX_UNAVAILABLE);
                return (EX_NOUSER);
        else if (r == 552 || r == 554)
                return (EX_UNAVAILABLE);
+
+#ifdef LOG
+       if (LogLevel > 1)
+       {
+               syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s",
+                       e->e_id, SmtpReplyBuffer);
+       }
+#endif
+
        return (EX_PROTOCOL);
 }
 \f/*
        return (EX_PROTOCOL);
 }
 \f/*
@@ -293,8 +442,9 @@ smtprcpt(to, m)
 **             none.
 */
 
 **             none.
 */
 
-smtpdata(m, e)
+smtpdata(m, mci, e)
        struct mailer *m;
        struct mailer *m;
+       register MCI *mci;
        register ENVELOPE *e;
 {
        register int r;
        register ENVELOPE *e;
 {
        register int r;
@@ -308,37 +458,67 @@ smtpdata(m, e)
        */
 
        /* send the command and check ok to proceed */
        */
 
        /* send the command and check ok to proceed */
-       smtpmessage("DATA", m);
-       SmtpPhase = "DATA wait";
-       setproctitle("%s %s: %s", CurEnv->e_id, CurHostName, SmtpPhase);
-       r = reply(m);
+       smtpmessage("DATA", m, mci);
+       SmtpPhase = mci->mci_phase = "client DATA 354";
+       setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+       r = reply(m, mci, e, TimeOuts.to_datainit, NULL);
        if (r < 0 || REPLYTYPE(r) == 4)
        if (r < 0 || REPLYTYPE(r) == 4)
+       {
+               smtpquit(m, mci, e);
                return (EX_TEMPFAIL);
                return (EX_TEMPFAIL);
+       }
        else if (r == 554)
        else if (r == 554)
+       {
+               smtprset(m, mci, e);
                return (EX_UNAVAILABLE);
                return (EX_UNAVAILABLE);
+       }
        else if (r != 354)
        else if (r != 354)
+       {
+#ifdef LOG
+               if (LogLevel > 1)
+               {
+                       syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s",
+                               e->e_id, SmtpReplyBuffer);
+               }
+#endif
+               smtprset(m, mci, e);
                return (EX_PROTOCOL);
                return (EX_PROTOCOL);
+       }
 
        /* now output the actual message */
 
        /* now output the actual message */
-       (*e->e_puthdr)(SmtpOut, m, CurEnv);
-       putline("\n", SmtpOut, m);
-       (*e->e_putbody)(SmtpOut, m, CurEnv);
+       (*e->e_puthdr)(mci->mci_out, m, e);
+       putline("\n", mci->mci_out, m);
+       (*e->e_putbody)(mci->mci_out, m, e, NULL);
 
        /* terminate the message */
 
        /* terminate the message */
-       fprintf(SmtpOut, ".%s", m->m_eol);
-       if (Verbose && !HoldErrs)
-               nmessage(Arpa_Info, ">>> .");
+       fprintf(mci->mci_out, ".%s", m->m_eol);
+       if (Verbose)
+               nmessage(">>> .");
 
        /* check for the results of the transaction */
 
        /* check for the results of the transaction */
-       SmtpPhase = "result wait";
-       setproctitle("%s %s: %s", CurEnv->e_id, CurHostName, SmtpPhase);
-       r = reply(m);
-       if (r < 0 || REPLYTYPE(r) == 4)
+       SmtpPhase = mci->mci_phase = "client DATA 250";
+       setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+       r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
+       if (r < 0)
+       {
+               smtpquit(m, mci, e);
+               return (EX_TEMPFAIL);
+       }
+       mci->mci_state = MCIS_OPEN;
+       e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
+       if (REPLYTYPE(r) == 4)
                return (EX_TEMPFAIL);
        else if (r == 250)
                return (EX_OK);
        else if (r == 552 || r == 554)
                return (EX_UNAVAILABLE);
                return (EX_TEMPFAIL);
        else if (r == 250)
                return (EX_OK);
        else if (r == 552 || r == 554)
                return (EX_UNAVAILABLE);
+#ifdef LOG
+       if (LogLevel > 1)
+       {
+               syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s",
+                       e->e_id, SmtpReplyBuffer);
+       }
+#endif
        return (EX_PROTOCOL);
 }
 \f/*
        return (EX_PROTOCOL);
 }
 \f/*
@@ -354,40 +534,81 @@ smtpdata(m, e)
 **             sends the final protocol and closes the connection.
 */
 
 **             sends the final protocol and closes the connection.
 */
 
-smtpquit(m)
+smtpquit(m, mci, e)
        register MAILER *m;
        register MAILER *m;
+       register MCI *mci;
+       ENVELOPE *e;
 {
        int i;
 
 {
        int i;
 
-       /* if the connection is already closed, don't bother */
-       if (SmtpIn == NULL)
-               return;
-
-       /* send the quit message if not a forced quit */
-       if (SmtpState == SMTP_OPEN || SmtpState == SMTP_SSD)
+       /* send the quit message if we haven't gotten I/O error */
+       if (mci->mci_state != MCIS_ERROR)
        {
        {
-               smtpmessage("QUIT", m);
-               (void) reply(m);
-               if (SmtpState == SMTP_CLOSED)
+               SmtpPhase = "client QUIT";
+               smtpmessage("QUIT", m, mci);
+               (void) reply(m, mci, e, TimeOuts.to_quit, NULL);
+               if (mci->mci_state == MCIS_CLOSED)
                        return;
        }
 
                        return;
        }
 
-       /* now actually close the connection */
-       (void) fclose(SmtpIn);
-       (void) fclose(SmtpOut);
-       SmtpIn = SmtpOut = NULL;
-       SmtpState = SMTP_CLOSED;
-
-       /* and pick up the zombie */
-       i = endmailer(SmtpPid, m->m_argv[0]);
+       /* now actually close the connection and pick up the zombie */
+       i = endmailer(mci, e, m->m_argv);
        if (i != EX_OK)
        if (i != EX_OK)
-               syserr("smtpquit %s: stat %d", m->m_argv[0], i);
+               syserr("451 smtpquit %s: stat %d", m->m_argv[0], i);
+}
+\f/*
+**  SMTPRSET -- send a RSET (reset) command
+*/
+
+smtprset(m, mci, e)
+       register MAILER *m;
+       register MCI *mci;
+       ENVELOPE *e;
+{
+       int r;
+
+       SmtpPhase = "client RSET";
+       smtpmessage("RSET", m, mci);
+       r = reply(m, mci, e, TimeOuts.to_rset, NULL);
+       if (r < 0)
+               mci->mci_state = MCIS_ERROR;
+       else if (REPLYTYPE(r) == 2)
+       {
+               mci->mci_state = MCIS_OPEN;
+               return;
+       }
+       smtpquit(m, mci, e);
+}
+\f/*
+**  SMTPPROBE -- check the connection state
+*/
+
+smtpprobe(mci)
+       register MCI *mci;
+{
+       int r;
+       MAILER *m = mci->mci_mailer;
+       extern ENVELOPE BlankEnvelope;
+       ENVELOPE *e = &BlankEnvelope;
+
+       SmtpPhase = "client probe";
+       smtpmessage("RSET", m, mci);
+       r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
+       if (r < 0 || REPLYTYPE(r) != 2)
+               smtpquit(m, mci, e);
+       return r;
 }
 \f/*
 **  REPLY -- read arpanet reply
 **
 **     Parameters:
 **             m -- the mailer we are reading the reply from.
 }
 \f/*
 **  REPLY -- read arpanet reply
 **
 **     Parameters:
 **             m -- the mailer we are reading the reply from.
+**             mci -- the mailer connection info structure.
+**             e -- the current envelope.
+**             timeout -- the timeout for reads.
+**             pfunc -- processing function for second and subsequent
+**                     lines of response -- if null, no special
+**                     processing is done.
 **
 **     Returns:
 **             reply code it reads.
 **
 **     Returns:
 **             reply code it reads.
@@ -396,10 +617,20 @@ smtpquit(m)
 **             flushes the mail file.
 */
 
 **             flushes the mail file.
 */
 
-reply(m)
+reply(m, mci, e, timeout, pfunc)
        MAILER *m;
        MAILER *m;
+       MCI *mci;
+       ENVELOPE *e;
+       time_t timeout;
+       void (*pfunc)();
 {
 {
-       (void) fflush(SmtpOut);
+       register char *bufp;
+       register int r;
+       bool firstline = TRUE;
+       char junkbuf[MAXLINE];
+
+       if (mci->mci_out != NULL)
+               (void) fflush(mci->mci_out);
 
        if (tTd(18, 1))
                printf("reply\n");
 
        if (tTd(18, 1))
                printf("reply\n");
@@ -408,87 +639,111 @@ reply(m)
        **  Read the input line, being careful not to hang.
        */
 
        **  Read the input line, being careful not to hang.
        */
 
-       for (;;)
+       for (bufp = SmtpReplyBuffer;; bufp = junkbuf)
        {
        {
-               register int r;
                register char *p;
                register char *p;
+               extern time_t curtime();
 
                /* actually do the read */
 
                /* actually do the read */
-               if (CurEnv->e_xfp != NULL)
-                       (void) fflush(CurEnv->e_xfp);   /* for debugging */
+               if (e->e_xfp != NULL)
+                       (void) fflush(e->e_xfp);        /* for debugging */
 
                /* if we are in the process of closing just give the code */
 
                /* if we are in the process of closing just give the code */
-               if (SmtpState == SMTP_CLOSED)
+               if (mci->mci_state == MCIS_CLOSED)
                        return (SMTPCLOSING);
 
                        return (SMTPCLOSING);
 
+               if (mci->mci_out != NULL)
+                       fflush(mci->mci_out);
+
                /* get the line from the other side */
                /* get the line from the other side */
-               p = sfgets(SmtpReplyBuffer, sizeof SmtpReplyBuffer, SmtpIn);
+               p = sfgets(bufp, MAXLINE, mci->mci_in, timeout, SmtpPhase);
+               mci->mci_lastuse = curtime();
+
                if (p == NULL)
                {
                        extern char MsgBuf[];           /* err.c */
                if (p == NULL)
                {
                        extern char MsgBuf[];           /* err.c */
-                       extern char Arpa_TSyserr[];     /* conf.c */
 
                        /* if the remote end closed early, fake an error */
                        if (errno == 0)
 # ifdef ECONNRESET
                                errno = ECONNRESET;
 
                        /* if the remote end closed early, fake an error */
                        if (errno == 0)
 # ifdef ECONNRESET
                                errno = ECONNRESET;
-# else ECONNRESET
+# else /* ECONNRESET */
                                errno = EPIPE;
                                errno = EPIPE;
-# endif ECONNRESET
+# endif /* ECONNRESET */
 
 
-                       message(Arpa_TSyserr, "reply: read error");
+                       mci->mci_errno = errno;
+                       mci->mci_exitstat = EX_TEMPFAIL;
+                       message("451 %s: reply: read error from %s",
+                               e->e_id == NULL ? "NOQUEUE" : e->e_id,
+                               mci->mci_host);
                        /* if debugging, pause so we can see state */
                        if (tTd(18, 100))
                                pause();
 # ifdef LOG
                        /* if debugging, pause so we can see state */
                        if (tTd(18, 100))
                                pause();
 # ifdef LOG
-                       syslog(LOG_INFO, "%s", &MsgBuf[4]);
-# endif LOG
-                       SmtpState = SMTP_CLOSED;
-                       smtpquit(m);
+                       if (LogLevel > 1)
+                               syslog(LOG_INFO, "%s", &MsgBuf[4]);
+# endif /* LOG */
+                       mci->mci_state = MCIS_ERROR;
+                       smtpquit(m, mci, e);
                        return (-1);
                }
                        return (-1);
                }
-               fixcrlf(SmtpReplyBuffer, TRUE);
+               fixcrlf(bufp, TRUE);
 
 
-               if (CurEnv->e_xfp != NULL && index("45", SmtpReplyBuffer[0]) != NULL)
+               if (e->e_xfp != NULL && strchr("45", bufp[0]) != NULL)
                {
                        /* serious error -- log the previous command */
                        if (SmtpMsgBuffer[0] != '\0')
                {
                        /* serious error -- log the previous command */
                        if (SmtpMsgBuffer[0] != '\0')
-                               fprintf(CurEnv->e_xfp, ">>> %s\n", SmtpMsgBuffer);
+                               fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer);
                        SmtpMsgBuffer[0] = '\0';
 
                        /* now log the message as from the other side */
                        SmtpMsgBuffer[0] = '\0';
 
                        /* now log the message as from the other side */
-                       fprintf(CurEnv->e_xfp, "<<< %s\n", SmtpReplyBuffer);
+                       fprintf(e->e_xfp, "<<< %s\n", bufp);
                }
 
                /* display the input for verbose mode */
                }
 
                /* display the input for verbose mode */
-               if (Verbose && !HoldErrs)
-                       nmessage(Arpa_Info, "%s", SmtpReplyBuffer);
+               if (Verbose)
+                       nmessage("050 %s", bufp);
+
+               /* process the line */
+               if (pfunc != NULL && !firstline)
+                       (*pfunc)(bufp, m, mci, e);
+
+               firstline = FALSE;
 
                /* if continuation is required, we can go on */
 
                /* if continuation is required, we can go on */
-               if (SmtpReplyBuffer[3] == '-' || !isdigit(SmtpReplyBuffer[0]))
+               if (bufp[3] == '-')
+                       continue;
+
+               /* ignore improperly formated input */
+               if (!(isascii(bufp[0]) && isdigit(bufp[0])))
                        continue;
 
                /* decode the reply code */
                        continue;
 
                /* decode the reply code */
-               r = atoi(SmtpReplyBuffer);
+               r = atoi(bufp);
 
                /* extra semantics: 0xx codes are "informational" */
 
                /* extra semantics: 0xx codes are "informational" */
-               if (r < 100)
-                       continue;
+               if (r >= 100)
+                       break;
+       }
 
 
-               /* reply code 421 is "Service Shutting Down" */
-               if (r == SMTPCLOSING && SmtpState != SMTP_SSD)
-               {
-                       /* send the quit protocol */
-                       SmtpState = SMTP_SSD;
-                       smtpquit(m);
-               }
+       /*
+       **  Now look at SmtpReplyBuffer -- only care about the first
+       **  line of the response from here on out.
+       */
 
 
-               /* save temporary failure messages for posterity */
-               if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0')
-                       (void) strcpy(SmtpError, &SmtpReplyBuffer[4]);
+       /* save temporary failure messages for posterity */
+       if (SmtpReplyBuffer[0] == '4' && SmtpError[0] == '\0')
+               (void) strcpy(SmtpError, SmtpReplyBuffer);
 
 
-               return (r);
+       /* reply code 421 is "Service Shutting Down" */
+       if (r == SMTPCLOSING && mci->mci_state != MCIS_SSD)
+       {
+               /* send the quit protocol */
+               mci->mci_state = MCIS_SSD;
+               smtpquit(m, mci, e);
        }
        }
+
+       return (r);
 }
 \f/*
 **  SMTPMESSAGE -- send message to server
 }
 \f/*
 **  SMTPMESSAGE -- send message to server
@@ -502,20 +757,37 @@ reply(m)
 **             none.
 **
 **     Side Effects:
 **             none.
 **
 **     Side Effects:
-**             writes message to SmtpOut.
+**             writes message to mci->mci_out.
 */
 
 /*VARARGS1*/
 */
 
 /*VARARGS1*/
-smtpmessage(f, m, a, b, c)
+#ifdef __STDC__
+smtpmessage(char *f, MAILER *m, MCI *mci, ...)
+#else
+smtpmessage(f, m, mci, va_alist)
        char *f;
        MAILER *m;
        char *f;
        MAILER *m;
+       MCI *mci;
+       va_dcl
+#endif
 {
 {
-       (void) sprintf(SmtpMsgBuffer, f, a, b, c);
-       if (tTd(18, 1) || (Verbose && !HoldErrs))
-               nmessage(Arpa_Info, ">>> %s", SmtpMsgBuffer);
-       if (SmtpOut != NULL)
-               fprintf(SmtpOut, "%s%s", SmtpMsgBuffer,
-                       m == 0 ? "\r\n" : m->m_eol);
+       VA_LOCAL_DECL
+
+       VA_START(mci);
+       (void) vsprintf(SmtpMsgBuffer, f, ap);
+       VA_END;
+
+       if (tTd(18, 1) || Verbose)
+               nmessage(">>> %s", SmtpMsgBuffer);
+       if (mci->mci_out != NULL)
+       {
+               fprintf(mci->mci_out, "%s%s", SmtpMsgBuffer,
+                       m == NULL ? "\r\n" : m->m_eol);
+       }
+       else if (tTd(18, 1))
+       {
+               printf("smtpmessage: NULL mci_out\n");
+       }
 }
 
 }
 
-# endif SMTP
+# endif /* SMTP */
index 0aa5469..cbbbc4d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)util.c     5.20 (Berkeley) 3/8/91";
+static char sccsid[] = "@(#)util.c     8.1 (Berkeley) 6/27/93";
 #endif /* not lint */
 
 #endif /* not lint */
 
-# include <stdio.h>
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <sysexits.h>
-# include <errno.h>
 # include "sendmail.h"
 # include "sendmail.h"
-
-/*
+# include <sysexits.h>
+\f/*
 **  STRIPQUOTES -- Strip quotes & quote bits from a string.
 **
 **     Runs through a string and strips off unquoted quote
 **  STRIPQUOTES -- Strip quotes & quote bits from a string.
 **
 **     Runs through a string and strips off unquoted quote
@@ -51,8 +46,6 @@ static char sccsid[] = "@(#)util.c    5.20 (Berkeley) 3/8/91";
 **
 **     Parameters:
 **             s -- the string to strip.
 **
 **     Parameters:
 **             s -- the string to strip.
-**             qf -- if set, remove actual `` " '' characters
-**                     as well as the quote bits.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -64,9 +57,8 @@ static char sccsid[] = "@(#)util.c    5.20 (Berkeley) 3/8/91";
 **             deliver
 */
 
 **             deliver
 */
 
-stripquotes(s, qf)
+stripquotes(s)
        char *s;
        char *s;
-       bool qf;
 {
        register char *p;
        register char *q;
 {
        register char *p;
        register char *q;
@@ -75,76 +67,16 @@ stripquotes(s, qf)
        if (s == NULL)
                return;
 
        if (s == NULL)
                return;
 
-       for (p = q = s; (c = *p++) != '\0'; )
-       {
-               if (c != '"' || !qf)
-                       *q++ = c & 0177;
-       }
-       *q = '\0';
-}
-\f/*
-**  QSTRLEN -- give me the string length assuming 0200 bits add a char
-**
-**     Parameters:
-**             s -- the string to measure.
-**
-**     Reurns:
-**             The length of s, including space for backslash escapes.
-**
-**     Side Effects:
-**             none.
-*/
-
-qstrlen(s)
-       register char *s;
-{
-       register int l = 0;
-       register char c;
-
-       while ((c = *s++) != '\0')
-       {
-               if (bitset(0200, c))
-                       l++;
-               l++;
-       }
-       return (l);
-}
-\f/*
-**  CAPITALIZE -- return a copy of a string, properly capitalized.
-**
-**     Parameters:
-**             s -- the string to capitalize.
-**
-**     Returns:
-**             a pointer to a properly capitalized string.
-**
-**     Side Effects:
-**             none.
-*/
-
-char *
-capitalize(s)
-       register char *s;
-{
-       static char buf[50];
-       register char *p;
-
-       p = buf;
-
-       for (;;)
+       p = q = s;
+       do
        {
        {
-               while (!isalpha(*s) && *s != '\0')
-                       *p++ = *s++;
-               if (*s == '\0')
-                       break;
-               *p++ = toupper(*s);
-               s++;
-               while (isalpha(*s))
-                       *p++ = *s++;
-       }
-
-       *p = '\0';
-       return (buf);
+               c = *p++;
+               if (c == '\\')
+                       c = *p++;
+               else if (c == '"')
+                       continue;
+               *q++ = c;
+       } while (c != '\0');
 }
 \f/*
 **  XALLOC -- Allocate memory and bitch wildly on failure.
 }
 \f/*
 **  XALLOC -- Allocate memory and bitch wildly on failure.
@@ -167,7 +99,6 @@ xalloc(sz)
        register int sz;
 {
        register char *p;
        register int sz;
 {
        register char *p;
-       extern char *malloc();
 
        p = malloc((unsigned) sz);
        if (p == NULL)
 
        p = malloc((unsigned) sz);
        if (p == NULL)
@@ -222,6 +153,45 @@ copyplist(list, copycont)
        return (newvp);
 }
 \f/*
        return (newvp);
 }
 \f/*
+**  COPYQUEUE -- copy address queue.
+**
+**     This routine is the equivalent of newstr for address queues
+**     addresses marked with QDONTSEND aren't copied
+**
+**     Parameters:
+**             addr -- list of address structures to copy.
+**
+**     Returns:
+**             a copy of 'addr'.
+**
+**     Side Effects:
+**             none.
+*/
+
+ADDRESS *
+copyqueue(addr)
+       ADDRESS *addr;
+{
+       register ADDRESS *newaddr;
+       ADDRESS *ret;
+       register ADDRESS **tail = &ret;
+
+       while (addr != NULL)
+       {
+               if (!bitset(QDONTSEND, addr->q_flags))
+               {
+                       newaddr = (ADDRESS *) xalloc(sizeof(ADDRESS));
+                       STRUCTCOPY(*addr, *newaddr);
+                       *tail = newaddr;
+                       tail = &newaddr->q_next;
+               }
+               addr = addr->q_next;
+       }
+       *tail = NULL;
+       
+       return ret;
+}
+\f/*
 **  PRINTAV -- print argument vector.
 **
 **     Parameters:
 **  PRINTAV -- print argument vector.
 **
 **     Parameters:
@@ -264,7 +234,7 @@ char
 lower(c)
        register char c;
 {
 lower(c)
        register char c;
 {
-       return(isascii(c) && isupper(c) ? tolower(c) : c);
+       return((isascii(c) && isupper(c)) ? tolower(c) : c);
 }
 \f/*
 **  XPUTS -- put string doing control escapes.
 }
 \f/*
 **  XPUTS -- put string doing control escapes.
@@ -282,29 +252,67 @@ lower(c)
 xputs(s)
        register char *s;
 {
 xputs(s)
        register char *s;
 {
-       register char c;
+       register int c;
+       register struct metamac *mp;
+       extern struct metamac MetaMacros[];
 
        if (s == NULL)
        {
                printf("<null>");
                return;
        }
 
        if (s == NULL)
        {
                printf("<null>");
                return;
        }
-       (void) putchar('"');
-       while ((c = *s++) != '\0')
+       while ((c = (*s++ & 0377)) != '\0')
        {
                if (!isascii(c))
                {
        {
                if (!isascii(c))
                {
+                       if (c == MATCHREPL || c == MACROEXPAND)
+                       {
+                               putchar('$');
+                               continue;
+                       }
+                       for (mp = MetaMacros; mp->metaname != '\0'; mp++)
+                       {
+                               if ((mp->metaval & 0377) == c)
+                               {
+                                       printf("$%c", mp->metaname);
+                                       break;
+                               }
+                       }
+                       if (mp->metaname != '\0')
+                               continue;
                        (void) putchar('\\');
                        c &= 0177;
                }
                        (void) putchar('\\');
                        c &= 0177;
                }
-               if (c < 040 || c >= 0177)
+               if (isprint(c))
+               {
+                       putchar(c);
+                       continue;
+               }
+
+               /* wasn't a meta-macro -- find another way to print it */
+               switch (c)
                {
                {
+                 case '\0':
+                       continue;
+
+                 case '\n':
+                       c = 'n';
+                       break;
+
+                 case '\r':
+                       c = 'r';
+                       break;
+
+                 case '\t':
+                       c = 't';
+                       break;
+
+                 default:
                        (void) putchar('^');
                        (void) putchar('^');
-                       c ^= 0100;
+                       (void) putchar(c ^ 0100);
+                       continue;
                }
                }
-               (void) putchar(c);
        }
        }
-       (void) putchar('"');
        (void) fflush(stdout);
 }
 \f/*
        (void) fflush(stdout);
 }
 \f/*
@@ -353,16 +361,30 @@ makelower(p)
 **             none.
 */
 
 **             none.
 */
 
-buildfname(p, login, buf)
-       register char *p;
+buildfname(gecos, login, buf)
+       register char *gecos;
        char *login;
        char *buf;
 {
        char *login;
        char *buf;
 {
+       register char *p;
        register char *bp = buf;
        register char *bp = buf;
+       int l;
+
+       if (*gecos == '*')
+               gecos++;
+
+       /* find length of final string */
+       l = 0;
+       for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
+       {
+               if (*p == '&')
+                       l += strlen(login);
+               else
+                       l++;
+       }
 
 
-       if (*p == '*')
-               p++;
-       while (*p != '\0' && *p != ',' && *p != ';' && *p != '%')
+       /* now fill in buf */
+       for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
        {
                if (*p == '&')
                {
        {
                if (*p == '&')
                {
@@ -370,10 +392,9 @@ buildfname(p, login, buf)
                        *bp = toupper(*bp);
                        while (*bp != '\0')
                                bp++;
                        *bp = toupper(*bp);
                        while (*bp != '\0')
                                bp++;
-                       p++;
                }
                else
                }
                else
-                       *bp++ = *p++;
+                       *bp++ = *p;
        }
        *bp = '\0';
 }
        }
        *bp = '\0';
 }
@@ -386,26 +407,70 @@ buildfname(p, login, buf)
 **             mode -- mode bits that must match.
 **
 **     Returns:
 **             mode -- mode bits that must match.
 **
 **     Returns:
-**             TRUE if fn exists, is owned by uid, and matches mode.
-**             FALSE otherwise.
+**             0 if fn exists, is owned by uid, and matches mode.
+**             An errno otherwise.  The actual errno is cleared.
 **
 **     Side Effects:
 **             none.
 */
 
 **
 **     Side Effects:
 **             none.
 */
 
-bool
+#ifndef S_IXOTH
+# define S_IXOTH       (S_IEXEC >> 6)
+#endif
+
+int
 safefile(fn, uid, mode)
        char *fn;
 safefile(fn, uid, mode)
        char *fn;
-       int uid;
+       uid_t uid;
        int mode;
 {
        int mode;
 {
+       register char *p;
        struct stat stbuf;
 
        struct stat stbuf;
 
-       if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == uid &&
-           (stbuf.st_mode & mode) == mode)
-               return (TRUE);
+       if (tTd(54, 4))
+               printf("safefile(%s, %d, %o): ", fn, uid, mode);
        errno = 0;
        errno = 0;
-       return (FALSE);
+
+       for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/')
+       {
+               *p = '\0';
+               if (stat(fn, &stbuf) < 0 || !bitset(S_IXOTH, stbuf.st_mode))
+               {
+                       int ret = errno;
+
+                       if (ret == 0)
+                               ret = EACCES;
+                       if (tTd(54, 4))
+                               printf("[dir %s] %s\n", fn, errstring(ret));
+                       *p = '/';
+                       return ret;
+               }
+       }
+
+       if (stat(fn, &stbuf) < 0)
+       {
+               int ret = errno;
+
+               if (tTd(54, 4))
+                       printf("%s\n", errstring(ret));
+
+               errno = 0;
+               return ret;
+       }
+       if (stbuf.st_uid != uid && uid == 0)
+               mode >>= 6;
+       if (tTd(54, 4))
+               printf("[uid %d, stat %o] ", stbuf.st_uid, stbuf.st_mode);
+       if ((stbuf.st_uid == uid || uid == 0) &&
+           (stbuf.st_mode & mode) == mode)
+       {
+               if (tTd(54, 4))
+                       printf("OK\n");
+               return 0;
+       }
+       if (tTd(54, 4))
+               printf("EACCES\n");
+       return EACCES;
 }
 \f/*
 **  FIXCRLF -- fix <CR><LF> in line.
 }
 \f/*
 **  FIXCRLF -- fix <CR><LF> in line.
@@ -432,7 +497,7 @@ fixcrlf(line, stripnl)
 {
        register char *p;
 
 {
        register char *p;
 
-       p = index(line, '\n');
+       p = strchr(line, '\n');
        if (p == NULL)
                return;
        if (p > line && p[-1] == '\r')
        if (p == NULL)
                return;
        if (p > line && p[-1] == '\r')
@@ -450,26 +515,59 @@ fixcrlf(line, stripnl)
 **     whatever), so this tries to get around it.
 */
 
 **     whatever), so this tries to get around it.
 */
 
+struct omodes
+{
+       int     mask;
+       int     mode;
+       char    *farg;
+} OpenModes[] =
+{
+       O_ACCMODE,              O_RDONLY,               "r",
+       O_ACCMODE|O_APPEND,     O_WRONLY,               "w",
+       O_ACCMODE|O_APPEND,     O_WRONLY|O_APPEND,      "a",
+       O_TRUNC,                0,                      "w+",
+       O_APPEND,               O_APPEND,               "a+",
+       0,                      0,                      "r+",
+};
+
 FILE *
 FILE *
-dfopen(filename, mode)
+dfopen(filename, omode, cmode)
        char *filename;
        char *filename;
-       char *mode;
+       int omode;
+       int cmode;
 {
        register int tries;
 {
        register int tries;
-       register FILE *fp;
+       int fd;
+       register struct omodes *om;
+       struct stat st;
+
+       for (om = OpenModes; om->mask != 0; om++)
+               if ((omode & om->mask) == om->mode)
+                       break;
 
        for (tries = 0; tries < 10; tries++)
        {
                sleep((unsigned) (10 * tries));
                errno = 0;
 
        for (tries = 0; tries < 10; tries++)
        {
                sleep((unsigned) (10 * tries));
                errno = 0;
-               fp = fopen(filename, mode);
-               if (fp != NULL)
+               fd = open(filename, omode, cmode);
+               if (fd >= 0)
                        break;
                if (errno != ENFILE && errno != EINTR)
                        break;
        }
                        break;
                if (errno != ENFILE && errno != EINTR)
                        break;
        }
-       errno = 0;
-       return (fp);
+       if (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, locktype);
+               errno = 0;
+       }
+       return fdopen(fd, om->farg);
 }
 \f/*
 **  PUTLINE -- put a line like fputs obeying SMTP conventions
 }
 \f/*
 **  PUTLINE -- put a line like fputs obeying SMTP conventions
@@ -489,8 +587,6 @@ dfopen(filename, mode)
 **             output of l to fp.
 */
 
 **             output of l to fp.
 */
 
-# define SMTPLINELIM   990     /* maximum line length */
-
 putline(l, fp, m)
        register char *l;
        FILE *fp;
 putline(l, fp, m)
        register char *l;
        FILE *fp;
@@ -500,24 +596,24 @@ putline(l, fp, m)
        register char svchar;
 
        /* strip out 0200 bits -- these can look like TELNET protocol */
        register char svchar;
 
        /* strip out 0200 bits -- these can look like TELNET protocol */
-       if (bitnset(M_LIMITS, m->m_flags))
+       if (bitnset(M_7BITS, m->m_flags))
        {
        {
-               for (p = l; svchar = *p; ++p)
-                       if (svchar & 0200)
+               for (p = l; (svchar = *p) != '\0'; ++p)
+                       if (bitset(0200, svchar))
                                *p = svchar &~ 0200;
        }
 
        do
        {
                /* find the end of the line */
                                *p = svchar &~ 0200;
        }
 
        do
        {
                /* find the end of the line */
-               p = index(l, '\n');
+               p = strchr(l, '\n');
                if (p == NULL)
                        p = &l[strlen(l)];
 
                /* check for line overflow */
                if (p == NULL)
                        p = &l[strlen(l)];
 
                /* check for line overflow */
-               while ((p - l) > SMTPLINELIM && bitnset(M_LIMITS, m->m_flags))
+               while (m->m_linelimit > 0 && (p - l) > m->m_linelimit)
                {
                {
-                       register char *q = &l[SMTPLINELIM - 1];
+                       register char *q = &l[m->m_linelimit - 1];
 
                        svchar = *q;
                        *q = '\0';
 
                        svchar = *q;
                        *q = '\0';
@@ -559,15 +655,38 @@ xunlink(f)
        register int i;
 
 # ifdef LOG
        register int i;
 
 # ifdef LOG
-       if (LogLevel > 20)
-               syslog(LOG_DEBUG, "%s: unlink %s\n", CurEnv->e_id, f);
-# endif LOG
+       if (LogLevel > 98)
+               syslog(LOG_DEBUG, "%s: unlink %s", CurEnv->e_id, f);
+# endif /* LOG */
 
        i = unlink(f);
 # ifdef LOG
 
        i = unlink(f);
 # ifdef LOG
-       if (i < 0 && LogLevel > 21)
+       if (i < 0 && LogLevel > 97)
                syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
                syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
-# endif LOG
+# endif /* LOG */
+}
+\f/*
+**  XFCLOSE -- close a file, doing logging as appropriate.
+**
+**     Parameters:
+**             fp -- file pointer for the file to close
+**             a, b -- miscellaneous crud to print for debugging
+**
+**     Returns:
+**             none.
+**
+**     Side Effects:
+**             fp is closed.
+*/
+
+xfclose(fp, a, b)
+       FILE *fp;
+       char *a, *b;
+{
+       if (tTd(53, 99))
+               printf("xfclose(%x) %s %s\n", fp, a, b);
+       if (fclose(fp) < 0 && tTd(53, 99))
+               printf("xfclose FAILURE: %s\n", errstring(errno));
 }
 \f/*
 **  SFGETS -- "safe" fgets -- times out and ignores random interrupts.
 }
 \f/*
 **  SFGETS -- "safe" fgets -- times out and ignores random interrupts.
@@ -576,6 +695,8 @@ xunlink(f)
 **             buf -- place to put the input line.
 **             siz -- size of buf.
 **             fp -- file to read from.
 **             buf -- place to put the input line.
 **             siz -- size of buf.
 **             fp -- file to read from.
+**             timeout -- the timeout before error occurs.
+**             during -- what we are trying to read (for error messages).
 **
 **     Returns:
 **             NULL on error (including timeout).  This will also leave
 **
 **     Returns:
 **             NULL on error (including timeout).  This will also leave
@@ -589,31 +710,34 @@ xunlink(f)
 static jmp_buf CtxReadTimeout;
 
 char *
 static jmp_buf CtxReadTimeout;
 
 char *
-sfgets(buf, siz, fp)
+sfgets(buf, siz, fp, timeout, during)
        char *buf;
        int siz;
        FILE *fp;
        char *buf;
        int siz;
        FILE *fp;
+       time_t timeout;
+       char *during;
 {
        register EVENT *ev = NULL;
        register char *p;
        static int readtimeout();
 
        /* set the timeout */
 {
        register EVENT *ev = NULL;
        register char *p;
        static int readtimeout();
 
        /* set the timeout */
-       if (ReadTimeout != 0)
+       if (timeout != 0)
        {
                if (setjmp(CtxReadTimeout) != 0)
                {
 # ifdef LOG
                        syslog(LOG_NOTICE,
        {
                if (setjmp(CtxReadTimeout) != 0)
                {
 # ifdef LOG
                        syslog(LOG_NOTICE,
-                           "timeout waiting for input from %s\n",
-                           RealHostName? RealHostName: "local");
+                           "timeout waiting for input from %s during %s\n",
+                           CurHostName? CurHostName: "local", during);
 # endif
                        errno = 0;
 # endif
                        errno = 0;
-                       usrerr("451 timeout waiting for input");
+                       usrerr("451 timeout waiting for input during %s",
+                               during);
                        buf[0] = '\0';
                        return (NULL);
                }
                        buf[0] = '\0';
                        return (NULL);
                }
-               ev = setevent((time_t) ReadTimeout, readtimeout, 0);
+               ev = setevent(timeout, readtimeout, 0);
        }
 
        /* try to read */
        }
 
        /* try to read */
@@ -636,8 +760,9 @@ sfgets(buf, siz, fp)
                buf[0] = '\0';
                return (NULL);
        }
                buf[0] = '\0';
                return (NULL);
        }
-       for (p = buf; *p != '\0'; p++)
-               *p &= ~0200;
+       if (SevenBit)
+               for (p = buf; *p != '\0'; p++)
+                       *p &= ~0200;
        return (buf);
 }
 
        return (buf);
 }
 
@@ -655,7 +780,9 @@ readtimeout()
 **             f -- file to read from.
 **
 **     Returns:
 **             f -- file to read from.
 **
 **     Returns:
-**             buf on success, NULL on error or EOF.
+**             input line(s) on success, NULL on error or EOF.
+**             This will normally be buf -- unless the line is too
+**                     long, when it will be xalloc()ed.
 **
 **     Side Effects:
 **             buf gets lines from f, with continuation lines (lines
 **
 **     Side Effects:
 **             buf gets lines from f, with continuation lines (lines
@@ -670,6 +797,7 @@ fgetfolded(buf, n, f)
        FILE *f;
 {
        register char *p = buf;
        FILE *f;
 {
        register char *p = buf;
+       char *bp = buf;
        register int i;
 
        n--;
        register int i;
 
        n--;
@@ -685,8 +813,26 @@ fgetfolded(buf, n, f)
                                i = '\r';
                        }
                }
                                i = '\r';
                        }
                }
-               if (--n > 0)
-                       *p++ = i;
+               if (--n <= 0)
+               {
+                       /* allocate new space */
+                       char *nbp;
+                       int nn;
+
+                       nn = (p - bp);
+                       if (nn < MEMCHUNKSIZE)
+                               nn *= 2;
+                       else
+                               nn += MEMCHUNKSIZE;
+                       nbp = xalloc(nn);
+                       bcopy(bp, nbp, p - bp);
+                       p = &nbp[p - bp];
+                       if (bp != buf)
+                               free(bp);
+                       bp = nbp;
+                       n = nn - (p - bp);
+               }
+               *p++ = i;
                if (i == '\n')
                {
                        LineNumber++;
                if (i == '\n')
                {
                        LineNumber++;
@@ -694,13 +840,13 @@ fgetfolded(buf, n, f)
                        if (i != EOF)
                                (void) ungetc(i, f);
                        if (i != ' ' && i != '\t')
                        if (i != EOF)
                                (void) ungetc(i, f);
                        if (i != ' ' && i != '\t')
-                       {
-                               *--p = '\0';
-                               return (buf);
-                       }
+                               break;
                }
        }
                }
        }
-       return (NULL);
+       if (p == bp)
+               return (NULL);
+       *--p = '\0';
+       return (bp);
 }
 \f/*
 **  CURTIME -- return current time.
 }
 \f/*
 **  CURTIME -- return current time.
@@ -743,7 +889,7 @@ bool
 atobool(s)
        register char *s;
 {
 atobool(s)
        register char *s;
 {
-       if (*s == '\0' || index("tTyY", *s) != NULL)
+       if (*s == '\0' || strchr("tTyY", *s) != NULL)
                return (TRUE);
        return (FALSE);
 }
                return (TRUE);
        return (FALSE);
 }
@@ -850,3 +996,33 @@ bitzerop(map)
                        return (FALSE);
        return (TRUE);
 }
                        return (FALSE);
        return (TRUE);
 }
+\f/*
+**  STRCONTAINEDIN -- tell if one string is contained in another
+**
+**     Parameters:
+**             a -- possible substring.
+**             b -- possible superstring.
+**
+**     Returns:
+**             TRUE if a is contained in b.
+**             FALSE otherwise.
+*/
+
+bool
+strcontainedin(a, b)
+       register char *a;
+       register char *b;
+{
+       int l;
+
+       l = strlen(a);
+       for (;;)
+       {
+               b = strchr(b, a[0]);
+               if (b == NULL)
+                       return FALSE;
+               if (strncmp(a, b, l) == 0)
+                       return TRUE;
+               b++;
+       }
+}
index 6896049..724bde4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 1983 Eric P. Allman
 /*
  * Copyright (c) 1983 Eric P. Allman
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)version.c  5.67 (Berkeley) 5/10/91";
+static char sccsid[] = "@(#)version.c  8.1 (Berkeley) 6/27/93";
 #endif /* not lint */
 
 #endif /* not lint */
 
-char   Version[] = "5.67";
+char   Version[] = "8.1C";